以下、図面を参照して、本発明の一実施例の構成及び処理を説明する。以下の記述では、特に断わらない限り、図面に亘って、同一の要素は同一の符号で参照されるものとする。なお、ここで説明する構成と処理は、一実施例として説明するものであり、本発明の技術的範囲をこの実施例に限定して解釈する意図はないことを理解されたい。
本発明を実現するための構成を説明する前に、その前提として、ECUについて説明する。ECUは、一般的に、センサからの入力信号を、例えばA/D変換する入力インターフェースと、決められた論理に従ってディジタル入力信号を処理する論理演算部(マイクロコンピュータ)と、その処理結果を、アクチュエータ作動信号に変換する出力インターフェースとから構成されるものである。
この発明は、説明の便宜上、以下では、自動車のECUに関連して説明するが、それには限定されず、航空機、ロボットなどその他のECUをもつメカトロニクス機構全般に適用可能であることを理解されたい。
ECUは、周辺や環境状態、エンジンなどの駆動機構の状態、及び人間による指示操作の内容をセンサで検出して、信号として入力する。具体的には、水温センサ、吸気温センサ、過給圧センサ、ポンプ角センサ、クランク角センサ、車速センサ、アクセル位置センサ、A/Tシフト・ポジション、スタータ・スイッチ、エアコンECUなどからの信号がある。
ECUは、これらの信号を入力して、電磁スピル弁、フュエル・カット・ソレノイド、タイミング・コントロール・バルブ、吸気絞りVSV、グロー・プラグ・リレー、タコメータ及びエアコン・リレーなどを駆動する信号を出力しする。
1つのECUが複数の異なる機構を制御するための駆動信号を出力するようにすることは不可能ではないが、例えば、エンジンとエアコンのように、応答性やその制御の厳密性が異なるものを単一のECUで制御することは合理的でなく、従って、一般的に自動車にECUは複数個設けられる。
図1は、ECUの典型的な制御である、フィードバック閉ループ系の例を示す図である。すなわち、図1において、ある目標の信号が、ECUであるコントローラ102に入力され、ECUは、目標の信号を内部処理することによって、駆動信号を出力し、制御対象モデルである、エンジンなどのプラント104を駆動し、プラント104の出力は、センサ106を介して、コントローラ102の入力にフィードバックされる。
ここで目標信号として与えられるのは、例えば、スロットル開度、アイドル・コントロール、ブレーキ力、シフト、スタータON・OFF、バッテリ電圧、インジェクション通電時間、インジェクション通電回数、デポジット、ドウェル角、進角値、吸気完了フラグ、点火完了フラグ、大気圧、車両重量、転がり抵抗係数、道路勾配、粘着係数、吸気温、などのパラメータである。
また、センサ信号としてフィードバックされるのは、スロットル開度、吸気圧力、吸入空気量、シフト、エンジン回転数、車速、排気温、O2、冷却水温、空燃比、ノック、点火異常、などである。
ECUが制御する対象は、ニュートンの力学方程式で解かれる、機構系システムであったり、電気回路の応答方程式で解かれる、電気駆動回路であったり、それらの組み合わせであったりする。これらは、基本的に微分方程式であり、制御工学によれば、ラプラス変換によって応答関数に変換されて、記述することができる。
図2は、そのような応答関数による記述の例である。図2で破線202で囲った箇所が、図1のコントローラ102に対応し、破線204で囲った箇所が、図1の制御対象モデル104に対応し、センサ106が、ブロック206に対応する。なお、図2は、応答関数による表現の一例であって、特に本発明を限定する意図はないことを理解されたい。
さて、例えば、ECUが制御する対象が、ニュートンの力学方程式で解かれる、機構系システムであるとする。すると、ある時点のECUの制御出力は、その機構系システムの可動部分の位置及び速度という内部状態変数をもち、その時点の入力だけでは決まらない。そのことは、電気回路にもあてはまり、電気回路のキャパシタに残っている電荷の量や、コイルのインダクタンスによる磁力などの内部状態変数が、やはり存在する。
従って、ECUは、図3に示すように、入力uに対して、その内部状態xを勘案した値yを出力することになる。
さて、前述したSILSのようなテストの目的で、自動車部品メーカーは、自社が提供する機器のECUのソフトウェア・エミュレータを提供する。すなわち、図2に示すような機能を、アセンブラまたはCなどの言語が書かれたコードをアセンブリまたはコンパイルした実行可能プログラムにより、純粋にソフトウェア的に実現する。
本発明のこの実施例では、ECUのソフトウェア・エミュレータの内部状態を取り出して利用する。ソフトウェア・エミュレータによっては、内部状態が取り出し可能である場合と、そのままでは、内部状態が取り出し可能でない場合がある。
そこで、ECUのソフトウェア・エミュレータの内部状態がそのままでは、内部状態が取り出し可能でない場合、ソースコード解析ツールによって、次のような処理を行う。
もし、ECUのソフトウェア・エミュレータのソースコードが入手可能であるならそれをそのまま利用し、実行可能バイナリ・ファイルしかなければ、所定のツールで、逆アセンブルまたは逆コンパイルする。そうして、ECUのソフトウェア・エミュレータのソースコードに対して、データーフロー解析という技法を適用して、ソースコードを基本ブロックに分割する。基本ブロックとは、ソースコードを、複数の制御が合流するところ、または、制御が複数に分岐するところで分断した、各々の部分のことである。このような基本ブロックをノードとして、その分岐の制御の流れのリンクで接続すると、有向グラフ構造になる。これは特に、制御フローグラフとも呼ばれる。制御フローグラフは、始点ノードと終点ノードをもち、プログラムで実行され得るノードは全て、始点ノードからの有効エッジをもつ。基本ブロックのうち、exit()やreturnなどのステートメントを含む制御の末端ノードは全て、終点ノードへの有効エッジをもつ。
次に、制御フローグラフの始点ノードと終点ノードの可能な全てのパスに対して、Use/Def解析を行う。ここで、Useとは、ある変数が、別の変数に値をストアするために使用される場合をいう。典型的には、代入式の右辺である。Defとは、ある変数に、値がストアされる場合をいう。典型的には、代入式の左辺である。
この場合、個々のパス毎に、Defの前あるいは、DefなしでUseされている変数、すなわち未定義参照変数があるかどうかがチェックされ、もし未定義参照変数があると、その変数名は一旦保存される。
こうして、全てのパスがスキャンされた後に保存されている変数名を用いて、後述するように、ラッパ(wrapper)コードが生成される。
ところで、実行フローのスキャンと、Use/Def解析は、データーフロー解析という技法を用いることによって、より効率的に実行することができるので、以下、それについて説明する。
その第1ステップは、各基本ブロックにおけるdefリストの計算である。具体的にはプログラム全体で使用される変数のリストを1ビットで表現し、各基本ブロックごとに定義される変数を1されないものを0としたビットベクタで表現する。
その第2ステップは、プログラム全体の到達可能なdefリストの計算である。すなわち、各基本ブロックでは、複数の入力がある場合には論理積(AND)してから,自身への入力とする。自身からの出力は、その入力と、自身で定義したdefリストの論理和(OR)をとり、後続の基本ブロックに渡す。実行していく順番は、制御フローグラフ上での深さ優先順序が効率的である。
第3ステップは、クロージャ解析アルゴリズムにより、到達可能なdefリストのクロージャを求めることである。そして、上記第2ステップを、全ての基本ブロックの出力defリストが変化しなくなるまで、繰り返す。ここで、クロージャとは、環境と結び付けられた値のことである。
第4ステップは、未定義変数の使用の発見である。すなわち、各基本ブロックの入力defリストが0として表現された変数が、useとして使用されているものを検出する。
なお、データフロー解析のより詳しい説明については、Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman, "Compilers Principles, Technologies, and Tools", Addison-Wesley Publishing Company, 1986, p. 608-633などを参照されたい。
さて、例えば、元のECUシミュレーション・ソースコードが、関数 Func(x,y,z) であらわされるとする。また、未定義参照変数として、a, bが登録されていたとする。
すると、例えば、_Func(x,y,z,_a,_b)という関数が用意され、
_Func(x,y,z,_a,_b)
{
a = _a;
b = _b;
Func(x,y,z);
_a = a;
_b = b;
return;
}
_Func(x,y,z,_a,_b)
{
a = _a;
b = _b;
の部分のところを、入力用ラッパコードと呼び、
_a = a;
_b = b;
return;
}
の部分のところを、出力用ラッパコードと呼ぶ。
なお、 Func(x,y,z); のところは、関数呼び出しではなく、インライン展開でもよい。このような関数_Func(x,y,z,_a,_b)を、_a,_bに適当な値を入れて呼び出すことにより、Func(x,y,z)の内部状態をセットすることができ、また、_Func(x,y,z,_a,_b)を呼び出した結果、_a,_bに、処理後の内部状態の値がセットされるので、必要に応じて、それらの値を別途保存するなど、利用可能である。このようにラッパコードが付されたソースコードは、実行可能プログラムを生成するために、コンパイルまたはアセンブルされる。
また、C++など、特定の処理言語の仕様によっては、_Func(x,y,z,_a,_b)でなく、_Func(x,y,z,&_a,&_b)のように、参照演算子&をつけて関数に引数として与える必要があることもある。
こうして、内部状態あるいは、内部変数を取り出すことができるようになった後のECUのソフトウェア・エミュレータを図式的に、図4に示す。そこに示すように、ECUのソフトウェア・エミュレータ402は、内部ロジックfを示す部分と、内部状態または状態変数xとに好都合に分離される。
すると、内部ロジックfを用いて、出力y = f(t,x,u, ...) と記述することができる。ここでtは、時間である。また、状態変数xに係るコードが分離されたことによって、任意の時点、すなわち典型的には出力がなされるタイミングで、状態変数xと、好ましくは入力uも、状態リポジトリ404として、ハードディスクドライブに書き出すことができる。
状態変数xに係るコードを分離した効果はこれだけではない。すなわち、矢印406で示すように、ソフトウェア・エミュレータ402には、任意の時点で、状態変数xをセットすることができる。これによって、状態リポジトリ404から入力と状態変数xを選んでセットすることにより、ECUのソフトウェア・エミュレータ402を、その状態変数xが状態リポジトリ404に書き出された任意の時点の状態に戻して、そこから計算をやり直させることができる。
以上説明したような処理は、ECUだけでなく、物理装置シミュレータも含む論理プロセス全般に適用することが可能である。従って、以下では、論理プロセスを、内部状態変数を取り出し可能で、且つ内部状態変数を所望の値にセット可能であるものとして扱う。
次に、図5を参照して、本発明を実施するために使用されるコンピュータのハードウェアについて説明する。図5において、ホスト・バス502には、複数のCPU0 504a、CPU1 504b、CPU2 504c、CPU3 504dが接続されている。ホスト・バス502にはさらに、CPU0 504a、CPU1 504b、CPU2 504c、CPU3 504dの演算処理のためのメイン・メモリ506が接続されている。
一方、I/Oバス508には、キーボード510、マウス512、ディスプレイ514及びハードティスク・ドライブ516が接続されている。I/Oバス508は、I/Oブリッジ518を介して、ホスト・バス502に接続されている。キーボード510及びマウス512は、オペレータが、コマンドを打ち込んだり、メニューをクリックするなどして、操作するために使用される。ディスプレイ514は、必要に応じて、後述する本発明に係るプログラムをGUIで操作するためのメニューを表示するために使用される。
この目的のために使用される好適なコンピュータ・システムのハードウェアとして、IBM(R)System Xがある。その際、CPU0 504a、CPU1 504b、CPU2 504c、CPU3 504dは、例えば、インテル(R)Core 2 DUOであり、オペレーティング・システムは、Windows(商標)Server 2003である。オペレーティング・システムは、ハードティスク・ドライブ516に格納され、コンピュータ・システムの起動時に、ハードティスク・ドライブ516からメイン・メモリ506に読み込まれる。
なお、本発明を実施するために使用可能なコンピュータ・システムのハードウェアは、IBM(R)System Xに限定されず、本発明のシミュレーション・プログラムを走らせることができるものであれば、任意のコンピュータ・システムを使用することができる。オペレーティング・システムも、Windows(R)に限定されず、Linux(R)、Mac OS(R)など、任意のオペレーティング・システムを使用することができる。さらに、ECUエミュレータ・プログラム、物理装置シミュレータなどの論理プロセスを高速で動作させるために、POWER(商標)6ベースで、オペレーティング・システムがAIX(商標)のIBM(R)System Pなどのコンピュータ・システムを使用してもよい。
ハードディスク・ドライブ516にはさらに、ECUエミュレータ、物理装置シミュレータなどの複数の論理プロセス、及び、複数の論理プロセスを協働して動作させるためのプログラムが格納され、キーボード510及びマウス512によって起動操作可能である。
好適には、フルビークルSILSを実現するために、1台の自動車で使われるすべてのECUのエミュレータ・プログラムが、ハードティスク・ドライブ516に保存されている。そのECUのエミュレータ・プログラムが、そのままでは内部の状態変数を取り出せないものてある場合は、上述したラッパコードを被せることにより、予め、状態変数をセット及び取り出し可能としておくものとする。
ハードティスク・ドライブ516にはさらに、後述するECUエミュレータ・プログラムのためのスケジューラ、エンジン、トランスミッション、ステアリング、ワイパなどの物理装置(プラント)シミュレータ・プログラム、全体のシステムの時刻を管理するためのグローバル・タイム・マネジャ及び、登り坂道、高速道路、つづら折道などの様々な、テストのためのシナリオを格納したシナリオ・ジェネレータのプログラムも格納されている。
なお、ここでの「エミュレータ」と、「シミュレータ」の用語の使い分けであるが、もともとの、別のプロセッサで動くことを想定して書かれていたECUのコードを、CPU0〜CPU3などをターゲットとして動くようにすることを、エミュレーションと呼び、それを行うプログラムを、エミュレータと呼ぶ。一方、エンジンなどの物理的システムの動作を仮想計算するシステムを、シミュレータと呼ぶ。
次に、図6を参照して、本発明のシミュレーション・システムの機能論理ブロック図を説明する。図6において、共有メモリ602は、実際は、図5に示すメイン・メモリ506の一部であってよい。共有メモリ602には、ECUエミュレータ・プログラム604a、604b、・・・604nが、アダプタプロック606を介して接続されている。
アダプタプロック606は、本発明に従い、連続系シミュレータ(図6では、物理装置シミュレータ608)と、離散系シミュレータ(図6では、ECUエミュレータ604)の間で、履歴を記録して離散系シミュレータが正しくロールバックできるようにする機能を提供するものであり、その詳細は、図7以下を参照して後述する。
共有メモリ602にはさらに、物理装置シミュレータ・プログラム608a、・・・608mと、グローバル・タイム・マネジャ610が、論理的に結合されている。
グローバル・タイム・マネジャ610は、ECUエミュレータ・プログラム604a、604b、・・・604n及び物理装置シミュレータ・プログラム608a、・・・608mの間のイベントのタイム・スタンプに基づき、それらのイベントの間の一貫性を維持するように動作する。グローバル・タイム・マネジャ610のより詳しい動作は、後述する。
ECUのエミュレータ・プログラム604a、604b、・・・604nは、それぞれ、エンジン、ブレーキ、トランスミッション、ステアリングなど、車の異なる部分の制御に対応するもので、それぞれが異なる速度のクロックで動作するので、対応するECUのエミュレータ・プログラムも、それに比例するクロック比で動作するものとする。
一例として、スレッドを作成いることにより、複数のCPUに、ECUのエミュレータ・プログラムを割り当てるコードを、C言語を例にとって示す。
void* ecu_wrapper(void* parm)
{
...
/* define state_repository */
...
LOOP_BEGIN:
...
/* ECUのユニット処理を行う */
LOOP_END:
...
}
上記のようなコードを用意しておいて、
pthread_t thread_id;
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_create(&thread_id, thread_attr, ecu_wrapper, NULL);
pthread_attr_destroy(&thread_attr);
とすると、オペレーティング・システムがスレッドを生成して、それをECUのエミュレータ・プログラムに割り当てる。物理的には、そのスレッドは、CPU0〜CPU3のどれかに割り当てられるが、それはオペレーティング・システムに任され、エミュレータ・プログラムにとっては、透過的である。
このような割り当て処理は、ECUエミュレータ・プログラム604a、604b、・・・604n各々に個別に行われる。
なお、図6に示した論理構成では、ECUエミュレータ・プログラム604a、604b、・・・604n、物理装置シミュレータ・プログラム606a、・・・606m、アダプタブロック606、及びグローバル・タイム・マネジャ610は、共有メモリ602を使用してデータを交換するが、代わりに、CAN(controller area network)エミュレータを使用してもよい。
図示しないが、図6の構成には、登り坂道、高速道路、つづら折道などの様々な、テストのためのシナリオを格納したシナリオ・ジェネレータも接続される。
なお、図6では、単一のアダプタブロック606が、複数のECUエミュレータ・プログラム604a、604b、・・・604nをカバーするように示されているが、これは一実施例にすぎず、ECUエミュレータ・プログラム毎にアダプタブロックを設けるようにしてもよい。
図7は、図6のアダプタブロック606の機能ブロックを示す図である。図7において、エッジ通知ブロック702は、連続系シミュレータ608からパルスを受け取る度に、パルス・テーブル704に、時刻及び、各入力テーブルでのパルス値を記録する。またパルスのエッジを検出する度に、エッジ・テーブル706に、時刻、入力ポート、エッジのタイプ(立上がりか、立下がりか)を記録し、ECUエミュレータ604のペリフェラル612に通知する。
ヒストリ・マネジャ708は、ペリフェラル612から割込み応答がある度毎に、割込み応答リスト710にその時刻を記録し、グローバル・タイム・マネジャ610に、タイム・スタンプとして通知する。一方、グローバル・タイム・マネジャ610から、確定時刻を受け取る。
割込み応答時間リスト710は、離散系シミュレータ(ごの場合、ECUエミュレータ604)からの割込み応答の時刻の履歴を保持する。ECUエミュレータ604は、そこに保持されている時刻にロールバックすることが可能である。
入力スケジューラ712は、各タイムスライスでアダプタブロック606に入力される変数の値を、入力変数テーブル714に書き込んだり、入力変数テーブル714のエントリと、読取り要求テーブル716のエントリを対比して、ロールバックが必要かどうかの判断をしたりする。
入力変数テーブル714は、アダプタブロック606に入力される変数の値の履歴を保持する。入力変数テーブル714には、各タイムスライス毎に入力があるが、値が変化した時の時刻と値を、エントリとしてもつ。変数が複数ある場合は、変数の数だけ、入力変数テーブルをもつ。この実施例では、入力変数テーブル714には、最終入力時間のフィールドも併せて保持されている。しかし、これは一実施例であって、最終入力時間のフィールドだけを独立に保持してもよい。
読取り要求テーブル716は、離散系シミュレータからの変数の読込要求の履歴を保持する。読取り要求テーブル716は、変数の読込要求の時刻、返答に使った値と、返答済みか否かのフラグをエントリとしてもつ。このとき、アダプタブロック606がまだ実行していない時刻での要求は未応答とし、返答済みフラグを、falseとする。変数が複数ある場合は、変数の数だけ、読取り要求テーブルをもつ。
変数アクセス・インターフェース718は、離散系シミュレータからの変数の読み書きイベントを処理する。読込みに関しては、入力変数テーブル714の値を参照し、読込みの履歴を、読取り要求テーブル716に記録する。書込みに関しては、出力変数テーブル720に値を記録し、必要に応じて出力スケジュール時間722を変更する。
出力スケジューラ724は、各タイムスライスで、アダプタブロック606から出力される変数の値を、出力変数テーブル720を参照して決めたり、出力スケジュール時間722を参照して、どの時刻からの出力が必要かを判断し、あるいは実際に出力する。
出力変数テーブル720は、離散系シミュレータからの変数の書込みの履歴を保持する。出力変数テーブル720は、変数の書込みの時刻と、その際の値をエントリとしてもつ。アダプタブロックは、出力変数テーブルをみて、毎タイムスライスでの変数の出力値を決める。変数が複数ある場合は、変数の数だけ、出力変数テーブルをもつ。
出力スケジュール時間722は、アダプタブロック606の次のタイムスライス実行時に変数を出力すべき最初の時刻を保持する。アダプタブロックは、変数出力処理時に、この時刻からそのタイムスライスでの時刻までの各タイムステップでの出力を行う。なお、パルス・テーブル704、エッジ・テーブル706、割込み応答時間リスト710、入力変数テーブル714、読取り要求テーブル716、出力スケジュール時間722のフィールド、及び出力変数テーブル720は、好適には、メイン・メモリ506の所定領域に確保されるが、ハードディスク・ドライブ516に確保するようにしてもよい。
図8は、本発明に係る処理の概要フローチャートを示す図である。先ず、ステップ802では、エッジ検出を含む、パルス入力の処理が行われる。この処理は、図9のフローチャートを参照して、後で詳細に説明する。
ステップ804では、変数入力の処理が行われる。この処理は、図10のフローチャートを参照して、後で詳細に説明する。
ステップ806では、離散系シミュレータのロールバックが必要かどうかが判断される。この判断は、実際は、ロールバックフラグがセットされているかどうかに基づき、行われる。ロールバックフラグについては、後で、図9及び図10のフローチャートに関連して説明される。
ステップ806で、ロールバックフラグがセットされているなら、ステップ808に進み、そこで、離散系シミュレータをロールバックさせる処理が行われる。この処理は、図13のフローチャートを参照して、後で詳細に説明する。
ステップ810では、変数出力の処理が行われる。この処理は、図11のフローチャートを参照して、後で詳細に説明する。
次に、図9を参照して、図8のステップ802に対応する、パルス入力の処理について、説明する。図9のステップ902で、アダプタブロック606が、今のタイムスライスtのパルス入力の値を取得する。
ステップ904では、パルス・テーブル704に既に、時刻tのエントリが存在するかどうかが判断される。もしそうなら、ステップ906に進み、そこで、そのエントリと今回の入力で、パルスの値が異なっているかどうかが判断される。
もし、そのエントリと今回の入力で、パルスの値が同じなら、特に何もしないで、パルス入力の処理が完了する。
もし、そのエントリと今回の入力で、パルスの値が異なっているなら、ステップ907でエッジ・テーブル706の時刻t以降のエントリを削除してから、ステップ908に進み、そこで、パルス・テーブル704に、時刻tのエントリが、今回の値で上書き記録される。そして、ステップ910で、ロールバックフラグがセットされる。
次に、ステップ912に進み、そこで、今回の値が、前タイムスライスのパルス値が異なるかどうかが判断される。もしそうなら、ステップ914で、エッジ・テーブル706に時刻tのエントリが記録される。
ステップ912の判断が否定的なら、処理は直ちに終了する。
ステップ904に戻って、パルス・テーブル704に、時刻tのエントリが存在しないなら、ステップ916に進み、パルス・テーブル704に、時刻tでの値が記録される。
次に、ステップ918に進み、そこで、今回の値が、前タイムスライスのパルス値が異なるかどうかが判断される。もしそうなら、ステップ920で、エッジ・テーブル706に時刻tのエントリが記録され、ステップ922で、ペリフェラル612にエッジ信号が入力され、処理は終了する。
ステップ918の判断が否定的なら、処理は直ちに終了する。
次に、図10を参照して、図8のステップ804に対応する、変数入力の処理について、説明する。図10のステップ1002で、入力スケジューラ712が、今のタイムスライスtのパルス入力の値を取得する。
ステップ1004で、入力スケジューラ712が、入力変数テーブル714で、時刻t以前で、最近のエントリを探す。
ステップ1006では、入力スケジューラ712が、そのエントリが入力変数テーブル714で末尾かどうか、判断する。もしそうなら、ステップ1008で、入力スケジューラ712が、最終入力時間をtにセットする。
ステップ1010では、入力スケジューラ712が、探したエントリの値が今回の値と異なるかどうか判断する。もしそうなら、ステップ1012で、今回の時刻と値が末尾のエントリとして、入力変数テーブル714に追加される。そして、ステップ1014に進む。
ステップ1010で、入力スケジューラ712が、探したエントリの値が今回の値と同一であると判断すると、処理は直ちにステップ1014に進む。
ステップ1014で、入力スケジューラ712が、読取り要求テーブル716に、時刻t以前で、返答フラグがfalseのエントリERがあるかどうかを判断し、もしそうでないなら、処理は直ちに終了する。
ステップ1014で、入力スケジューラ712が、読取り要求テーブル716に、時刻t以前で、返答フラグがfalseのエントリERがあると判断すると、ステップ1016に進み、入力スケジューラ712が、エントリERの時刻ter以前で最近のエントリを入力変数テーブル714で探す。
ステップ1018では、入力スケジューラ712が、その探したエントリの値Verを、読取り要求テーブル716のエントリERとして書き込む。
ステップ1020では、変数アクセス・インターフェース718が、エントリERに対応する読取り要求に対する返答メッセージをペリフェラルに、時刻ter、値Verで、入力し、処理は終わる。
ステップ1006に戻って、エントリが入力変数テーブル714で末尾でないと判断されたなら、入力スケジューラ712が、ステップ1022に進み、そのエントリの値が今回の値と異なるかどうかを判断する。もしそうなら、ステップ1024に進み、最終入力時間をtにし、ステップ1026で、入力変数テーブル714の時刻t以降のエントリが削除される。そして、ステップ1028で、今回の時刻と値で、入力変数テーブル714の末尾にエントリが追加される。
次にステップ1030に進み、そこで、入力スケジューラ712が、読取り要求テーブル716中で時刻t以降の返答フラグがtrueのエントリがあるかどうかをチェックする。そして、もしそうなら、ステップ1032で、ロールバックフラグをセットして、処理は終わる。そうでないなら、直ちに処理は終わる。
ステップ1022に戻って、そのエントリの値が今回の値と同じなら、直ちに処理は終わる。
次に、図11を参照して、図8のステップ810に対応する、変数出力の処理について、説明する。図11の処理は基本的に、出力スケジューラ724によって実行される。
ステップ1102では、出力スケジューラ724が、出力スケジュール時間tsが、今のタイムスライスの時間tよりも前かどうかを判断する。そして、もしそうなら、ステップ1104で、出力スケジューラ724は、出力変数テーブル720において、時刻tsからtまでの変数出力を行う。そうでないなら、ステップ1106で、出力スケジューラ724は、出力変数テーブル720において、時刻tでの変数出力を行う。
そして、ステップ1108で、出力スケジューラ724は、出力スケジュール時間722を次のタイムスライスの時刻にセットして、処理を終了する。
図12のフローチャートは、図11でのステップ1104またはステップ1106の出力処理を、より詳しく説明するものである。ステップ1202では、ある時刻toが与えられたとき、出力変数テーブル720で、出力変数テーブル720において、to以前で、最近のエントリが探される。
ステップ1204では、見つかったそのエントリが、時刻toでのエントリとして出力される。
次に、図13を参照して、図8のステップ808に対応する、ロールバック処理について、説明する。ステップ1302で、ヒストリ・マネジャ708が、割込み応答時間リスト710から、時刻t以前で、最新のロールバック可能時間を探す。ここでtとは、今のタイムスライスの時間である。
ステップ1304では、そのロールバック可能時間をtrbとする。
ステップ1306では、ヒストリ・マネジャ708が、そのtrbへのロールバック要求を、ペリフェラル612に送る。典型的に図4に示されるように、ECUエミュレータ604は、状態リポジトリに状態の履歴を保持しているので、このロールバック要求に応答して、状態を遡ることが可能である。
ステップ1308では、ヒストリ・マネジャ708が、パルス・テーブル704、エッジ・テーブル706、割込み応答時間リスト710、入力変数テーブル714、及び出力変数テーブル720の、時刻tより後のエントリを削除する要求を、変数アクセス・インターフェース718に送る。変数アクセス・インターフェース718は、この要求に応答して、実際にエントリ削除作業を行う。
ステップ1310では、エッジ・テーブル706に記録された時刻trbから時刻tまでのエッジを、エッジ通知モジュール702が、ペリフェラル612に入力する。
ステップ1302では、ヒストリ・マネジャ708が、グローバル・タイム・マネジャ610に、時刻を申告する。このとき、現在の確定時刻を申告値として使う。
次に、図14のフローチャートを参照して、ペリフェラル612から届くイベントの処理を説明する。この処理は、図8のフローチャートに示す処理とは別プロセスまたは別スレッドであるので、図8には含まれていない。
図14のステップ1402では、アダプタブロック606が、ペリフェラル612から届くイベントのうち、未処理のイベントがあるかどうかを判断する。未処理のイベントがなければ、ステップ1402で待機状態となる。
未処理のイベントがあると、次のステップ1404で、その未処理のイベントが、割込み応答(割込みハンドラの起動)通知イベントであるかどうかが判断される。
もし未処理のイベントが、割込み応答通知イベントであるなら、ステップ1406で、割込み応答時間リスト710に 今回のイベントの時刻tackのエントリがあるかどうかが判断される。もしそうなら、ステップ1402で待機状態となる。
ステップ1406で、割込み応答時間リスト710に 今回のイベントの時刻tackのエントリがないと判断されると、ステップ1408で、割込み応答時間リスト710の末尾に、イベントの時刻tackが記録される。
そこで、ステップ1410では、出力スケジュール時間(時刻ts)がtackより前かどうかが判断される。もしそうなら、ステップ1412で、申告値としてtsを使うことによりグローバル・タイム・マネジャ610に時刻の申告が行われ、そうでなければ、ステップ1414で、申告値としてtackを使うことによりグローバル・タイム・マネジャ610に時刻の申告が行われ、ステップ1402での待機に戻る。
ステップ1404に戻って、未処理のイベントが、割込み応答通知イベントでないなら、ステップ1416に進み、そこで、変数アクセス・インターフェース718によって、未処理のイベントが、変数の読込み要求イベントかどうかが判断される。もしそうなら、ステップ1418で、変数アクセス・インターフェース718が変数の読込み要求イベントの処理を行って、ステップ1402での待機に戻る。読込み要求イベントの処理については、図15のフローチャートを参照して後でより詳細に説明する。
ステップ1416で、変数アクセス・インターフェース718が、未処理のイベントが、変数の読込み要求イベントでないと判断すると、ステップ1420で変数アクセス・インターフェース718は、ステップ1420で、未処理のイベントが変数の書込みイベントであると認識し、ステップ1422で変数アクセス・インターフェース718が変数の書込み要求イベントの処理を行って、ステップ1402での待機に戻る。書込み要求イベントの処理については、図16のフローチャートを参照して後でより詳細に説明する。
次に、図15のフローチャートを参照して、変数アクセス・インターフェース718による変数の読込み要求イベントの処理を説明する。図15のステップ1502では、読取り要求パケットの時刻をtrqとする。
ステップ1504では、変数アクセス・インターフェース718が、読取り要求テーブル716に、時刻trqのエントリがあるかどうか判断し、もしそうなら、そのエントリの値をVrとする。
次に、ステップ1506で、変数アクセス・インターフェース718は、時刻trq、値Vrで、読取り要求に対する返答メッセージを、ペリフェラル612に入力し、変数の読込み要求イベントの処理を終わる。
このとき、時刻trqは、離散イベント系がロールバックして昔の時刻をやり直した状態であるが、当該エントリの返答フラグは必ずtrueであることに留意されたい。なぜなら、連続系でロールバックを起こした時刻tより後の読取り要求テーブル716のエントリは、ロールバック時に削除されているため、今回のtrqは時刻t以前であるから対応する値はロールバック時には返答可能であったはずだからである。
ステップ1504に戻って、読取り要求テーブル716に、時刻trqのエントリがないなら、ステップ1508に行って、変数アクセス・インターフェース718は、最終入力時間が読取り要求パケットの時刻trqより後かどうかを判断する。
もしそうなら、変数アクセス・インターフェース718は、入力変数テーブル714で、時刻trq以前で最近のエントリを探し、そのエントリの値をVrとする。
ステップ1512では、変数アクセス・インターフェース718は、読取り要求テーブル716の末尾に、時刻trq、値Vr、返答フラグtrueのエントリを記録する。
ステップ1514では、変数アクセス・インターフェース718は、読取り要求に対する返答メッセージを、時刻trq、値Vrでペリフェラル612に入力する。次に処理は、判断ステップ1518に進む。
ステップ1508の判断に戻って、最終入力時間が読取り要求パケットの時刻trqより後でないなら、変数アクセス・インターフェース718は、ステップ1516で読取り要求テーブル716の末尾に、時刻trq、返答フラグfalseのエントリを記録して、判断ステップ1518に進む。
判断ステップ1518では、出力スケジュール時間(時刻ts)がtrqより前かどうかが判断される。もしそうなら、ステップ1520で、申告値としてtsを使って、グローバル・タイム・マネジャ610に時刻が申告される。もしそうでなければ、ステップ1522で、申告値としてtrqを使って、グローバル・タイム・マネジャ610に時刻が申告され、変数の読込み要求イベントの処理が終わる。
次に、図16のフローチャートを参照して、変数アクセス・インターフェース718による変数の書込み込み要求イベントの処理を説明する。図16のステップ1602では、書込み要求パケットの時刻をtwqとする。
ステップ1604では、変数アクセス・インターフェース718は、出力変数テーブル714に要求パケットの時刻twqのエントリが存在するかどうかを判断する。もしそうなら、変数アクセス・インターフェース718は、変数の書込み要求イベントの処理を終わる。
なお、ステップ1604で、出力変数テーブル714に要求パケットの時刻twqのエントリが存在するということは、離散イベント系がロールバックして昔の時刻をやり直した状態であり、当該エントリの値は今回の書込み要求の値と同一であることを意味する。なぜなら連続系でロールバックを起こした時刻tより後の出力変数テーブル720のエントリはロールバック時に削除されているため、今回のtwqは時刻t以前であり、時刻t以前までは離散イベント系はロールバックする前に実行したのと同一の入力を受けるため、同一の動作をするはずであるからである。
ステップ1604で、出力変数テーブル714に要求パケットの時刻twqのエントリが存在しないなら、ステップ1606で、変数アクセス・インターフェース718は、出力変数テーブル720の末尾に、書込み要求パケットの時刻twqと値のエントリを記録する。
ステップ1608では、出力スケジュール時間(時刻ts)がtwqより前かどうかが判断される。もしそうなら、ステップ1610で、申告値としてtsを使って、グローバル・タイム・マネジャ610に時刻が申告される。もしそうでなければ、ステップ1612で、変数アクセス・インターフェース718が出力スケジュール時間をtwqにセットし、ステップ1614で、申告値としてtwqを使って、グローバル・タイム・マネジャ610に時刻が申告され、こうして、変数の書込み要求イベントの処理が終わる。
以上、本発明の構成を説明してきたが、本発明の構成の動作をより具体的に示すために、幾つかのシナリオに沿って説明する。
<シナリオ1>
シナリオ1は、連続系シミュレータからのパルス入力に応じた、離散系シミュレータへの割込みの起動シーケンスに関する。図17に、シナリオ1のタイミング・チャートを示す。図示されているように、連続系の3タイムスライス毎に、時間t0、t3、t6、t9、t12・・・と、ECUのペリフェラルに、エッジ通知がなされる。これは図式的な例であって、実際はもっと大きい間隔でエッジ通知がなされることに留意されたい。これは、エッジ通知モジュール702が、入力パルスのエッジをそのタイミングで検出しているからである。但し、全てのエッジ通知が離散系への割込みを引き起こす訳ではない。割込みを引き起こすイベントに応答してのみ、離散系への割込みが引き起こされる。
一方、離散系からは、連続系に対して、変数の読取り要求や、変数の書込み要求もなされる。図17で、変数A読取り要求や、変数Z書込み要求というのが、それに該当する。
以下、アダプタブロック606で使用されるテーブル及びフィールドについて説明する。
図18は、パルス・テーブル704のエントリの例を示す。パルス・テーブル704は、各タイムスライスで、アダプタブロック606に入力されるパルス信号の履歴を保持する。パルス・テーブル704は、図示されているように、時刻と、入力毎のパルス信号の値をエントリとしてもつ。複数のパルス信号が入力される場合、それぞれの値を書く。
図19は、エッジ・テーブル706のエントリの例を示す。エッジ・テーブル706は、アダプタブロック606に入力されるパルス信号のエッジ(立上り/立下り)の履歴を保持するためのものであって、時刻と、エッジの種類(立上りまたは立下りで、up/downで示されている)と、それが生じた入力ポートをエントリとしてもつ。
図20は、割込み応答時間リスト710のエントリの例を示す。割込み応答時間リスト710は、離散系シミュレータからの割込みの応答の時刻の履歴を保持し、その時刻に、離散系シミュレータは、ロールバック可能である。
図21は、変数Aの入力変数テーブル714のエントリの例を示す。入力変数テーブル714は、アダプタブロック606に入力される。毎タイムスライス毎に入力があるが、入力変数テーブル714は、値が変化したときの時刻と値を、エントリとしてもつ。入力変数テーブル714は、入力される変数の数だけ用意される。
図22は、アダプタブロック606の最終入力時間722のエントリの例を示す。最終入力時間722のフィールドには、各タイムスライスで変数の入力が行われる度に、その時刻が書き込まれる。この実施例では、入力変数テーブル714に関連したフィールドとして示されている。
図23は、変数Aの読取り要求テーブル716のエントリの例を示す。読取り要求テーブル716には、離散例シミュレータからの変数の読込み要求の履歴が保持される。読取り要求テーブル716は、変数の読込み要求の時刻、返答に使用された値、及び返答済みか否かのフラグをエントリとしてもつ。このとき、アダプタブロック606がまだ実行していない時刻での要求は、未返答として、返答済みフラグは、falseとされる。読取り要求テーブル716は、返答に使用される変数の数だけ用意される。
図24は、変数Zの出力変数テーブル720のエントリの例を示す。出力変数テーブル720は、離散系シミュレータからの変数の書込みの履歴を保持する。出力変数テーブル720は、変数の書込みの時刻と、その際の値をエントリとしてもつ。アダプタブロック606は、この表をみて、毎タイムスライスで変数の出力値を決める。出力変数テーブル720は、出力される変数の数だけ用意される。
図25は、アダプタブロック606の出力スケジュール時間722の変数Zのエントリの例を示す。出力スケジュール時間722は、アダプタブロック606の次のタイムスライス実行時に、変数を出力すべき最初の時刻を保持する。アダプタブロック606は、変数出力処理時に、この時刻からそのタイムスライスでの時刻までの各タイムステップでの出力を行う。通常は、出力処理時にはそのタイムスライスでの時刻が書込まれているはずだが、離散系シミュレータの実行が遅く、古い時刻での変数書込みがあった場合に、アダプタブロック606で既に実行した値がここに書き込まれていることがある。出力スケジュール時間722のフィールドは、出力される変数の数だけ用意される。
図26は、シナリオ1における、エッジ通知モジュール702、ヒストリ・マネジャ708、グローバル・タイム・マネジャ610、ECUペリフェラル612、ECUエミュレータ604、及び変数アクセス・インターフェース718の間の通知または応答の流れを、時間付きで示す図である。
エッジ通知モジュール702は、パルスを連続系シミュレータから受け取る度にパルス・テーブル704に時刻と、各入力ポートでのパルス値を記録する。エッジ通知モジュール702は、前のタイムスライスでの値と異なれば、エッジとみなす。エッジ通知モジュール702は、エッジを検出する度に、エッジ・テーブル706に、時刻、入力ポート、及びエッジの種類を記録し、ペリフェラル612に通知する。
ペリフェラル612は、エッジ通知モジュール702から通知がある度に、設定に基づいた動作をして、割込みが発生するのであれば、離散系シミュレータ(この場合、ECUエミュレータ604)に割込みを入力する。そして、離散系シミュレータから割込みがある度に、ヒストリ・マネジャ708にそのまま渡す。ペリフェラル612はまた、離散系シミュレータによって設定される。
離散系シミュレータは、割込み入力により割込みが起動されたタイミングで、時刻付の割込み応答を、ペリフェラル612に返す。
ヒストリ・マネジャ708は、ペリフェラル612から応答がある度に、割込み応答時間リスト710にその時刻を記録し、グローバル・タイム・マネジャ610に、その時刻をタイムスタンプとして通知する。但し、アダプタブロック606からの出力時刻である、出力スケジュール時間722の方が遅れていれば、出力スケジュール時間722の1つ前のタイムスライスの時刻を、グローバル・タイム・マネジャ610に通知する。一方、ヒストリ・マネジャ708は、グローバル・タイム・マネジャ610から確定時刻の報告を受けると、それを保持する。
シナリオ1では、離散系シミュレータが変数の値を読取る場合、ペリフェラル612に、変数名と時刻の情報をもつ読取り要求パケットを送信し、返答を待つ。
ペリフェラル612は、離散系シミュレータから読取り要求パケットを受け取ると、それを変数アクセス・インターフェース718にそのまま渡し、返答を待つ。変数アクセス・インターフェース718から、読取り要求パケットに対する返答が到着したら、ペリフェラル612は、それを、離散系シミュレータに渡す。
変数アクセス・インターフェース718は、ペリフェラル612から読取り要求パケットがあれば、図14のフローチャートに示す処理により、変数値を取得して値を返し、ヒストリ・マネジャ708に読取り要求パケットの時刻を、タイムスタンプとして通知する。
離散系シミュレータが変数の値を書込む場合、ペリフェラル612に、変数名と時刻と値の情報をもつ書込み要求パケットを送信し、返答を待つ。
ペリフェラル612は、離散系シミュレータから書込み要求パケットを受け取ると、それを変数アクセス・インターフェース718にそのまま渡す。
変数アクセス・インターフェース718は、ペリフェラル612から書込み要求パケットがあれば、図14のフローチャートに示す処理により、変数値を書込む手続きを行い、ヒストリ・マネジャ708に書込み要求パケットの時刻を、タイムスタンプとして通知する。
ヒストリ・マネジャ708は、変数アクセス・インターフェース718からタイムスタンプの通知が到着すると、グローバル・タイム・マネジャ610にタイムスタンプとして通知する。但し、アダプタブロック606からの出力時刻である、出力スケジュール時間722の方が遅れていれば、出力スケジュール時間722の1つ前のタイムスライスの時刻を、グローバル・タイム・マネジャ610に通知する。
<シナリオ2>
シナリオ2は、連続系シミュレータへのパルス入力がロールバックしたため、離散系シミュレータにトランザクションのやり直しを指示するというものである。図27に、シナリオ2のタイミング・チャートを示す。図27において、t9まで実行した時点で、t8までのパルスが到着したとする。すると、アダプタブロック606は、t8以前で一番近いロールバック可能な時点t2(これは、割込み応答時間リスト710から分かる)まで戻るように離散系シミュレータに指示し、エッジの通知を、エッジ・テーブル706を参照して、t1からt8までやり直すようにする。
図28は、シナリオ2における、エッジ通知モジュール702、ヒストリ・マネジャ708、グローバル・タイム・マネジャ610、ECUペリフェラル612、ECUエミュレータ604、及び変数アクセス・インターフェース718の間の通知または応答の流れを、時間付きで示す図である。
エッジ通知モジュール702は、古い時刻のパルス入力があり、その値がパルス・テーブル704に記録された値と異なる場合、パルス・テーブル704とエッジ・テーブル706の、そのパルス入力の古い時刻以降を削除し、ヒストリ・マネジャ708に、そのパルス入力の時刻付のロールバック要求を出す。そして、ヒストリ・マネジャ708からロールバックの通知を待ち、ロールバック可能時刻から今回のパルス入力までのエッジを、エッジ・テーブル706を参照して、ペリフェラル612に通知する。
ヒストリ・マネジャ708は、エッジ通知モジュール702からロールバック要求を受け取ると、割込み通知時間リスト706から、そのパルス入力時刻以前で一番近いロールバック可能時刻を探し、その時刻へのロールバック要求をペリフェラル612に出す。その時刻以降の割込み通知時間リスト706のエントリは削除する。さらに、探した時刻を、グローバル・タイム・マネジャ610に、確定時刻として通知する。そして、エッジ通知モジュール702に、ロールバック可能時間を渡す。さらに、変数アクセス・インターフェース718に、パルス入力時刻とロールバック可能時間を引数として、エントリ削除要求を出す。
ペリフェラル612は、ヒストリ・マネジャ708からロールバック要求を受け取ると、離散系シミュレータにそのまま渡す。
離散系シミュレータは、ペリフェラル612からロールバック要求を受け取ると、記載された時刻にロールバックする。
変数アクセス・インターフェース718は、エントリ削除要求を受け取ると、入力変数テーブル714と出力変数テーブル720のパルス入力時刻以降のエントリを削除し、また、読取り要求テーブル716における、ロールバック可能時間以降のエントリを削除する。さらに、変数アクセス・インターフェース718は、最終入力時間と、出力スケジュール時間722を、パルス入力時刻にセットする。
図29は、シナリオ2における、パルス・テーブル、エッジ・テーブル及び割込み応答時間リストの変化を示す図である。すなわち、連続系シミュレータがt9まで実行した後、t8のパルスが到着して、その値が0であった。これは、パルス・テーブルにおけるt8の値とは異なるので、ロールバックが必要である、と判断される。そこで、割込み応答時間リストで、t8から一番近いロールバック可能時刻を調べると、t2である。そこで、アダプタブロック606は、このt2まで戻るように離散系シミュレータに指示し、t2以降t8までのエッジを再入力する。
図30は、シナリオ2における、変数Zの出力変数テーブル、出力スケジュール時間、変数Aの入力変数テーブル、変数Aの読取り要求テーブル、最終入力時間の変化を示す図である。ここでは、入力変数テーブルと出力変数テーブルが、t8以降のエントリを削除され、読取り要求テーブルはt2以降のエントリを削除され、最終入力時間と出力スケジュール時間がt8にセットされることが示されている。
<シナリオ3>
シナリオ3は、連続系シミュレータへの変数入力がロールバックしたため、離散系シミュレータにトランザクションのやり直しを指示するというものである。図31に、シナリオ3のタイミング・チャートを示す。図31において、t9まで実行した時点で、t5の入力が到着したとする。このとき、パルスの値は以前に受け取ったt5の値と同じだが、変数Aの値がt5で変化した。離散系シミュレータはt6で変数Aの値を参照しているので、t6に一番近いロールバック可能な時点であるt2まで戻るように、アダプタブロック606が、離散系シミュレータに指示し、エッジの通知を、エッジ・テーブル706を参照して、t3からt5までやり直すようにする。
図32は、シナリオ3における、エッジ通知モジュール702、ヒストリ・マネジャ708、グローバル・タイム・マネジャ610、ECUペリフェラル612、ECUエミュレータ604、及び変数アクセス・インターフェース718の間の通知または応答の流れを、時間付きで示す図である。
入力スケジューラ712は、古い入力があり、その値が入力変数テーブル714に記録された値と矛盾し、且つ読取り要求テーブル716に今回の入力の時刻以降のエントリが合った場合、ヒストリ・マネジャ708に、その変数入力の時刻付けのロールバック要求を出す。
エッジ通知モジュール702は、ヒストリ・マネジャ708からのロールバックの通知があれば、ロールバック可能時刻から今回の入力時刻までのエッジをエッジ・テーブル706を参照して、ペリフェラル612へ入力する。そうして、パルス・テーブル704と、エッジ・テーブル706の今回の入力時刻以降のエントリを削除する。
ヒストリ・マネジャ708は、入力スケジューラ712からロールバック要求を受け取ると、割込み応答時間リスト710において、そのパルス入力時刻以前で一番近いロールバック可能時刻を探し、その時刻へのロールバック要求をペリフェラル612に渡す。その時刻以降の割込み応答時間リスト710のエントリは削除する。そうして、ヒストリ・マネジャ708は、グローバル・タイム・マネジャ610にタイムスタンプとして確定時刻を通知し、さらに、エッジ通知モジュール702に、ロールバック可能時刻を渡す。ヒストリ・マネジャ708はさらに、変数アクセス・インターフェース718へ、パルス入力時刻とロールバック可能時刻を引数として、エントリ削除要求を渡す。
ペリフェラル612は、ヒストリ・マネジャ708からロールバック要求を受け取ると、離散系シミュレータにそのまま渡す。
離散系シミュレータは、ペリフェラル612からロールバック要求を受け取ると、記載された時刻にロールバックする。
変数アクセス・インターフェース718は、ヒストリ・マネジャ708からエントリ削除要求を受け取ると、入力変数テーブル714と出力変数テーブル720については、パルス入力時刻以後のエントリを削除する。読取り要求テーブルについては、ロールバック可能時刻以後のエントリを削除する。最終入力時間と、出力スケジュール時間については、パルス入力時刻にセットする。
<シナリオ4>
シナリオ4は、離散系シミュレータが遅く、連続系シミュレータの出力をやり直して後段のブロックにロールバックさせる必要が生じるケースである。連続系シミュレータへの変数入力がロールバックしたため、離散系シミュレータにトランザクションのやり直しを指示するというものである。図33に、シナリオ4のタイミング・チャートを示す。
また、図34は、図33におけるシーケンスでの、出力変数テーブルと、出力スケジュール時間の変化を示すものである。
図34(a)は、連続系でt9まで出力が終わった時点での状態の変数Zの出力変数テーブルと、出力スケジュール時間とをそれぞれ示す。
図34(b)は、連続系がt10を実行する前に変数Zの書込み要求が到着したとする。この書込み要求パケットは、変数名=Z、時刻=t7、値=700.0である。
すると、連続系でt10を実行する際の出力スケジュール時間がt7なので、出力スケジューラ724によって、t7からt10までの出力が行われ、その出力が終わると、出力スケジュール時間は、次のタイムスライスであるt11にセットされる。
以上、自動車用の複数のシミュレーション・システムに関連して、本発明の特定の実施例を説明してきたが、本発明はこのような特定の実施例に限定されず、飛行機用のシミュレーション・システムなど、一般的な電子機械制御系システムのシミュレーション・システムに適用可能であることを、この分野の当業者であるなら、理解するであろう。