以下、図面を参照して、本発明の一実施例の構成及び処理を説明する。以下の記述では、特に断わらない限り、図面に亘って、同一の要素は同一の符号で参照されるものとする。なお、ここで説明する構成と処理は、一実施例として説明するものであり、本発明の技術的範囲をこの実施例に限定して解釈する意図はないことを理解されたい。
本発明を実現するための構成を説明する前に、その前提として、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に書き出された任意の時点の状態に戻して、すなわち、ロールバックして、そこから計算をやり直させることができる。
次に、図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に限定されず、ECUエミュレータ・プログラムを走らせることができるものであれば、任意のコンピュータ・システムを使用することができる。オペレーティング・システムも、Windows(R)に限定されず、Linux(R)、Mac OS(R)など、任意のオペレーティング・システムを使用することができる。さらに、ECUエミュレータ・プログラムを高速で動作させるために、POWER(商標)6ベースで、オペレーティング・システムがAIX(商標)のIBM(R)System Pなどのコンピュータ・システムを使用してもよい。
ハードディスク・ドライブ516にはさらに、テストするための複数のECUエミュレータ・プログラム、及び、それら複数のECUエミュレータ・プログラムを協働させてテストするための、本発明に係るプログラムが格納され、キーボード510及びマウス512によって起動操作可能である。
好適には、ホールビークルSILSを実現するために、1台の自動車で使われるすべてのECUのエミュレータ・プログラムが、ハードティスク・ドライブ516に保存されている。そのECUのエミュレータ・プログラムが、そのままでは内部の状態変数を取り出せないものてある場合は、上述したラッパコードを被せることにより、予め、状態変数をセット及び取り出し可能としておくものとする。
ハードティスク・ドライブ516にはまた、後述する、本発明に係る、センサとしての共有メモリ領域に論理プロセスが値を読み書きする際の、一貫性維持のためのロールバック処理の機能を含む、のシミュレーション制御用のプログラムも保存されており、システム起動時にメイン・メモリ506に呼び出されて動作する。
ハードティスク・ドライブ516にはさらに、後述するECUエミュレータ・プログラムのためのスケジューラ、エンジン、トランスミッション、ステアリング、ワイパなどの物理装置(プラント)シミュレータ・プログラム、全体のシステムの入力を同期させるためのグローバル・スケジューラ及び、登り坂道、高速道路、つづら折道などの様々な、テストのためのシナリオを格納したシナリオ・ジェネレータのプログラムも格納されている。
なお、ここでの「エミュレータ」と、「シミュレータ」の用語の使い分けであるが、もともとの、別のプロセッサで動くことを想定して書かれていたECUのコードを、CPU0〜CPU3などをターゲットとして動くようにすることを、エミュレーションと呼び、それを行うプログラムを、エミュレータと呼ぶ。一方、エンジンなどの物理的システムの動作を仮想計算するシステムを、シミュレータと呼ぶ。
次に、図6を参照して、本発明のシミュレーション・システムの機能論理ブロック図を説明する。図6において、共有メモリ602は、実際は、図5に示すメイン・メモリ506の一部であってよい。共有メモリ602には、ECUエミュレータ・プログラム604a、604b、・・・604nと、グローバル・スケジューラ608と、物理装置シミュレータ・プログラム606a、・・・606mが論理的に結合されている。
グローバル・スケジューラ608は、ECUエミュレータ・プログラム604a、604b、・・・604n及び物理装置シミュレータ・プログラム606a、・・・606mの間のイベントのタイム・スタンプに基づき、それらのイベントの間の一貫性を維持するように動作する。グローバル・スケジューラ608のより詳しい動作は、後述する。
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及びグローバル・スケジューラ608は、共有メモリ602を使用してデータを交換するが、代わりに、CAN(controller area network)エミュレータを使用してもよい。
図示しないが、図6の構成には、登り坂道、高速道路、つづら折道などの様々な、テストのためのシナリオを格納したシナリオ・ジェネレータも接続される。
図7は、図6に示したシミュレーション・システムにおいて、センサ702に、物理装置シミュレータ606a、606b、606iと、ECUエミュレータ604a、604b、604jが、値の書込み、あるいは読取り処理を行う様子を図式的に示す。
前述のように、センサ702は実は、図6の共有メモリ602、すなわち、図5のメイン・メモリ506の一区画の領域である。図6に示したシミュレーション・システムにとって、1つの大域変数(global variable)である、とも言える。図示するように、例えば、物理装置シミュレータ606aがセンサ702としてのメモリ領域に書込み、それからECUエミュレータ604aが、書かれた値を読取る、などの処理が行われる。
この際、当然であるが、読み書きの順序は重要である。すなわち、物理装置シミュレータ606aがセンサ702としてのメモリ領域に書込んだ後に、ECUエミュレータ604aが、書かれた値を読取るのと、物理装置シミュレータ606aがセンサ702としてのメモリ領域に書込む前に、ECUエミュレータ604aが、書かれた値を読取るのとでは、ECUエミュレータ604aが読取る値は、全く異なる。
なお、物理装置シミュレータやECUエミュレータなどの論理プロセスは、センサ702としてのメモリ領域に、単に値を書込むだけ、あるいは、単にそこから値を読取るだけ、という処理以外に、センサ702としてのメモリ領域から値xを読取って、直ちにx+Δxを、そのメモリ領域に書き込む、という値更新処理もありえる。
図8は、論理プロセスA、B及びCによる読書き動作を示すタイミングチャートの例である。図8(A)を参照すると、論理プロセスAが、時間t1で、所定の大域変数に10という値を書込む。さらに論理プロセスAは、時間t3で、その大域変数に15という値を書込む。
一方、論理プロセスCは、Δt間隔で周期的に、その大域変数から値を読取る。論理プロセスBは、この時点では、何もしない。
図8(B)には、その様子を図式的に示す。すなわち、論理プロセスAが、センサ(大域変数)に値を書込み、論理プロセスCが、センサ(大域変数)から値を読取る。
尚このとき、例えば、時間t1で、論理プロセスAが所定の大域変数に10という値を書込むとは、その書込みイベントに、時間t1が関連付けられる、ということを意味する。この時間は、単一の論理プロセス内では一貫性があるが、前述のように論理プロセスは、異なる速度で動作することがあるので、異なる論理プロセス間では、仮にti < tjだとしても、シミュレーション・システム内で、時間tiをもつ第1の論理プロセスのイベントが、時間tjをもつ第2の論理プロセスのイベントよりも、先に生起するとは限らない。
図8の処理では、時間の経過に沿って、一貫性を保って、論理プロセス間で値の読み書きが行われているので、矛盾は生じない。
ところが、図9に示すように、論理プロセスAが時間t3をもつイベントで、値15を大域変数に書込み、論理プロセスCがその値15を大域変数から読取った時点で、論理プロセスBが、時間t2 < t3をもつイベントで、値5を、大域変数に書き込むとする。これにより、大域変数の値は、時間t2以降、5となる。
すると、論理プロセスAは、自己の時間t3をもつイベントで値15を書いたことが、単なる書込みであるなら、論理プロセスA自体は、その論理プロセスBの書込みによって影響は受けないが、自己の時間t3をもつイベントで値15を書いたことが、もし大域変数の値を読取って、それに基づき書込み値を決定する変更書込みであるなら、その論理プロセスBの書込みによって最早有効ではなくなるので、キャンセルされなくてはならない。
同様に、論理プロセスCの、Δtでの周期的な大域変数の値の読取り動作も、時間t2以降、最早有効ではなくなるので、キャンセルされなくてはならない。
図9(B)には、その様子を図式的に示す。すなわち、論理プロセスAが、センサ(大域変数)に値を書込み、論理プロセスBも、センサ(大域変数)に値を書込み、論理プロセスCが、センサ(大域変数)から値を読取る。このとき、論理プロセスAの書込みが、変更書込みであるなら、点線矢印で示すように、書込み処理も付随している。
本発明は、ある論理プロセスの書込み処理によって、別の論理プロセスの読取り、あるいは書込み処理が無効になったかどうかをシミュレーション・システムが判断し、もし無効になったのなら、処理が無効化された論理プロセスに通知して、その論理プロセスが、必要に応じて、ロールバックなどの、処理の一貫性を取り戻す対処する処理を行うことを可能ならしめる。
図10は、図6に示したシミュレーション・システムの機能論理ブロック図を、特に本発明の機能に関連する箇所にフォーカスして示した機能論理ブロック図である。図10において、LP1、LP2、・・LPkは、論理プロセスであり、具体的には、図6に示したECUエミュレータ604a、604b、・・・604n、物理装置シミュレータ606a、606b、・・・606mのどれかである。
図示されているように、論理プロセスLP1、LP2、・・LPkと、グローバル・スケジューラ608とは、CANエミュレータまたは共有メモリ1002を介して、互いに接続されている。これは、基本的には、図6で、共有メモリ602として示されているものと同じである。
グローバル・スケジューラ608の基本的機能は、論理プロセスLP1、LP2、・・LPkから時間付きのイベントを受領し、そのうちのもっとも古い時間をもつイベントをもって確定時間を判断し、全論理プロセスに通知することである。
そこで、グローバル・スケジューラ608のメッセージ(イベントとも言う)を受領する機能を利用して、この実施例では、各大域変数毎に、各論理プロセスLP1、LP2、・・LPk毎の同期テーブル1004a、1004b、・・・1004kが設けられている。便宜上、大域変数1のための同期テーブルの領域をメモリ領域1006aで示し、大域変数2のための同期テーブルの領域をメモリ領域1006bで示し、シミュレーション・システムでセンサとして使用される全ての大域変数の各々に、メモリ区画1006a、1006b・・1006qが用意され、その各々に、各論理プロセスLP1、LP2、・・LPk毎の同期テーブルが存在することを理解されたい。
このようなメモリ区画1006a、1006b・・1006qは、グローバル・スケジューラ608だけがアクセスできるプライベート・メモリ領域として、メイン・メモリ506内に確保されている。
同期テーブルの役割は、グローバル・スケジューラ608に対して、所定の大域変数に対する書込みイベントが、ある論理プロセスから届いたとき、グローバル・スケジューラ608が、その実際の書込み動作の完了を確認して、その完了時間を、その所定の大域変数における、その論理プロセスに対応する同期テーブルに書込む。
同期テーブルがどのように利用されるかは、後述の具体的な動作例を参照することにより、より一層明らかになるであろう。
本発明の更なる特徴によれば、論理プロセスLP1、LP2、・・LPk及びグローバル・スケジューラ608がアクセス可能な、共有メモリ領域1008が、メイン・メモリ506内に確保されている。共有メモリ領域1008には、シミュレーション・システムでセンサとして使用される全ての大域変数の各々に、メモリ区画1010a、1010b・・1010qが用意されている。その大域変数毎の各メモリ区画には、書込みテーブル1012、読取りテーブル1014a、1014b、・・・1014k、及びコミット時間格納領域1016が設けられている。読取りテーブル1014a、1014b、・・・1014kは、その各々が、論理プロセスLP1、LP2、・・LPkに対応している。
すなわち、書込みテーブル1012は、好適な実施例では、大域変数につき1つであり、読取りテーブルも、好適な実施例では、大域変数毎に、論理プロセスの数だけ用意される。また、コミット時間格納領域1016は、大域変数につき1つである。なお、このような構成は、一実施例に過ぎず、シミュレーション・システム全体で単一の書込みテーブルにすることもできる。この場合、例えば、書込みテーブルに大域変数を指定する欄を設ければよい。コミット時間格納領域の欄も同様である。
書込みテーブル1012は、時間と、値と、書込みを行った論理プロセス(LP)を示すフィールドをもち、グローバル・スケジューラ608は、論理プロセスから、大域変数、時間及び値を指定する書込みイベントを受け取ると、その時間と値で、その大域変数に関連する書込みテーブル1012に値を書き込む。その書込みが完了すると、グローバル・スケジューラ608は、その完了時間を、その大域変数における、その論理プロセスの同期テーブルに書込む。
コミット時間格納領域1016には、すべての同期テーブルに完了時間のエントリが入れられたとき、そのうちの最も古い時間が格納される。
一方、論理プロセスの読取り動作は、グローバル・スケジューラ608を介することなく、論理プロセスが直接、共有メモリ領域1008の、値を読取るべき大域変数の書込みテーブル1012にアクセスすることにより、行われる。すなわちその際、論理プロセスは、書込みテーブル1012の一番新しい時間のエントリにアクセスして、その値を読取る。そうして、読取ったエントリの時間と値を、その大域変数における、その論理プロセス用の読取りテーブルに書込む。
このようにして格納される書込みテーブルと読取りテーブルのエントリは、論理プロセスが読取った値の一貫性チェックに使用されるが、そのチェック動作は、後述のフローチャート及び具体的な動作例を参照することにより、後で詳細に説明される。
次に、図11以下のフローチャートを参照し、且つ図10に示した書込みテーブル及び読取りテーブルも適宜参照しながら、本発明の実施例に係る処理を説明する。なお、図11から図14までと、図21のフローチャートで示す処理のプログラムは、ハードディスク・ドライブ516に保存され、シミュレーション・システムの起動時に、メイン・メモリ506にロードされて、動作する。このようなプログラムは、C、C++、System C、MATLAB/Simulinkなどのコンピュータ言語やツールで書かれたものである。
図11は、論理プロセスによる読取り動作を示すフローチャートである。このフローチャートにおいて、ステップ1102で、論理プロセス(LP)が、値を読もうとする大域変数の書込みテーブルの1012(図10を参照)の最新の時間をもつエントリの値を読取る。続いて、その論理プロセスは、ステップ1104で、その大域変数に関連して、その論理プロセス用に設けられた読取りテーブル1014に、その論理プロセスが指定した時刻に対応する時刻と、読取った値とを書き込む。
図12は、論理プロセスによる書込み動作を示すフローチャートである。ステップ1202では、論理プロセスが、グローバル・スケジューラ608に、書込みメッセージ(書込みイベントとも言う)を送る。書込みメッセージには、書き込む大域変数の指定と、時間と、書き込む値の情報が含まれている。このように、グローバル・スケジューラ608が、書込みメッセージを論理プロセスから一旦受け取ると、グローバル・スケジューラ608はそれらのメッセージを一旦キュー(図示しない)に入れ、順次処理するので、書込みテーブルへのアクセス競合が回避される。
ステップ1204では、グローバル・スケジューラ608が、書込みメッセージに含まれている値を使用して、その大域変数の書込みテーブル1012に、値と、時間と、書込みする論理プロセスのIDからなるエントリを挿入する。その書込みが完了したことに応答して、グローバル・スケジューラ608は、その完了時間を、その大域変数における、その論理プロセスの同期テーブル1004に、書き込む。通常、書込みテーブル1012への書込みと、その完了に応答して同期テーブル1004に完了時間か書き込まれるまでには、若干の遅延があるので、同期テーブル1004に書き込まれる値は、書込みテーブル1012に書かれる時間よりも少し後になる。
ステップ1206では、その大域変数における、読取りテーブル1014と書込みテーブル1012との一貫性がチェックされ、その結果、ステップ1208で有効と判断されるか否かによって、異なる処理が行われる。
図13は、ステップ1206とステップ1208の詳細を示すフローチャートである。ステップ1302では、その大域変数における、書込みテーブルの値の列を、{Vw(t1), Vw(t2), ... , Vw(tm)}とする。t1,t2, ..., tmは、書込みテーブルに書かれている時間である。
ステップ1304では、先ほど書かれた値を、Vw(tk)とする。k ∈ {1,2,..., m}であってすなわち、Vw(tk)は、{Vw(t1), Vw(t2), ... , Vw(tm)}のうちのどれかである。
ステップ1306では、その大域変数における、書込みを行った論理プロセスの読取りテーブル1014(図10では、論理プロセス毎に、読取りテーブル1014a、1014b・・・のように示されているが、ここでは総称的に、読取りテーブル1014と示す)の値の列を、{Vr(s1), Vr(s2), ... , Vr(sn)}とする。s1,s2, ..., snは、読取りテーブル1014に書かれている時間である。
ステップ1308では、Vr(si) = Vr(s1), Vr(s2), ... , Vr(sn)として、i = 1, 2, ... .nでループを廻す。
ステップ1310では、si >= tk-1且つsi < tk+1かどうかが判断される。この判断はすなわち、siという時間が、先ほど書込みテーブルに書かれた時間の前後の時間の範囲に入っているかどうかの判断である。もしそうでないなら、処理は、ステップ1308に戻って、次のiに進む。なお、もしtk-1に該当するエントリがない場合は、tk-1 = 0と想定し、tk+1に該当するエントリがない場合は、tk+1を仮想的に∞であるような非常に大きい時間と想定する。
ステップ1310での判断が肯定的であると、ステップ1312に進み、そこで、tk > siかどうかが判断される。tk > siであるということは、先ほど書込みテーブルに書かれた時間tkが、siという時間よりも大きいという意味なので、Vr(si)が、書込みテーブルにおけるVw(tk)よりも1つ前のエントリの値であるVw(tk-1)と等しいかどうかという判断が、ステップ1314で行われる。その結果、等しいと判断されると、ステップ1318で、ループを完了したかどうかが判断される。ループを完了したなら、書込みテーブルと読取りテーブルは矛盾がない、すなわち、有効と判断される。ループがまだ完了していないなら、ステップ1308に戻って、次のsiに進む。Vr(si)が、Vw(tk-1)と等しくないと、読取りテーブルには、書込みテーブルと一貫性のないエントリが含まれているということになり、ステップ1320に行って、読取りテーブルが無効である、という判断となる。
ステップ1312に戻って、tk > siでないと、先ほど書込みテーブルに書かれた時間tkが、siという時間よりも小さいか等しいという意味なので、Vr(si)が、書込みテーブルにおけるVw(tk)と等しいかどうかという判断が、ステップ1316で行われる。その結果、等しいと判断されると、ステップ1318に行って、ループを完了したかどうかが判断される。ループを完了したなら、書込みテーブルと読取りテーブルは矛盾がない、すなわち、有効と判断される。ループがまだ完了していないなら、ステップ1308に戻って、次のsiに進む。Vr(si)が、Vw(tk)と等しくないと、読取りテーブルには、書込みテーブルと一貫性のないエントリが含まれているということになり、ステップ1320に行って、読取りテーブルが無効である、という判断となる。
ステップ1310が否定的なままだと、ステップ1308のループが単に終端に達して、ステップ1318に至り、読取りテーブルは有効ということになる。
図12のフローチャートに戻って、図13のフローチャートにおける無効1320あるいは有効1318が、ステップ1208の判断となる。
なお、ステップ1206とステップ1208は、単一の書込みテーブル1012と、複数の読取りテーブル1014a、1014b・・・1014kの各々とで順次実行されることを理解されたい。従って、ステップ1208では、複数の論理プロセスの読取りテーブルが無効と判断される、ということがあり得る。
そこで、複数の論理プロセスの読取りテーブルの全てが有効であるなら、ステップ1208の判断が肯定的となって、図12のフローチャートで示す処理は、完了する。
ステップ1208で、読取りテーブルが無効と判断された論理プロセスが1つでもあると、ステップ1210で、グローバル・スケジューラ608が、読取りテーブルが無効と判断された論理プロセスに、ダウト(doubt)メッセージを送る。ダウト・メッセージは、ステップ1206でのチェックのもととなった書込みメッセージの、大域変数と、時間と、値の情報を含む。
ステップ1212で、ダウト・メッセージを受け取った論理プロセスは、それに従い、対応する読取りテーブルのエントリを変更する。ここでいう読取りテーブルのエントリの変更とは、図14のフローチャートに示すように、ステップ1402で論理プロセスがダウト・メッセージを受け取ると、ステップ1404で、ダウト・メッセージに含まれる大域変数の指定に対応する読取りテーブルにおいて、ダウト・メッセージに含まれる時間よりも後の時間をもつエントリを消去するか無効化し、ステップ1406で、ダウト・メッセージに含まれる時間と値のエントリを、読取りテーブルに書き込むことである。そうして、ステップ1408では、必要に応じて、ロールバック処理が行われる。すなわち、図4に示すように、論理プロセスが、内部状態と入力のヒストリを状態リポジトリ404に保存していると、更新された読取りテーブルのエントリに基づき、状態リポジトリ404を検索して、その状態に論理プロセスを戻して、そこから再開することができる。
図12に戻って、ステップ1214では、論理プロセスが、書込みをロールバックするかどうかを判断する。書込みロールバックが必要な処理は、図17以下を参照して、後で説明する。
そして、ステップ1216で、書込みロールバックが必要と判断されると、ステップ1218で、論理プロセスは、グローバル・スケジューラ608に、書込みキャンセルのメッセージを送る。このことも、図17以下を参照して、後で説明する。
ステップ1216で、書込みロールバックは不要と判断されると、処理は終了する。
これも後で詳しく説明するが、ステップ1220に示すように、書込みキャンセルが生じると、それによって指定されたエントリを書込みテーブルから除去した後、改めて、ステップ1206で、書込みテーブルと読取りテーブルの一貫性がチェックされる。この場合は、書込みキャンセルの後書込みテーブルに残った時間の最も新しいエントリと読取りテーブルとの一貫性をチェックすれば十分である。
次に、図15と図16を参照して、書込み処理による、読取りテーブルの無効化と変更処理の例を説明する。これらの図には、論理プロセスLP1、LP2・・、LPn、グローバル・スケジューラ608、及び書込みテーブル1012と読取りデーブル1014を含む共有メモリ領域1008が示されている。
ここでは、説明の便宜上、大域変数は、変数1だけのメモリ区画を図示する。また、同期テーブル1004も、論理プロセスLP1、LP2及びLP3の対応するもののみ、表示する。
なお、図15及び図16において、LP3の同期テーブル1004cが、アクセス不可となっているのは、LP3は、この変数1にアクセスしないと分かっているので、予めその旨フラグを立てておくという意味である。というのは、この実施例では、コミット時間の領域1016に格納される時間は、全てのLPの同期テーブルに完了時間が埋まった段階でそのうちの最も古い時間によって決定されるが、もしLP3の同期テーブル1004cをアクセス不可として認識しておかないと、そこの完了時間が埋まらないため、コミット時間が確定できなくなるからである。
さて、図15で、LP1が、変数1に対して時間10で100という値を書き込むメッセージを、グローバル・スケジューラ608に送る。すると、そのメッセージを以って、グローバル・スケジューラ608は、時間10で100という値を、書込みテーブル1012に書き込む。それから少し遅れて12という時間で、グローバル・スケジューラ608は、書込み完了を確認し、それによって、LP1の同期テーブル1004aに、12という数字を格納する。
そこで、時間15で、LPnが変数1の値を読みに来る。値を読むことは、変数1の書込みテーブル1012を読みに来ることである。その時点では、100という値が入ったエントリだけがあるので、LPnは、その値を読取って、その値を使った処理を行う。一方、LPnは、読取りの記録として、時間15で、読取った値の100を、LPn用の読取りテーブル1014に書き込む。なお、シミュレーション・システムでは、各LPでシミュレーション時間が異なることがあるので、上述のように、あるLPによる時間10での書込みの後に、時間15での、別のLPによる読取りが、その時間順序で起こるとは限らず、その逆の順序でも起こりえるということを理解されたい。
次に、LP1が、変数1に対して時間20で50という値を書き込むメッセージを、グローバル・スケジューラ608に送る。すると、そのメッセージを以って、グローバル・スケジューラ608は、時間20で50という値を、書込みテーブル1012に書き込む。それから少し遅れて12という時間で、グローバル・スケジューラ608は、書込み完了を確認し、それによって、LP1の同期テーブル1004aに、22という数字を格納する。
ここで、図12のフローチャートに戻って参照すると、このような書込み処理に応答して、ステップ1206で示す書込みテーブルと読取りテーブルの一貫性チェックが行われる。しかし、この場合、書込みテーブル1012に先ほど書かれたエントリの時間は20で、読取りテーブルのエントリの時間15よりも大きい。このことは、図13のフローチャートで、ステップ1310が決して肯定的にならないので、ループは、ステップ1318に抜けて、一貫性はOKであることになる。
さらにLP1が、変数1に対して時間30で10という値を書き込むメッセージを、グローバル・スケジューラ608に送って書込み処理を行う場合も同様であるので、詳細な処理の説明は省略する。
ここで再び、図12のフローチャートのステップ1206で示す書込みテーブルと読取りテーブルの一貫性チェックに着目する。今回書込みテーブル1012に追加されたエントリは、時間が11で値が110である。まず、時間が11ということで、読取りテーブルのエントリの時間15で以って、10 <= 15 < 20が成立し、このことは、図13のフローチャートのステップ1310の判断を肯定的にする。次に、11 < 15なので、ステップ1316の判断に行く。そこで、今回書込みテーブル1012に追加されたエントリの値である110と、読取りテーブル1014の時間15のエントリの値100が比較され、一致しないので、ステップ1320に行き、結局、ステップ1208が有効でない、という判断になる。そこで、ステップ1210に示すように、グローバル・スケジューラ608が、変数1で、時間11で、値110というダウト・メッセージを、LPnに送る。
LPnでは、このダウト・メッセージを受領すると、そこにある時間15で値100という読取りテーブル1014のエントリをキャンセルする。なぜなら、その時間15は、ダウト・メッセージに含まれている時間11よりも後で、そのエントリの値が異なっているからである。
そうして、キャンセルした最も古い時間15をそのまま使って、ダウト・メッセージに含まれている値110でもって、読取りテーブル1014に、時間15で値110のエントリを書き込む。論理プロセスLPnは、この更新された読取り値で以って、必要なロールバック処理を行う。LP2の処理が完了すると LP2が完了メッセージを、グローバル・スケジューラに送ってくる。これによって、LP2の完了時刻として 13が埋まる。
なお、このような書込みや読取り処理を行うと、同期テーブル、書込みテーブル、及び読取りテーブルのエントリは増えてくる。この実施例では、同期テーブルのエントリは、書込みが行われたタイミングで、コミット時間よりと同等かより古い時間のエントリを削除するように、グローバル・スケジューラ608が動作を行う。
書込みテーブル、及び読取りテーブルの場合は、この実施例では、特定サイズでメモリ区画を区切り、エントリが増えてきて、そのメモリ区画の終端に達したら、メモリ位置を指し示すインデックスを最初の位置に戻して、引き続きデータを書き込んでいくという方法で、エントリが増え続けるのを防いでいる。ただ、書込みテーブル、及び読取りテーブルの場合も、あるタイミングで、コミット時間と同等かより古いものを削除するようにしてもよい。
図17(1)は、書込みキャンセル動作の例を説明するための図である。ここでは、論理プロセスAと、論理プロセスBを考える。図17で先ず、ある大域変数に、あるタイミングで、論理プロセスAが値10を書き込むとする。その後のあるタイミングで、論理プロセスBが、その大域変数を読む。値は、10である。そこで論理プロセスBは、内部のロジックにより、その大域変数が0より大きいなら20を書き込み、そうでないなら、なにもしないとする。すると、このロジックにより、論理プロセスBは、値20を大域変数に書込む。
ところが、図17(2)のように、論理プロセスAが、値10の書込みをキャンセルして、値-10をその大域変数に書込むと、論理プロセスBが読取る大域変数も、-10となる。そこで論理プロセスBは、その大域変数が0より大きいなら20を書き込み、そうでないなら、なにもしないというロジックを再び適用するが、すると、大域変数の値は0より小さいのだから、論理プロセスBは何もしない、というオプションしか取りえない。しかし、論理プロセスBには、前の書込み値が正しくないことは認識している。これを解消するために、論理プロセスBが、グローバル・スケジューラ608に、書込みテーブルに既に書込んだエントリの取り消しを行うメッセージを出すことができるようにする。
図18、図19及び図20は、書込みの取り消し動作の例を説明する図である。図18において、論理プロセスLP1が、グローバル・スケジューラ608に、時間10で値100の書込みメッセージを送る。これによって、グローバル・スケジューラ608によって、書込みテーブル1012に対応するエントリが書かれる。次に時間20で、論理プロセスLP2が、書込みテーブル1012の値を読取って、読取りテーブル1014に読取った時間と値のエントリを書込む。すなわち、図18で前面に表示されている読取りテーブル1014は、LP2の読取りテーブルである。次にLP2が、グローバル・スケジューラ608に、時間30で値50の書込みメッセージを送る。これによって、グローバル・スケジューラ608によって、書込みテーブル1012に対応するエントリが書かれる。ここで留意すべきなのは、この書込む50という値は、時間20で読取った値100に依存している、ということである。従って、時間20で読取った値が100と異なれば、時間30で書く値も、50とは異なるということがありえる。
次に、図19において、LP1が、グローバル・スケジューラ608に、時間15で値110の書込みメッセージを送る。これによって、グローバル・スケジューラ608によって、書込みテーブル1012に対応するエントリが書かれる。すると、読取りテーブル1014の時間20で値100のエントリと、書込みテーブル1012のエントリとを比較すると、読取りテーブル1014の時間20で値100のエントリは、時間的に書込みテーブル1012の時間10のエントリと時間30の間にあって、時間15のエントリよりも時間が後なので、図13のフローチャートのステップ1316の比較が行われ、そこでの判断がNoなので、読取りテーブル1014の時間20で値100のエントリは、無効と判別される。
こうして、図16に関連して説明したのと同様の仕組みで、LP2は、読取りテーブル1014をロールバックする。その様子は、図19の読取りテーブル1014に示すとおりである。
しかし、ロールバックによって、読取りテーブル1014の時間20で値100のエントリが無効になってしまうと、その読取り内容に依存していた書込みテーブル1012における時間30で値50のエントリは最早無効である、ということを、LP2は論理的に認識することができる。これに従い、LP2は、グローバル・スケジューラ608に、書込みテーブル1012における時間30で値50のエントリをキャンセルするメッセージを送る。それに応答して、グローバル・スケジューラ608は、書込みテーブル1012における時間30で値50のエントリをキャンセルする。その様子が、図20に示されている。この処理は、図12のフローチャートのステップ1220に至る。こうして、ステップ1206での書込みテーブル1012と読取りテーブル1014の一貫性チェックが行われる。この場合、キャンセルされたエントリを除く、書込みテーブル1012の最も新しい時間のエントリと、読取りテーブル1014のエントリとの間で、一貫性チェックを行えば十分である。
ところで、もし書込みテーブルに対して、複数の論理プロセスが同時にアクセスすることがないような排他的な仕組みをシミュレーション・システムが用意しているなら、グローバル・スケジューラ608を介することなく、直接論理プロセスが、書込みテーブルと読取りテーブルにアクセスしてよい。よって、これは別の実施例である。以下、この場合の処理について説明する。
図21は、その場合の書込み処理をフローチャートを示す。なお、読取り処理は、図11のフローチャートで既に示したとおりである。図21において、ステップ2102では、論理プロセスが直接、書込みテーブルに、時間と値をもつエントリを書込む。
ステップ2104では、その大域変数における、読取りテーブル1014と書込みテーブル1012との一貫性がチェックされ、その結果、ステップ1206で有効と判断されるか否かによって、異なる処理が行われる。ステップ1206で有効と判断されると、処理は完了する。
ステップ2104とステップ2106は、より詳細には、図13のフローチャートで示した処理であるが、既に詳細に説明したので、ここでは説明を省略する。
こうして、ステップ2106で、書込みテーブルと読取りテーブルの間に一貫性がなく有効でないと判断されると、ステップ2108で、その読取りテーブルが書込みテーブルとの一貫性がないと判断された論理プロセスに、ダウト・メッセージを送る。
ダウト・メッセージを受け取った論理プロセスは、ステップ2110で、ダウト・メッセージに含まれる内容に従い、読取りテーブルのエントリを変更する。ここでいう読取りテーブルのエントリの変更とは、図14のフローチャートに示すように、ステップ1402で論理プロセスがダウト・メッセージを受け取ると、ステップ1404で、ダウト・メッセージに含まれる大域変数の指定に対応する読取りテーブルにおいて、ダウト・メッセージに含まれる時間よりも後の時間をもつエントリを消去するか無効化し、ステップ1406で、ダウト・メッセージに含まれる時間と値のエントリを、読取りテーブルに書き込むことである。その後、必要に応じてその他のロールバック処理を行う。こうして、処理は完了する。
次に、図22と図23を参照して、この別の実施例の処理について説明する。これらの図において、グローバル・スケジューラ608は、表示されているが、処理には関与しない。
図22において、LP1が、時間10で値100のエントリを、変数1の書込みテーブル1012に書き込む。次に、時間12、17、25でそれぞれ、LP2が書込みテーブル1012のエントリの値を読取り、LP2の読取りテーブル1014に、時間と値をエントリとして順次書込んでいく。
その後、図23に示すように、LP2がステップ2102に従い、時間20で値50のエントリを、変数1の書込みテーブル1012に書き込む。すると、その書込みエントリで以って、ステップ2104に従い書込みテーブルと読取りテーブルとの一貫性のチェックが行われると、読取りテーブル1014における時間25のエントリのところで、10 <= 25 < ∞で且つ、20 < 25なので、図13のステップで、ステップ1316の判断に行き、そこで書込みテーブルの時間20のエントリと、読取りテーブル1014の時間25のエントリとが比較されて、その値が一致しないので、読取りテーブル1014のエントリは無効と判断される。この判断に応答して、LP1が、LP2に、時間20で値50の書込みに関するダウト・メッセージを送る。これに応答して、LP2は、その読取りテーブル1014において、時間25のエントリを無効にし、時間25で値50のエントリを書込む。
尚、上記実施例では、1つの大域変数毎に1つの書込みテーブルが用意されたが、本発明は、このような構成に限定されることなく、書込みテーブルに大域変数を示す欄を入れることによって、シミュレーション・システムで単一の書込みテーブルを設けるようにしてもよい。
同様に、上記実施例では、1つの大域変数につき、論理プロセス毎に1つの読取りテーブルを用意したが、本発明はやはり、このような構成に限定されることなく、読取りテーブルに大域変数と論理プロセスを示す欄を入れることによって、シミュレーション・システムで単一の読取りテーブルを使用するようにすることも可能である。
以上、自動車用の複数のシミュレーション・システムに関連して、本発明の特定の実施例を説明してきたが、本発明はこのような特定の実施例に限定されず、飛行機用のシミュレーション・システムなど、一般的な電子機械制御系システムのシミュレーション・システムに適用可能であることを、この分野の当業者であるなら、理解するであろう。