自動車は、その初期の時代の20世紀初頭は、動力としてのエンジンと、ブレーキ、アクセル、ハンドル、トランスミッション、サスペンジョンを含む、機構部品からなっていたが、エンジンのプラグの点火、ヘッドライト以外は、電気的な仕組みはほとんど利用していなかった。
ところが、1970年代頃から、大気汚染、石油危機などに備えて、エンジンを効率的に制御する必要性が生じ、このためエンジンの制御に、ECUが使用されるようになってきた。ECUは、一般的に、センサからの入力信号を、例えばA/D変換する入力インターフェースと、決められた論理に従ってディジタル入力信号を処理する論理演算部(マイクロコンピュータ)と、その処理結果を、アクチュエータ作動信号に変換する出力インターフェースとから構成される。
いまや、エンジンやトランスミッションなどの制御システム、Anti-lock Breaking System (ABS)、Electronic Stability Control (ESC)、パワーステアリングだけでなく、ワイパー制御やセキュリティ・モニタリング・システムなどに至るまで、最近の自動車では、機構部品だけでなく、エレクトロニクス部品やソフトウエアが重要な比率を占める。後者に関する開発費は全体の25%とも40%とも言われ、ハイブリッド型の自動車では70%を占める。
電子制御は、ECUを複数、配置して行われる。ECU間は車載ネットワーク、例えば、Controller Area Network (CAN) で相互に接続される。また、制御の対象である、エンジンやトランスミッションなどには、それぞれのECUから直接ワイヤリングして接続する。
ECUは、小さなコンピュータであり、センサ入力などからの割り込みに応じて動作する。一方、エンジンなどは連続的に機械的動作を行っている。すなわち、コンピュータ系のディジタル・システムと、機械系の物理システムが、自動車という単一システムにおいて、並列に協調動作を行っている。当然、これを支えるソフトウエアは複雑さがますます増大しており、ECU単体で動作を検証するだけでなく、複数を同時に検証する仕組みの実現が急務である。
ここで、ECUに信号を入力するセンサには、エンジンの温度などを計測する温度センサ、エンジンに吸入される圧力を推定するための圧力センサ、アクセスペダルの踏み量を測定するスロットル・ポジション・センサ、ステアリング舵角センサ、車高センサ、回転速度センサ、ノックセンサ、加速度センサ、流量センサ、酸素センサ、希薄空燃比センサなどがある。
一方、ECUの出力信号によって駆動されるアクチュエータには、電磁ソレノイド及びモータ等がある。ソレノイドは例えば、エンジンのインジェクタ、トランスミッションのシフト・コントロール、ブレーキのバルブ制御、ドアロックなどに使用される。
モータは、主としてサーボ機構として、エンジンのスタータ、エンジンのフューエル・コントロール、ブレーキの油圧ポンプ、舵角制御、ステアリング、ワイパ、パワーウインドウ、シートベルト、エアバックなどに使用される。
このようなテストにために従来行われている技法として、HILS(Hardware In the Loop Simulation)がある。特に、自動車全体のECUをテストする環境は、フルビークルHILSと呼ばれる。フルビークルHILSにおいては、実験室内で、本物のECUが、エンジン、トランスミッション機構などをエミュレーションする専用のハードウェア装置に接続され、所定のシナリオに従って、テストが行われる。ECUからの出力は、監視用のコンピュータに入力され、さらにはディスプレイに表示されて、テスト担当者がディスプレイを眺めながら、異常動作がないかどうか、チェックする。
しかし、HILSは、専用のハードウェア装置を使い、それと本物のECUの間を物理的に配線しなくてはならないので、準備が大変である。また、別のECUに取り替えてのテストも、物理的に接続し直さなくてはならないので、手間がかかる。さらに、本物のECUを用いたテストであるため、テストに実時間を要する。従って、多くのシナリオをテストすると、膨大な時間がかかる。また、HILSのエミュレーション用のハードウェア装置は、一般に、非常に高価である。
そこで近年、高価なエミュレーション用ハードウェア装置を使うことなく、ソフトウェアで構成する手法が存在する。この手法は、SILS(Software In the Loop Simulation)と呼ばれ、ECUに搭載されるマイクロコンピュータ、入出力回路、制御のシナリオなどを全て、ソフトウェア・シミュレータで構成する技法である。これによれば、ECUのハードウェアが存在しなくても、テストを実行可能である。
ここで、ECUエミュレータと、物理装置シミュレータ、特にエンジン・シミュレータとが協働する例について説明する。なお、以下、便宜上、ECUエミュレータとエンジン・シミュレータではなく、実際のECUとエンジンの間の動作として説明する。先ず、クランクシャフトの回転にあわせてピストンが上死点に達する30度前のタイミングで、エンジンは、ECUに割り込みを引き起こす。その割り込みを受けたECUは、燃料噴射のタイミングを計算して、その時刻に噴射の指示を出す。それを受けたエンジンは、燃料を噴射して、引き続き、惰性で回転するクランクの動作を計算する。そして、ピストンが再び上死点の30度前に達したら、エンジンは、ECUに割り込みを引き起して、ECUに知らせる。すると、ECUは、点火のタイミングを計算して、その時刻にエンジンに指示を出す。これに応じて、エンジンは、シリンダー内の燃料を爆発させて、新たな回転の動作を計算し始める。このような動作が繰り返し行われる。
このように、エンジンとECUが交互に動く動作は、クリティカル・パスとして捉えられる。従って、自動車の離散イベントを並列にシミュレーションする場合には、このようなクリティカル・パスの存在によって、計算性能の観点からみて、並列性を十分に発揮しえない。従って、マルチプロセッサ・システムのコンピュータを用いたフルビークルHILSにおいて、複数のECUエミュレータにそれぞれ、個別のCPUを割り当てたとしても、最悪の場合、1個のCPUで、複数のECUエミュレータ及びエンジン・エミュレータをシリアルに計算する程度の性能しかでないことがある。
複数の論理プロセスを並列に矛盾なく動作させるための、もっとも簡単な方法は、全体の号令にあわせて各論理プロセスを動作させることである。しかし、この方法では、割り込みなどのイベントが発生しない時刻でもすべて同期処理を行う必要があるため、処理の負荷が大きく、また、処理が遅くなる。
複数の論理プロセスを非同期的に並列に動作させる、離散イベントのシミュレーションでは、プロセス間の通信は、タイム・スタンプの付いたイベントを、メッセージとして送受信することによって行われる。このとき、タイム・スタンプは、シミュレーション・システム全体で共通の時刻が記録される。このような時刻をシミュレーション時計と呼ぶことにすると、シミュレーション時計のどの時点で処理を行うかは、各論理プロセスで独立で、必ずしも一致する必要はない。但し、各論理プロセスが協働して処理を行う場合は、必ずタイム・スタンプの順序で行う必要がある。そのように処理を進める限り、全体をシリアルに処理する場合と同じように処理を進めることができる。
非同期処理の1つに、保守的同期(conservative synchronization)がある。この方法では、必ず、タイム・スタンプの古い順位のイベントを処理する。
保守的同期の例を説明すると、ある論理プロセスに、2つの上流プロセスからのキューがあり、その一方に、時間t1をもつイベントと、時間t2をもつイベントが届いているとする。時間t1の方が時間t2よりも古いとする。また、他方のキューには何も届いていないとする。すると、その論理プロセスは、時間t1をもつイベントから順に処理していけばよさそうなものだが、時間t1よりも古い時間をもつイベントが上流から、他方のキューに届く可能性があり、すなわち、時間t1が最古であることが保証されないため、処理を進めることができない。特に、論理プロセス間に送受信のループがある構成では、このような構成ではデッドロックを引き起こすことがある。
このような状況を回避するために、空メッセージ(null message)を利用した方法が知られている。この方法では、上流の論理プロセスが、ある時刻まではイベントを発生することがないことを示すために、その時刻をもつ空メッセージを、下流の論理プロセスに送る。そのような時刻は、タイム・スタンプ上の下位境界(lower bound on the timestamp:LBTS)と呼ばれる。このような空メッセージを受け取った下流の論理プロセスは、届いているイベントのタイムスタンプと、そのLBTSとを比較し、それより古いタイム・スタンプのイベントを確定とみなして処理することができる。
空メッセージを利用しない方法として、楽観的同期(optimistic synchronization)と呼ばれる手法が考え出された。この方法では、ある論理プロセスに、2つの上流プロセスからのキューがあり、時間t1をもつイベントと、時間t2をもつイベントが届いていて、時間t1の方が時間t2よりも古いとするとき、且つ他方のキューに何も届いていないときに、とりあえず時間t1をもつイベントを最も古いと仮定して処理を進める。その後で、時間t1よりも古い時刻をもつイベントが他方のキューに届いたら、先の時間t1のイベントを発端とする一連の処理を、遡及メッセージ(reverse message)を送ることによって順に取り消してから、新たに、時間t1よりも古い時刻をもつイベントを処理する。この方法では、論理プロセスから出力されるイベントは、一時的に必ずしもタイム・スタンプどおりではないが、ロールバックにより、最終的には、タイム・スタンプどおりになることが保証される。
このような方法で、デッドロックを回避しつつ、正しい順序でイベントが送り出されるようにすることができる。しかし、このような方法では、依然として処理の直列化は回避できず、よって処理はやはり、高速化できない。
特開平6−161987号公報は、ECUハードウェアを擬似的に実現して、ソフトウェアによる実機評価を可能ならしめることを目的とするものであって、マトリックス・スイッチを切り替えることによって、所望の機能のハードウェアをシミュレートすることを開示する。
特開平11−14507号公報は、車両全体のロジックを机上で検証できるようにすることを課題とするものであり、エンジン制御模擬装置(ECU)と、車両制御模擬装置からなる車両シミュレーション装置を開示する。ECUは、エンジンモデルの制御パラメータを演算し、その演算結果を車両制御模擬装置に送信する。車両制御模擬装置は、ECUから送られてくる制御パラメータを用いて車両モデルの各部の状態量を演算してその演算結果をECUに返送する。車両モデルは、ドライバモデル、吸気系モデル、燃料系モデル、燃焼系モデル、エンジン温推定モデル、駆動系モデル、触媒モデル、A/Fセンサモデル、リアO2 センサモデルから構成されている。ドライバモデルは、目標車速の変化パターンを入力する車速パターン入力手段を有する。
しかし、これらの文献には、論理プロセス間で同期をとる技術には言及はない。そこで、本願発明者らは、2008年6月18日に出願した特願2008−158995号特許出願において、各ECUエミュレータを、投機的にエミュレートする技法を提示した。すなわち、その発明によれば、クリティカル・パスを作らずに、各論理プロセスをできるだけ並列に実行させるために、ECUエミュレータや各物理装置シミュレータなどの各論理プロセスにおいて、入力イベントが届いていない場合でも、入力を予測して処理が進められる。このような投機的実行により、他の論理プロセスの出力を待つことなく、先行して処理を行うことにより、処理の並列性が高められる。そうして、もし遅れて受信する実際の入力と、予測して投機実行したときの入力が一致していない場合には、投機実行が失敗だったとして、その前の時刻に状態が戻され、その実際の入力に基づき、処理が再実行される。
特開平6−161987号公報
特開平11−14507号公報
特願2008−158995号明細書
以下、図面を参照して、本発明の一実施例の構成及び処理を説明する。以下の記述では、特に断わらない限り、図面に亘って、同一の要素は同一の符号で参照されるものとする。なお、ここで説明する構成と処理は、一実施例として説明するものであり、本発明の技術的範囲をこの実施例に限定して解釈する意図はないことを理解されたい。
本発明を実現するための構成を説明する前に、その前提として、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にはさらに、後述する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は、ECUエミュレータ・プログラム604の内部の、より詳細な論理ブロック図を示す。ここでは、ECUエミュレータ・プログラム604a、604b、・・・604nなどを、総称的に、ECUエミュレータ・プログラム604として説明する。
ECUエミュレータ制御ロジック・モジュール702は、いわゆるECUエミュレータの本来のロジックを含む本体である。
ロールバック表704は、前述したラッパコード付加の方法で、制御ロジック・モジュール702から取り出した内部状態変数を順次保存する機能をもつ。
ローカル・スケジューラ706は、ロールバック表704に保存されている内部状態変数を、制御ロジック・モジュール702に書き戻すことにより、ECUエミュレータ・プログラム604を所望の状態に戻す機能を持つ。
なお、制御ロジック・モジュール702には、共有メモリ602から、通信インターフェース・モジュール708を介して、イベント入力が提供される。
ECUエミュレータ・プログラム604はさらに、機能ブロックとして、判断ブロック710、閾値ブロック712及び予測ブロック714をもつ。
閾値ブロック712は、受信する実際の入力と、予測して投機実行したときの入力が一致しているとみなす基準となる許容誤差値の累積ヒストグラムを保持する。予測して投機実行したときの入力は、ロールバック表704に記録された入力から、タイムスタンプに従い、選ばれる。この累積ヒストグラムは、メイン・メモリ506上のECUエミュレータ・プログラム604専用のメモリ領域、または、ハードディスク516の所定の領域に保存されている。なお、累積ヒストグラムの作成処理については、後述する。
予測ブロック714は、予測して投機実行したときの入力を与える。この実施例では、基本的には、前回の入力と同じ入力を、投機実行入力として与える。
判断ブロック710は、受信した実際の入力と、予測して投機実行したときの入力とを比較する。このとき、閾値ブロック712から提供された値を許容誤差として用い、受信した実際の入力と、予測して投機実行したときの入力の値の差がこの許容誤差範囲内のとき、それらが一致しているとの判断を与え、そうでないとき、不一致の判断を与える。
なお、図示しないが、ECUエミュレータ604は、入力イベントを一旦格納するためのキューをもつ。キューは、ローカル・スケジューラ706内に設けてもよいし、メイン・メモリ506内の専用のプライベート・メモリ領域内に設けてもよい。
例えば、エアコンECUの出力は、エンジンECUに入力される。エアコンの駆動状態に応じて、エンジンの回転数を変え、以って発電量を調整する必要があるからである。
通信インターフェース・モジュール708は、制御ロジック・モジュール702からの出力を、共有メモリ702または、CAN(controller area network)エミュレータ(図示しない)に送出する。
次に、ECUエミュレータ604の閾値ブロック710に記録される誤差分布の概念について説明する。統計的に、投機入力の誤差が、指数分布に従う場合を示す。
指数分布の確率密度関数f(x) = μe-μxのグラフは、図8に示すとおりである。すなわち、誤差が小さいほど、生起確率が高い。
図9は、指数分布の累積分布関数F(x) = 1 - e-μxのグラフを示す。この累積分布関数に従うと、図示するように、百分率を与えると、許容誤差εが得られる。
図10の(A)は、あるECUエミュレータにおける、受信した実際の入力と、予測して投機実行したときの入力の値の誤差のヒストグラムである。横軸は、誤差xで、縦軸は度数である。このようなヒストグラムは、各ECU毎に、次のようにして記録される。先ず、許容誤差を0として、シミュレーション処理を行う。具体的なシミュレーション処理は、図15に関連して、後で詳細に説明する。
こうして、実際の入力が与えられる度に、予測値と入力の値の絶対値
|予測値 - 実測値|が、計算される。その値に応じて、予め等間隔Δのレンジに区切られたビンのカウンタがインクリメントされる。すなわち、予測値と入力の値の絶対値xが、
i * Δ <= x < (i+1) * Δ (i = 0,1,...,N-1)をみたすとき、i * Δに対応するカウンタが、1だけインクリメントされる。
結果的に、図10の(A)のような等間隔Δ刻みのヒストグラムが得られる。このような計算は、ヒストグラムの十分な精度が得られた時点で一旦完了し、以下で計算する累積ヒストグラムに基づく閾値に切り替えられる。
ヒストグラムの十分な精度が得られたとは、観測数が十分に大きくなったということであり、さらに言うとそれは予測値との差の絶対値が閾値より大きいサンプルが、一定数(例えば、20)を超えた、ということである。より一般的に言うと、予測値との差の絶対値が閾値より大きいサンプルの数をMとすると、Mの平方根を、全体のサンプル数Nで割った数が十分小さくなることを意味する。
Δiに対応するカウンタを、h[i]とすると、累積ヒストグラムを得るために、次のようなc[i]を計算する。なお、以下では、例示的にC言語の記法を用いる。ここでは、h[i]は整数であり、一方、c[i]は、浮動小数点数とする。
c[0] = h[0];
for ( i = 1; i < N; i++ ) // 累積値の計算
c[i] = c[i-1] + h[i];
for (i = 0; i < N; i++ ) // 全体の合計 c[N-1]で正規化
c[i] /= c[N-1];
この結果、c[i] を、 i = 0, 1, 2, ,,,, N - 1 の順に並べると、図10(B)に示すように、1に漸近する累積ヒストグラムとなる。
こうして累積ヒストグラムが得られると、ある値p ∈ [0,1]が与えられたとき、
c[i] <= p < c[i+1]を満たすiを求め、ε = i * Δで、閾値εを決定する。但し、p < c[0]である場合は、ε = 0とする。もちろん、このような計算は、メモリ上の累積ヒストグラムを参照して、コンピュータにより、自動的に計算される。
図11に示すように、このような正規化された累積ヒストグラムは、ECU#1、ECU#2、・・・ECU#n毎に個別に記録されて計算され、保存されている。見て取れるように、ECU毎に実際の入力と、予測して投機実行したときの入力の誤差の特性が異なるので、累積ヒストグラムの曲線も、ECU毎に異なる。従って、ECU#1、ECU#2、・・・ECU#nの各々の累積ヒストグラムは、同一のpに対して、異なる閾値ε1、ε2、・・・εnを返す。
図12は、オペレータが閾値を設定するための、グラフィック・ユーザ・インターフェース(GUI)を示す図である。このGUIにおいて、目盛り1202は、0から100までのスケールをもち、マウス512(図5)のドラッグによって、スライダ1204をずらすことによって、0と100の間の数を、精度として設定する。設定した精度は、表示領域1206に表示される。なお、ここに表示したGUIは、閾値設定のための一例に過ぎず、単にテキスト・フィールドに数字を打ち込んだり、周知のアップダウンコントローラのインターフェースを使用するなど、当業者が適当と判断する任意のインターフェースを使用できることを理解されたい。なお、このようなGUIの作成は、Windows(R)においては、適当なWin32 APIを用いて実現できることが、この分野の当業者に明らかであろう。他のオペレーティング・システムでも同様であって、この発明の特徴ではないので、これ以上の説明は省略する。
さて、ここに設定した数字をPとすると、p = P/100 として計算された値pが、図13に示すように、閾値を決める共通のパラメータとして、ECU#1 604a、ECU#2 604b、・・・ECU#n 604nの閾値ブロック712(図7)に提供される。パラメータを提供する方法としては、共通メモリ602の所定の領域に置いて、ECUエミュレータにアクセスさせる方法、あるいは、後述するグローバル・スケジューラ608によって、同報メッセージとして通信させる方法などがある。なお、ここに記したGUIでの数値パラメータの与え方は、ほんの一例であって、この分野の当業者であるなら、その他の変形例を思いつくであろう。例えば、目盛1202とスライダ1204で、直接、pの値である、0.0から、1.0までの間の値を指定するようにしてもよい。
図14は、閾値設定処理のフローチャートである。ステップ1402では、図12に示すスライダ1204が移動されたかどうかのイベントが待機され、もしマウス操作などで、スライダ1204が移動されると、ステップ1404では、そのスライダ1204が示す位置の値が読み取られる。スライダ1204を移動している間は設定値が定まらないので、スライダ1204が移動された後一定時間スライダ1204が移動されない、というイベントに応答して位置を値を読み取るようにしてもよい。
ステップ1406では、設定した値 pの値が、各ECUエミュレータに送られる。
ステップ1408では、各ECUエミュレータで、送信された値pから、各ECUエミュレータに保持されている累積ヒストグラムが参照され、図11でε1、ε2、・・・εnなどと示されている、誤差εが決定される。
ステップ1408ではさらに、このように設定された誤差εが、閾値ブロック712(図7)に設定されて、その後のシミュレーション処理に使用される。
次に、図15のフローチャートを参照して、ECUエミュレータの処理について処理を説明する。ここでの処理の大部分は、図7に示すローカル・スケジューラ706によって、主に行われる。まず、図15のステップ1502では、キューに、他の論理プロセスからイベントが到来しているかどうかが判断される。もしキューにイベントがあると、ステップ1504では、最も古いイベントeが取り出される。このイベントeのタイム・スタンプをtとする。
ステップ1506では、t = tkをもつエントリが、ロールバック表中にあるかどうかが判断される。ロールバック表とは、図16に示すように、タイム・スタンプ、入力イベント、出力イベント、内部状態、及び確定フラグからなり、後述する処理により、好適にはそのECUエミュレータに割り当てられた、メイン・メモリ506中の領域に書かれる。メイン・メモリ506ではなく、ハードディスク・ドライブ516に書かれてもよい。
また、図16から見て取れるように、ロールバック表は、2通りのエントリをもつ。1つは、入力イベントのエントリであり、タイム・スタンプの欄と、入力イベントの欄のみが有効である。
もう1つは、出力イベントのエントリであり、出力のタイム・スタンプの欄と、出力イベント、そのときの内部状態、及び確定フラグである。ロールバック表に内部状態を保持することは、途中から計算を再開するために有利である。なお、前述したラッパ・コードの技法により、もともと内部状態を暗にもつエミュレータの論理を、内部状態を状態変数として外部に取り出した論理に変更することができる。
ロールバック表中に、t = tkをもつエントリがあると、そのエントリをekとすると、e = ekであるかどうかが、ステップ1508で判断される。この比較は、図7に示す判断ブロック710によって、閾値ブロック712に設定された許容誤差値εを参照して行われる。e = ekという判断は、
|e - ek| < εであるなら、判断ブロック1508の判断が肯定的であるように、処理が行われる。ステップ1508での判断が肯定的である、ということは、先の投機的実行が成功であった、とシステムが見做すことを意味をする。そこで、処理は、最初のステップ1502に戻る。許容誤差値εを考慮してもe = ekでないなら、すなわち、
|e - ek| >= εであるなら、処理は、ステップ1510に進む。
ステップ1506で、t = tkをもつエントリが、ロールバック表中にないと判断されると、ステップ1510で、確定時間Tに戻って、それ以降の時間をもつロールバック表中のエントリが削除される。図16では、点線以下のエントリである。尚、確定時間Tは、後述するグローバル・スケジューラ608の処理によって通知されたものである。
ステップ1512では、時刻tとイベントeから、新しいエントリが作成され、それがロールバック表中に挿入される。
ステップ1514では、確定エントリの内部状態を使って、制御ロジック・モジュール702によって、新たなイベント処理が行われる。ここでいう内部状態とは、図4に、状態変数として示されているものである。
ステップ1516では、そのイベント処理の結果として生成された出力イベントが、ロールバック表に挿入される。ステップ1518では、その出力イベントが、通信インターフェース・モジュール708を介して、それは、所定の物理装置シミュレータに送られる。この送り方であるが、共有メモリ方式ならば、特定のメモリのアドレスに書いてシグナルされるし、CANエミュレータ方式の場合、送り出すメッセージに、所定の宛先を含むヘッダを付けることになる。このような処理は、図7に示す通信インターフェース・モジュール708によって、行われる。そうして処理は、ステップ1502に戻る。
ステップ1502で、キューにイベントがないと判断されると、ステップ1520では、図7の予測ブロック714によって、新しい入力イベントが予測される。例えば、エンジン・シミュレータ用のECUエミュレータの場合、ほぼ周期的にイベントが入来すると予測されるので、その予測に従って、ステップ1522で、その予測された新しいイベントをキューに入れ、処理がステップ1502に戻る。
尚、キューにイベントが到着しない間に、連続して予測に基づく処理を進めると、確定しないエントリがロールバック表を占めて、そのサイズが巨大になることがある。それを防止するために、ロールバック表中の未確定のエントリの数に上限を設けて、それを超えないようにシステム的に調節する。また、確定したエントリは、最後の一つを除いて破棄することにより、不要なエントリが、ロールバック表のサイズを圧迫することがないようにする。
図17に示すように、グローバル・スケジューラ608は、論理プロセスLP#1〜LP#N毎にキューQ1〜Qnをもつ。論理プロセスとは各々、図7に示すECUエミュレータ#1〜#n、物理装置シミュレータ#1〜#m、のどれかである。
キューQ1〜Qnには、対応する論理プロセスLP#1〜LP#Nから、随時にイベントが入来し、入来したイベントは、キューに一旦格納される。グローバル・スケジューラ608は、キューQ1〜Qnに格納されているイベントに基づき、確定イベントと、確定時間を出力する。
図18は、そのためのグローバル・スケジューラ608の処理を示すフローチャートである。ステップ1802で、グローバル・スケジューラ608は、どれかのキューQ1〜Qn(図17)に、新しいイベントが到来するのを待つ。
ステップ1804では、空のキューにイベントが届いたかどうかが判断され、そうでなければ、処理は、ステップ1802に戻る。
ステップ1804で、空のキューにイベントが届いたと判断されると、ステップ1806に行って、そこで、すべてのキューQ1〜Qnが少なくとも1つのイベントをもつかどうかが判断される。そうでなければ、やはり処理は、ステップ1802に戻る。
ステップ1806で、すべてのキューQ1〜Qnが少なくとも1つのイベントをもつと判断されると、ステップ1808では、すべてのキューQ1〜Qnの中で、最も古いイベントが見出される。このことは、すべてのイベントには、タイム・スタンプがつけられていることにより可能である。
ステップ1810では、見つけられた最も古いイベントが、確定イベントとされ、論理プロセスLP#1〜LP#Nに通知される。
ステップ1812では、確定イベントがキューから取り除かれる。そして、ステップ1802に戻り、グローバル・スケジューラ608は、次のイベントの到着を待つ。
本実施例のシステムによるシミュレーションのシナリオは、次のとおりである。初期段階では、図11に示すような誤差のヒストグラムのデータは、全くないとする。すると、最初は、許容誤差0で、シミュレーションが行われる。シミュレーションを行いつつ、図15のステップ1508の比較のところで、受信する実際の入力と、予測して投機実行したときの入力の差が計算されるので、これを記録することによって、誤差ヒストグラムのデータが蓄積されていく。
最初は、許容誤差0なので、ある一定数のサンプル(例えば、100個)が集まった段階で、各ECUエミュレータで、図10に示すように、誤差ヒストグラムを、累積ヒストグラムに変換する処理が行われる。このことは、好適には、コンピュータの処理により自動的に行われる。
一旦図11に示すように各ECUエミュレータに、累積ヒストグラムが構成されると、図12に示すGUIによって、許容誤差を設定することができる。
オペレータは、許容誤差0で、シミュレーションを開始する。すると、図15のステップ1508の判断がNOになる可能性が比較的高くなるので、ステップ1510以下でロールバックが起きて、シミュレーション速度は低下する。
そこから、オペレータが、図12に示すGUIによって、許容誤差0から次第に許容度を高めていくと(これは、図12では、スライダ1204を、目盛0から次第に右にずらしていくことを意味する)、許容誤差εが増え、図15のステップ1508の判断がYESになる可能性が次第に上がってきて、すると、ステップ1510以下でロールバックに進む頻度が減るので、結果的に、シミュレーション速度は向上する。
こうして、許容誤差を増やしていくと、ある許容誤差の値で、シミュレーション結果が急変する現象が観察される。それは、必要なロールバックが行われなくなったことを推定させる。すると、最早正しいシミュレーション結果が得られなくなるので、許容誤差の値を減らす必要があることを意味する。
このような処理によって、オペレータは、シミュレーション速度と、シミュレーションの正確さの両方の観点で、最適な許容誤差を選んで設定することが可能となる。
なお、上記実施例では、各ECUエミュレータについて、一旦、実際の入力と、予測して投機実行したときの入力の誤差に関する、正規化された累積ヒストグラムを作成し、これに対する共通の百分率に対応する許容誤差値で、シミュレーションを行うようにしているが、シミュレーションの性質によっては、個々のECUエミュレータに対して、直接、個別に、許容誤差値を設定するようにしてもよい。
しかし、最近のように、一台の自動車に、30個乃至50個のECUが搭載されるようなシステムにおいて、個々のECUエミュレータに、オペレータの判断により、個別に最適な許容誤差値を設定するのは、相当困難困難であると想定される。なぜなら、オペレータには、個々のECUエミュレータの特性は、分からないからである。
従って、上記実施例のような、正規化された累積ヒストグラムを、個々のECUエミュレータを作成することは、個々のECUエミュレータの特性の違いを吸収して、単一の共通の百分率のパラメータで、個々に許容誤差値を設定することを可能ならしめる点で、有利である。
以上、自動車用の複数のECUエミュレータを含むテスト・システムに関連して、本発明の特定の実施例を説明してきたが、本発明はこのような特定の実施例に限定されず、飛行機用のECUエミュレータを含むテスト・システムなど、一般的な電子機械制御系システムのテスト・システムに適用可能であることを、この分野の当業者であるなら、理解するであろう。