9 th Workshop on Critical Software System ( 2011) TOPPERS/SSP への組込みコンポーネントシステム適用における設計情報の可視化と抽象化 2011.11.17 株式会社ヴィッツ組込制御開発部 TOPPERS TECS-WG 鵜飼敬幸
目次 2 1. 目的 捉える課題 2. コンポーネントシステムについて TECS (TOPPERS Embedded Component System) 他言語との比較 3. コンポーネントシステムの適用 TOPPERS/SSPカーネルへの適用開発工程における有効性ソフトウェア構造の俯瞰における有効性 4. まとめ 今後の取り組み
目的 3 組込みソフトウェアの大規模化に対応する 複雑なソフトウェアの つながり を整理するアプローチ 多分岐 多部品を含むソフトウェア構造へのアプローチ コンポーネントシステムの有効性を確認する TECSを例にUML 等の他言語との違いと利点 フィーチャ バリエーションを包含するソフトウェアの理解性向上 UML TECS
捉える課題 大規模ソフトウェアにおける課題 課題を抱える現場では何が起こっているのか? 機能追加によるコードとリソースの肥大化 初期アーキテクチャのまま時間を理由に歪な継ぎ足しを繰り返す 機能の肥大化がリソースの拡充に直結する 製品バリエーションに対応するコードが混在 条件分岐 マクロスイッチのネストや箇所が膨大で理解性に乏しい 過剰な 変数 関数の複写 が増加の一途を辿る 4 ソフトウェアの保守性 解析性における観点での矛盾 : 新規の仕様追加 変更において修正ポイントが分かりやすい事 問題の発生が生じた場合の原因箇所が特定しやすい事 分かりやすければ改修時の修正時間が理由にはならない 実装機能を必要内に集約できれば理解性低下の抑制に寄不
5 E.C. R&D Dept. コンポーネントシステムについて
コンポーネントシステムについて 6 コンポーネントシステムの前提 ソフトウェアを何らかの部品単位で扱うための仕組み 再利用し易い形 部品で開発する 部品化へのアプローチに用いる技術が重要なキー ソフトウェアの継続的な改善を支援する仕組み ライフサイクルを鑑み 長期的に継続して改善できることが重要 モデルベース開発との協調 ソフトウェアのモデルを記述しプログラムを ( 自動 ) 生成する 人間が行う作業負荷 ( 記述量 ) の削減 モデル化の段階での設計検証 組込みシステムで扱える決定版が存在しなかった 汎用 OSではJavaBeans, CORBA,.NETなど他多数存在 組込み開発で扱える仕組みが登場 (TECS, SaveCCT )
TECS とは 7 TECS (TOPPERS Embedded Component System) 2009 年 5 月にNPO 法人 TOPPERSから一般公開 組込みソフトウェア向けのコンポーネントシステムとして開発 TECS 仕様で規定しているもの TECS 仕様 内容 コンポーネントモデル コンポーネント図 コンポーネント記述言語 TECS CDL コンポーネント実装モデル TECS によるソフトウェア部品の構成と使い方を規定 コンポーネントモデルを図により表現する手段 正確なコンポーネントの定義とコンポーネントを組み合わせてシステムを組み上げる記述言語 TECS コンポーネントを実装し 利用するモデルを定義仕様書に提供されているモデルは一例 本発表のポイント
ロードマップにみる位置づけ 8 大規模化 複雑化 動的オブジェクト生成 新世代カーネルフルセット TECS コンポーネントシステム対応 ASP 新世代カーネル仕様スタンダードプロファイル FMP マルチコアプロセッサ拡張 HRP2 メモリ保護, 時間保護 ASP Safety 機能安全対応 高性能 省エネルギー 省エネルギー制御 信頼性 安全性 SSP 最小セット 適用範囲拡大 2007 2008 2009 2010 2011 2012 リリース前のカーネルの名称は仮称
TECS に関して 9 利用者の想定スキル コンポーネント作成者 利用者 UMLにおけるクラスが設計できる程度のスキルを想定 構造化設計に知見があること 仕様の完成度 2009 年 5 月に Version1 を一般公開 達成機能 : 静的結合, ROM/RAM 出力支援, 最適化, RPC, プラグイン機構 例 ) コンポーネントの呼び出しをシリアル出力によって時系列でトレース可能とするトレースプラグインなど 利用上の注意事項 TOPPERSライセンスに準拠 Windows, Cygwin, OSX 上ので動作を確認 Windowsの実行形式以外の利用はRubyおよびraccが必要
設計領域の位置づけ 10 想定するコンポーネントシステムがカバーする設計領域の範囲 TECS を例として 分析 設計 UML TECS コンポーネント図 実装 C アセンブラ TECS TECS CDL テスト 静的コード解析ツール デバッガ トレースプラグイン
開発の流れ 11 (1)TECS コンポーネント図でソフトウェア構造を表現する 関数の型である (2) シグニチャ記述を行い 部品の型となる (3) セルタイプを記述する 必要な部品の型が揃ったら (4) 組上げ記述を行う これらすべてを (5)TECS CDL を用いて行う (5) の作成物を (6)TECS ジェネレータに通す その結果 対象言語の (10) インタフェースコード (9) ヘッダファイル (8) セルタイプコードのテンプレートが自動生成される セルタイプコードのテンプレートを元に コンポーネント開発者は (11) セルタイプコード (C 言語 ) を記述する インタフェースコードとセルタイプコードを (12) コンパイルし (13) リンクすることで (14) アプリケーションモジュールが完成する コンポーネント仕様開発者 (2) シグニチャ記述 ( インタフェースの定義 )(3) セルタイプ記述 ( コンポーネントの定義 ) (4) 組上げ記述 ( コンポーネントの構成の定義 ) (5) TECS CDL( コンポーネント記述言語 ) (8) テンプレートコード (11) セルタイプコード ( コンポーネントのソースコード ) 設計 コンポーネント開発者 仕様の規定 (6) TECS ジェネレータ (9) ヘッダ (10) インタフェースコード (12)C コンパイラ (13) リンカ (14) アプリケーションモジュール 製品 アプリケーション開発者 設計 (1) コンポーネント図 利用 (7) プラグイン 設計 プラグイン開発者 エンドユーザー RPC アクセス制御 トレース
呼び側 ccall1_func1( ) ccall1_func2( ) 受け側 結合の実装構造の標準形 受け口ディスクリプタ &tb_eent_mt &tb_b_cb 受け口関数テーブル tb_eent_func1_skel tb_eent_func2_skel tb_eent_func3_skel 受け口関数テーブルへのポインタ 受け側のセル CB 受け口スケルトン関数 ER { } tb_eent_func1_skel( struct tag_ssig1_vdes *epd) struct tag_tb_eent_des *lepd = (struct tag_tb_eent_des *)epd; return tb_eent_func1( lepd->idx ); 受け口関数 ta A tb B 12 /* 呼び口関数マクロ ( 短縮形 ) */ #define ccall1_func1( ) ta_ccall1_func1( p_cellcb ) #define ta_ccall1_func1( p_that ) (p_that)->ccall1->vmt-> func1( (p_that)->ccall1 ) 呼び側のセル CB typedef struct tag_ta_cb { /* call port */ struct tag_ssig1_vdes *ccall1; struct tag_ssig2_vdes *ccall2; } ta_cb; ER eent_func1( tb_idx idx) { ER ercd_ = E_OK; tb_cb *p_cellcb; if( tb_valid_idx( idx ) ){ p_cellcb = GET_CELLCB(idx); }else{ return E_ID; } /* 処理 */ return ercd_; }
結合の実装構造の標準形 13 呼び側 受け側 受け口関数テーブル 受け口スケルトン関数 ccall1_func1( ) ccall1_func2( ) 受け口ディスクリプタ &tb_eent_mt &tb_b_cb tb_eent_func1_skel tb_eent_func2_skel tb_eent_func3_skel 受け口関数テーブルへのポインタ 受け側のセル CB ER { } tb_eent_func1_skel( struct tag_ssig1_vdes *epd) struct tag_tb_eent_des *lepd = (struct tag_tb_eent_des *)epd; return tb_eent_func1( lepd->idx ); 受け口関数 /* 呼び口関数マクロ ( 短縮形 ) */ #define ccall1_func1( ) ta_ccall1_func1( p_cellcb ) #define ta_ccall1_func1( p_that ) (p_that)->ccall1->vmt-> func1( (p_that)->ccall1 ) 呼び側のセル CB typedef struct tag_ta_cb { /* call port */ struct tag_ssig1_vdes *ccall1; struct tag_ssig2_vdes *ccall2; } ta_cb; ER eent_func1( tb_idx idx) { ER ercd_ = E_OK; tb_cb *p_cellcb; if( tb_valid_idx( idx ) ){ p_cellcb = GET_CELLCB(idx); }else{ return E_ID; } /* 処理 */ return ercd_; }
他言語との比較 14 統一モデリング言語 (UML) との比較 TECS コンポーネント図 オブジェクト図 ( 実体の関連 ) に相当 コンポーネントの型 = セルタイプは TECS の概念 コンポーネントの結線は操作可能な関数束を表す コンポーネント図では関連の存在に加えて 関数テーブル ( シグニチャ ) と関連方向 ( 呼び口 受け口 ) を確定する UML の関連は集約や多重度, 依存などの存在を表現できる 関連 クラス図 :UML 関連 オブジェクト図 :UML tcell Cell1 呼び口 ccallport 受け口 eentryport シグニチャ soperation コンポーネント図 :TECS tcell Cell2
UML との比較 15 UML TECS 備考 クラス セルタイプ TECSではコンポーネントの型を意味する セルタイプ同士の関連を表す関連図はない オブジェクト セル TECSではコンポーネントの型の実体を指す オブジェクト図に対してTECSコンポーネント図を用いる クラス内関数 シグニチャ TECSでは関連線が関数テーブルを指し 名前をもつ また呼びだし側 : 呼び口, 呼ばれ側 : 受け口の名前をもつ UMLは矢印も可能 シグニチャは必ず方向の指定を伴う アクセス指定子なし C 言語の機能に併せアクセス指定子と記号はない 継承 派生なしシグニチャを踏襲することで機能の継承は可能 tcell Cell1 呼び口 ccallport 受け口 eentryport シグニチャ soperation tcell Cell2 セルタイプ名 セル名 コンポーネント図 :TECS 受け口にはセル内部に矢印を表記する
他言語との比較 16 C++(Java) 言語との比較 継承 派生の関係, アクセス指定子は規定しない オブジェクト指向のプログラム言語に依存してしまう TECSではUMLのクラスの 操作 が独立した情報 C 言語で扱える点がTECSの特徴 class CApp { クラス private: int m_att1; public: int Ope1(int arg1); }; CApp.h(.hpp) クラス宣言 (C++) signature soperation { シグニチャ uint32_t Ope1( [in] int32_t arg1 ); }; celltype tcell { セルタイプ call soperation ccallport; 呼び口 entry soperatoin eentryport; 受け口 attr { int32_t attr1 = 10000; }; var { uint32_t var1; }; }; tcell.cdl ( コンポーネント記述ファイル ) シグニチャ宣言とセルタイプ宣言 (TECS)
C++(Java) との比較 17 signature soperation { シグニチャ uint32_t Ope1( [in] uint32_t arg1 ); }; celltype tcell { セルタイプ call soperation ccallport; 呼び口 entry soperatoin eentryport; 受け口 attr { uint32_t attr1 = 10000; }; var { uint32_t var1; }; }; tcell.cdl ( コンポーネント記述ファイル ) シグニチャ宣言とセルタイプ宣言 cell tcell Cell1 { ccallport = Cell2.eEntryPort; var1 = 1; }; cell tcell Cell2 { var1 = 2; }; Main.cdl( コンポーネント記述ファイル ) セル宣言と全体の組上げ 構文 call entry tcell Cell1 意味 呼び口 受け口 呼び口 ccallport 受け口 eentryport シグニチャ soperation コンポーネント図 tcell Cell2 attr 定数 (celltype 宣言時に初期化要 ) var コンポーネント内変数
C++(Java) 言語との比較 18 3 段階の出力手順を経る TECSはコンポーネントの情報をエンティティ化 独立した情報 CDLファイルの内容が設計情報の丌足を補完する コンポーネント構成 結合情報を文章から言語記述へ オブジェクト指向における設計フロー TECS の設計フロー
19 E.C. R&D Dept. コンポーネントシステムの適用
コンポーネントシステムの適用方針 20 TOPPERS/SSP カーネルへコンポーネントシステムを適用 カーネル本体に手を加えずラッパーとしてコンポーネント化する 動作の上位互換を確保する TOPPERS/SSP カーネルのサンプルが TOPPERS/ASP カーネルでも動作できるよう, 拡張パッケージの導入を前提とする TOPPERS/SSP カーネル ( 以降 SSP と呼ぶ ) TOPPERS Smallest Set Profile Kernel uitron4.0 仕様の 仕様準拠の最低限の条件 をベースとする小規模リアルタイムカーネル : 拡張パッケージの導入で ASP と上位互換 2011 年 6 月 10 日会員早期リリース TOPPERS/ASP カーネル ( 以降 ASP と呼ぶ ) TOPPERS Advanced Standard Profile Kernel uitron4.0 仕様のスタンダードプロファイル準拠のリアルタイムカーネル 2006 年より一般公開中
コンポーネント全体像 21 TOPPERS/SSP カーネルに対応するコンポーネント化 ASP 対応版を基に SSP 版との共通化を検討した コンポーネント記述は SSP/ASP 共通セルで全て同じ サービスの機能単位でコンポーネント化した 組み合わせによりセルを新設 周期タスク等を複合セルによりコンポーネント化 複合コンポーネントについては本発表では触れない teventflag tdataqueue tprioritydataqueue tsemaphore tfixedsizememorypool tisr ttask tkernel SSP カーネル tcyclichandler tcyclictask tcyclictaskactivator talarmhandler tkernel ttask tisr tterminateroutine ASP 対応セル 拡張パッケージ対応セル tconfiginterrupt tisrwithconfiginterrupt tinitializeroutine SSP/ASP 共通セル TOPPERS/SSP コンポーネント全体像 SSP 仕様 カーネルに対応したセル同士のコンポーネント間の結合は 既存コードをラップする手段としたため アプリケーションを実装した際に出現する ( 図は結合のイメージ )
コンポーネント全体像 22 SSP シリアル出力サンプルプログラムへの適応 シリアル接続のターミナルから入力文字を待機 入力文字に応じて タスクの起動, 終了,CPU 例外発生を行う ttask InitTask tcyclichandler CyclicHandler ttask MainTask tsample1 Sample1 tkernel SSPKernel ttask Task tserial Serial 2 重線は能動的に動作するアクティブセル サンプルプログラム TECS コンポーネント図
適用結果 23 コンポーネント化の恩恵を確認 コンポーネントのオーバーヘッドを小さく抑えられる SSP のような小さなカーネルでも利用を検討できる C++ のようなオブジェクト指向的な概念を これまで組込開発に持ち込めなかった点の打開策になり得る 文字送信における比較 1 文字 5 文字 コンポーネント ( 最適化なし ) 31.27us 69.16us コンポーネント ( 最適化あり ) 29.16us 64.18us 非コンポーネント 29.15us 63.47us 非コンポーネント ( インライン ) 27.00us 61.59us SH3 (96MHz の例 ) メモリ消費における比較 text data bss rodata total コンポーネント ( 最適化なし ) 3,632 100 512 190 4,436 コンポーネント ( 最適化あり ) 3,120 100 512 88 3,820 非コンポーネント 3,632 0 568 100 4,300
コンポーネントシステム適用工程 24 ASP 対応版を基としたので (1) コンポーネント図の組み替え以外 (4) 組上げ記述によるコンポーネント結合まで 修正作業が発生しない コンポーネント自体は ASP 版そのもの (6)TECS ジェネレータにより (9) ヘッダ (10) インタフェースコードが自動で出力される (11) セルタイプコードを SSP に併せて実装する ASP の仕様にのみ存在する機能の関数コードを削除する ASP のみに使用するコードを (13) リンカの対象から除外する コンポーネント図 ( 組み替え ) 以外は C 言語のコンポーネントコード実装と リンク対象の変更のみ ソフトウェアのアーキテクチャ設計を コーディング工程まで揺らぎなく引き継いでいるから簡略化可能である コンポーネント仕様開発者 (2) シグニチャ記述 ( インタフェースの定義 )(3) セルタイプ記述 ( コンポーネントの定義 ) (4) 組上げ記述 ( コンポーネントの構成の定義 ) (5) TECS CDL( コンポーネント記述言語 ) (8) テンプレートコード (11) セルタイプコード ( コンポーネントのソースコード ) 設計 コンポーネント開発者 仕様の規定 (6) TECS ジェネレータ (9) ヘッダ (10) インタフェースコード (12)C コンパイラ (13) リンカ (14) アプリケーションモジュール 製品 アプリケーション開発者 設計 (1) コンポーネント図 利用 (7) プラグイン 設計 プラグイン開発者 エンドユーザー RPC アクセス制御 トレース
適用における考察 25 コンポーネントの適用における考察 文章による設計内容には多分に曖昧さを含んでいる 文章でもガイドワードなど表記ルールを適用することで曖昧さ抑制できるが? 形式化した記述を制約に課しているのと同じ ( ある種のプログラム言語 ) 人間の読解の手間が必要 読解の過程でミスの混入リスクがある 下位工程は文章から想像力を働かせて元の設計を復元する努力をしていた コンポーネントシステムは曖昧性の排除を行っている 文章による補完では ソフトウェア構造設計を方式設計工程で行うのではなく 実はより下位の工程で行うのと同義 完全一致する事の方が難しい アーキテクトの最終イメージ 構造一致 文章曖昧さを含む ドキュメント記述 アーキテクト ダイアグラム記述 ソフトウェア構造設計 詳細設計担当プログラマ コンポーネントシステム
適用結果 26 人間によるプログラム記述量の減尐 コンポーネントアーキテクチャの記述が丌要 コンポーネント間のグルーコードまで自動生成 コーディング工程ではコンポーネント内のローカル関数や シグニチャで定義した関数の実装に専念可能 記述量非依存部依存部グルー CDL total コンポーネント 456 185 0 125 766 非コンポーネント 549 278 119 0 946 ASP カーネルの計数値
開発工程における有効性 27 開発工程で俯瞰してみると コンポーネント結合コンポーネント記述統一された結合規則 出典 :SEC 組込みソフトウェア向け開発プロセスガイド マクロスイッチ条件分岐コメントによる設計情報 ( 曖昧さを含む ) コンポーネント結合はソフトウェア設計に影響 詳細設計あるいは実装工程で補完を行っていた構造設計を方式設計工程へ戻す 数段階抽象化している ソフトウェアアーキテクトの意識との乖離を抑止する
ソフトウェア構造の俯瞰における有効性 開発ターゲットの違い バリエーションの検討 例えば機能性は同じで性能が異なる部品を実装する 28 #ifdef Target1 Switch (Target ) { case Target1: baudrate = 9600; #else テキストから図へ 解析性の向上更なるメリットとして省 ROM/RAM 化処理時間の最適化 ttask InitTask ttask MainTask ttask InitTask ttask Task ttask MainTask tsample1 tcyclichan tkernel Sample1 dler SSPKernel CyclicHan dler tsample1 Sample1 C 言語のマクロや条件分岐を使った実装の場合 判定条件の数値の理解が必要になる ( ドキュメントやコメントを読む ) 出現箇所が多種多数に及ぶ場合の解析性低下は著しい ttask Task tcyclichan dler CyclicHan dler tserial Serial1 tserial Serial2 tkernel SSPKernel cell tserial Serial1 { baudrate = 9600; channel = 1; }; cell tserial Serial2 { baudrate = 4800; channel = 2; }; コンポーネント図 記述から対象ソースコードは一意に特定 条件分岐の抑制や余剰コードの排除で ROM/RAM の節約や 処理時間の最適化というメリットを享受することもできる
ソフトウェア構造の俯瞰における有効性 フィーチャの違い プロダクトライン的構想の検討 例えば仕向けの違いで必要な部品 ( 構成 ) を切り替える 29 Switch (Target ) { case Target1: SendSerial(); break; case Target2: SendCAN(); テキストから図へ 構成の一意の特定視覚化による理解性向上 ttask InitTask ttask MainTask ttask InitTask ttask Task ttask MainTask tsample1 tcyclichan tkernel Sample1 dler SSPKernel CyclicHan dler tsample1 Sample1 ソースコード内に全ての機能を残しておくアプローチでは ttask Task tcyclichan dler CyclicHan dler tserial Serial1 tcan CAN1 tkernel SSPKernel cell tserial Serial1 { baudrate = 9600; channel = 1; }; cell tcan CAN1 { baudrate = BD5K; channel = 2; }; 場合によっては余剰コード自体を取り去ることで品質要件に変化が出る事がリスクとなってしまう ハード拡充に始まるデメリットが顕在化 コンポーネントシステムは図から結合情報を自動で補完する コンポーネント図からコンポーネント記述へ統一された規則によって完全に書き下せるからこそ可能となる
30 E.C. R&D Dept. まとめ 今後の取り組み
まとめ 条件分岐やマクロによる実行コードの切り替えを用いたバリーエーションを実現するような複雑なソフトウェア構造を 解析性に貢献しつつ管理する手法を示した 31 機能の異なるソフトウェア部品の組み合わせによるフィーチャやプロダクトライン対象部品の管理手法を示した C 言語を用いた組込みソフトウェア開発において ソフトウェアモデルからソースコードを自動生成する手法を用いて アーキテクチャ設計を上位工程へ抽象化する具体的な方法を示した
今後の取り組み 32 形式記述との連携 先に紹介したプラグイン機構を用いて 形式記述の仕組みと連携する試み ハードウェア / ソフトウェア間の協調設計 FPGA などの再構成可能なハードウェアと ソフトウェアとの役割分担を制御する試み 互換性を確保した記述の拡張 上下位互換性の検討 バイナリ流通や動的結合に対応する備えとして
参考文献 33 1. OMG: CORBA Component Model 4.0, http://www.omg.org/technology/documents/formal/components.htm. 2. Microsoft Corporation:.NET Framework Conceptual Overview, http://msdn.microsoft.com/en-us/library/zw4w595w.aspx. 3. ORACLE: Enterprise JavaBeans Technology, http://www.oracle.com/us/products/tools/ejb-141389.html. 4. NPO 法人 TOPPERSプロジェクト : TOPPERS/SSPカーネル, https://www.toppers.jp/members.html#early. 5. NPO 法人 TOPPERSプロジェクト : TOPPERS/ASPカーネル, https://www.toppers.jp/asp-kernel.html. 6. OMG: Unified Modeling Language (UML), http://www.omg.org/spec/uml
34 E.C. R&D Dept. ありがとうございました 発表にあたり協力頂いた TOPPERS TECS-WGの皆さまに感謝致します