JP2008059192A - ハード・ソフト協調検証用シミュレータ - Google Patents

ハード・ソフト協調検証用シミュレータ Download PDF

Info

Publication number
JP2008059192A
JP2008059192A JP2006234298A JP2006234298A JP2008059192A JP 2008059192 A JP2008059192 A JP 2008059192A JP 2006234298 A JP2006234298 A JP 2006234298A JP 2006234298 A JP2006234298 A JP 2006234298A JP 2008059192 A JP2008059192 A JP 2008059192A
Authority
JP
Japan
Prior art keywords
time
cpu
simulation
function
tid
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
JP2006234298A
Other languages
English (en)
Inventor
Noriyoshi Ito
徳義 伊藤
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Oki Electric Industry Co Ltd
Original Assignee
Oki Electric Industry Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Oki Electric Industry Co Ltd filed Critical Oki Electric Industry Co Ltd
Priority to JP2006234298A priority Critical patent/JP2008059192A/ja
Publication of JP2008059192A publication Critical patent/JP2008059192A/ja
Pending legal-status Critical Current

Links

Images

Landscapes

  • Debugging And Monitoring (AREA)
  • Test And Diagnosis Of Digital Computers (AREA)

Abstract

【課題】コンテキスト切り替え制御のオーバーヘッドを減少させて処理時間を短縮することが可能な、SystemCシミュレータをベースとしたハード・ソフト協調検証用シミュレータを提供する。
【解決手段】ハードウエアとソフトウエアのシミュレーション・モデルとして生成された複数のスレッドに対応して、そのシミュレーション時刻を制御するためのタイムキーパーを設ける。各タイムキーパー12は、スレッド毎のシミュレーション時刻Tsimを保持する変数X、積算時間Tsumを保持する変数Y、及び中断時刻と対応する中断メソッドを格納する中断要求待ち行列Qを有し、スレッドから6種類のメソッド呼び出しに応じて変数x,yと待ち行列Qを管理し、必要な場合にSystemCシミュレータ11のwait関数を呼び出す。これにより、wait関数呼び出し回数が削減され、全体の処理時間が短縮できる。
【選択図】図1

Description

本発明は、ハードウエア設計やシステムレベル設計における論理検証や、ハードウエアとソフトウエアの協調検証を高速化するためのC言語ベースのハード・ソフト協調検証用シミュレータに関するものである。
従来、組み込みシステムのCPU(Central Processing Unit)、メモリ、バス、周辺デバイス等の動作を模擬したシミュレーション・モデル上で、リアルタイムOS(Operation System)、デバイスドライバ、アプリケーション・プログラム等からなるソフトウエア動作を検証する協調検証には、HDL(Hardware Description Language)を用いたシミュレータが使用されていた。しかし、HDLを用いたシミュレータでは、高速化が困難なため、例えば下記非特許文献1に記載されるような、C言語ベースのモデル記述言語を用いたシステムレベルのシミュレータが提案され、使用されるようになってきている。シミュレーションを高速化することにより、ハードウエアの詳細設計やLSI(Large Scale Integration)設計が完了する前に、ソフトウエアを含めたシステムレベルの事前検証が可能になる。
通常のC言語では、ハードウエアの遅延時間やCPUの実行サイクル数を反映したシミュレーションの実現が困難であるため、SpecCやSystemC等のハードウエアモデル記述用言語が提案され、標準化が進められている。
SystemCシミュレータでは、1つの起動中のタスクから起動できるスレッド(Thread)と呼ばれるより小さなモジュール単位で並行動作しているプロセスを実現している。また、SystemCシミュレータには、シミュレーション時刻を制御するためのwait関数が用意されている。wait関数は、SystemCシミュレータのカーネル(本体)で管理しているシミュレーション時刻を、wait関数呼び出しの引数として与えられた経過時間だけ進めると共に、並行して動作しているスレッド間のコンテキスト切り替えの制御を行うものである。なお、コンテキストとはシミュレーションを実行しているプロセッサの状態を指し、コンテキスト切り替えとは実行中のスレッドのコンテキストから別のスレッドのコンテキストに切り替えることを言う。
従って、SystemCシミュレータを使用して協調検証のシミュレーションを行う場合、並行動作を行うスレッドを、wait関数によって順次切り替えて制御することにより、ソフトウエアを含めたシステムレベルの検証を行うことができる。
特開2005−293219号公報 特開2006−23852号公報 Open SystemC Initiative,"SystemC 2.0.1 Language Reference Manual",Revision1.0
しかしながら、前記SystemCシミュレータを使用した協調検証のシミュレーションでは、wait関数を呼び出すたびにスレッド間のコンテキスト切り替え制御が行われることになるため、頻繁に行われるコンテキスト切り替え制御によってオーバーヘッドが大きくなり、シミュレーション速度の低下の一因となっている。
本発明は、コンテキスト切り替え制御のオーバーヘッドを減少させることによってシミュレーション時間を短縮することができる、SystemCシミュレータをベースとしたハード・ソフト協調検証用シミュレータを提供すること目的としている。
本発明は、ハードウエアとソフトウエアの協調検証を行うためのC言語ベースのハード・ソフト協調検証用シミュレータであって、ハードウエア及びソフトウエアに対応するシミュレーション・モデルを構成する複数のスレッド毎に設けられ、それぞれが対応するスレッドのシミュレーション時刻を制御するために、シミュレーション時刻を保持する第1の変数、積算時間を保持する第2の数、中断時刻と対応する中断メソッドを格納する中断要求待ち行列、及び処理用の関数を備えた複数のタイムキーパーと、これらのタイムキーパーからの要求に応じて、管理しているシステム時刻を与えられた要求時間だけ進めると共に、並行して動作している前記スレッド間のコンテキスト切り替えを制御するC言語ベースのシミュレータ本体とを備えたことを特徴としている。
本発明では、ミュレーション・モデルを構成する複数のスレッド毎に、各スレッドのシミュレーション時刻を保持するための第1の変数、積算時間を保持するための第2の変数、中断時刻と対応する中断メソッドを格納するための中断要求待ち行列、及び処理用の関数を備えたタイムキーパーを設けている。これにより、各スレッドのシミュレーション時刻が対応するタイムキーパーによって管理されるので、シミュレータ本体のwait関数を呼び出す頻度が減少し、このwait関数呼び出しに伴うコンテキスト切り替え制御のオーバーヘッドが減少してシミュレーション時間が短縮されるという効果がある。
この発明の前記並びにその他の目的と新規な特徴は、次の好ましい実施例の説明を添付図面と照らし合わせて読むと、より完全に明らかになるであろう。但し、図面は、もっぱら解説のためのものであって、この発明の範囲を限定するものではない。
図1は、本発明の実施例を示すシミュレータの構成図である。
このシミュレータ10は、SystemCシミュレータをベースとしてハードウエアとソフトウエアの協調検証を行うもので、従来のSystemCシミュレータ11の前段に複数のタイムキーパー12を設けたものである。
このシミュレータ10には、ハードウエアのシミュレーション・モデル1と、ソフトウエアのシミュレーション・モデル2が接続されるようになっている。
ハードウエアのシミュレーション・モデル1は、逐次的に実行されるCPUや周辺デバイス毎にその機能をSystemC言語でモデル化したもので、デバイス毎に作成された複数のスレッドで構成される。また、ソフトウエアのシミュレーション・モデル2は、C言語で記述されたリアルタイムOS、ドライバ、アプリケーション等のプログラムを、例えば、特許文献1に記載されたツールを利用して、SystemCモデルに変換した複数のスレッドで構成されている。
タイムキーパー12は、逐次的に実行されるデバイスやプログラム毎に、そのシミュレーション時刻を制御するためのもので、例えば、複数のマルチタスク環境のCPUでは、タスク間の実行制御が逐次的に行われるため、このCPUのシミュレーション時刻を統一的に管理する1つのタイムキーパー12が用意される。これに対して、複数のステートマシンが並列動作するようなデバイスに対しては、逐次的に実行される各ステートマシンをインプリメントするスレッド毎にタイムキーパー12が用意される。
各デバイスやプログラムのスレッドに対応して用意されたタイムキーパー12はチャネル接続され、各スレッドからチャネル接続されたポートを介して必要に応じて参照できるようになっている。
各タイムキーパー12は、それぞれシミュレーション時刻Tsimを保持する変数Xと、積算時間Tsumを保持する変数Yと、中断時刻と対応する中断メソッドを格納する中断要求待ち行列Qと、current_timeメソッド、current_sc_timeメソッド、flush_timeメソッド、break_timeメソッド、sum_timeメソッド及びsync_timeメソッドの6個のメソッドを有している。
current_timeメソッド(第1の関数)は、現在のシミュレーション時刻Tsimを戻り値として返す関数である。
current_sc_timeメソッド(第2の関数)は、SystemCシミュレータのカーネルで管理しているシミュレーション時刻(以下、システム時刻Tsysと呼ぶ)に相当するTsim-Tsumの値を戻り値として返す関数である。
flush_timeメソッド(第3の関数)は、積算時間Tsumを引数とするSystemCシミュレータのwait関数を呼び出した後、その積算時間Tsumをゼロクリアする関数である。なお、フラッシュ(flush)とは、ゼロクリアを意味する。
break_timeメソッド(第4の関数)は、引数として与えられた中断時刻bTsim、中断システム時刻bTsys、及び中断メソッドを中断要求として、タイムキーパーの中断要求待ち行列Qに登録する関数である。ここで、中断メソッドは、sum_timeメソッドにおいてシミュレーション時刻Tsimが中断時刻bTsim以上になった場合に呼び出される関数を示している。複数のバスマスタが同一周辺デバイスに対して、中断時刻と対応する中断メソッドを登録する場合に対応するため、これらは中断要求待ち行列Qとして管理されている。中断要求待ち行列Qの先頭には最も小さい中断時刻が格納され、中断時刻が大きくなる順序で格納されるようになっている。なお、初期化時に、中断要求待ち行列Qの内容は空に設定される。
sum_timeメソッド(第5の関数)は、中断要求待ち行列Qの状態に従って次の処理を行う関数である。
中断要求待ち行列Qが空の場合、シミュレーション時刻Tsimに経過時間timeを加算してこのシミュレーション時刻Tsimを進めると共に、積算時間Tsumに経過時間timeを加算してこの積算時間Tsumを更新する。
中断要求待ち行列Qが空でない場合は、シミュレーション時刻Tsimと中断要求待ち行列Qにおける先頭中断要求の中断時刻bTsimの関係により、処理が異なる。
シミュレーション時刻Tsimが中断時刻bTsim未満の場合、シミュレーション時刻Tsimに経過時間timeを加算してこのシミュレーション時刻Tsimを進めると共に、更新したシミュレーション時刻Tsimが中断システム時刻bTsysより小さいときは積算時間Tsumをゼロクリアし、そうでないときは積算時間Tsumを(Tsim-bTsys)の値に設定する。
シミュレーション時刻Tsimが中断時刻bTsim以上の場合、中断要求待ち行列Qの内で中断時刻bTsimがシミュレーション時刻Tsim以上であるすべての中断要求に対し、積算時間Tsumを(Tsim-bTsys)の値に設定して中断メソッドを呼び出した後、これらの中断要求を待ち行列Qから削除する。その後、シミュレーション時刻Tsimに経過時間timeを加算してこのシミュレーション時刻Tsimを進めると共に、積算時間Tsumに経過時間timeを加算してこの積算時間Tsumを更新する。
sync_timeメソッド(第6の関数)は、引数として与えられるシミュレーション時刻sTsimとタイムキーパーの現在のシミュレーション時刻Tsimを比較し、Tsim<sTsimの場合にsTsimと更新後のTsimの差分を引数としてsum_timeメソッドを呼び出す関数である。これにより、シミュレーション時刻TsimはsTsimの値に更新され、積算時間Tsumは(Tsum-sTsim-Tsim)の値に更新される。なお、Tsim≧sTsimの場合には、sum_timeメソッドの呼び出しは行われない。
上記の積算時間Tsumは、タイムキーパー12で更新しているシミュレーション時刻TsimとSystemCシミュレータ11のwait関数呼び出しによって更新されるシステム時刻Tsysとの差分時間を示している。従って、flush_timeメソッドを呼び出して積算時間Tsumをゼロクリアしたときには、シミュレーション時刻Tsimとシステム時刻Tsysは一致する。また、中断要求待ち行列Qが空であるとき、sum_timeメソッドは積算時間Tsumと経過時間timeを加算した値によってこの積算時間Tsumを更新する。
このシミュレータ10では、各デバイスがシミュレーション時刻をSystemCシミュレータ11のwait関数を呼び出して進めるのではなく、そのデバイスのタイムキーパーtikに対して、tik->
sum_timeメソッド呼び出しを行うことによって進めるようになっている。
他のデバイスに制御を切り替えたい場合は、現在実行中のデバイスのタイムキーパーtikに対して、tik->
flush_timeメソッド呼び出しを行う。これにより、タイムキーパーtikの積算時間Tsumを引数とするSystemCシミュレータ11のwait関数を呼び出しが行われる。このwait関数呼び出しにより、SystemCシミュレータ11のカーネル内で管理している実行中のデバイスのシステム時刻Tsysが積算時間Tsumで指定される時間だけ進められると共に、実行可能なデバイスの内で最もシステム時刻Tsysの小さいデバイスに制御が渡されるコンテキスト切り替え制御が行われる。
デバイス間でシミュレーション時刻を同期させる必要がある場合、sync_timeメソッド呼び出しを行う。あるデバイスのタイムキーパーdtikのシミュレーション時刻を、他のデバイスのタイムキーパーstikの現在のシミュレーション時刻に設定する場合、dtik->sync_time(stik->current_timeメソッド)メソッド呼び出しを行う。つまり、sTsim=stik->current_timeメソッド呼び出しによってタイムキーパーstikの現在のシミュレーション時刻sTsimを求め、このsTsimを引数としてdtik->
sync_timeメソッド呼び出しを行うことにより、タイムキーパーdtikのシミュレーション時刻がsTsimに設定される。
デバイスのタイムキーパーdtikに対して中断時刻bTsim、中断システム時刻bTsys、及び中断メソッドを中断要求として登録する場合、tik->break_timeメソッド呼び出しを行う。これにより、タイムキーパーtikにおいてtik->sum_timeメソッド呼び出しを行ってシミュレーション時刻の更新を行う前に、このタイムキーパーtikのシミュレーション時刻が中断時刻bTsim以上に達した場合、TikIFクラス内で定義された中断メソッドの呼び出しが行われる。中断メソッドとしてflush_timeメソッドを指定した場合には、この中断メソッド呼び出しによって他のデバイスへのコンテキスト切り替え制御が行われる。
以下、具体例を用いて図1のシミュレータ10の動作を説明する。なお、以下の説明におけるシミュレーション記述言語は、C言語に準じている。
(A)sum_timeメソッドの機能
デバイスにおけるシミュレーション時刻の制御は、そのデバイスに対応したタイムキーパーに対してsum_timeメソッド呼び出しを行うことによって実現される。
例えば、CPUとそのタイムキーパーctikをチャネル接続するために、SystemCシミュレータにおいて次のようなCPUクラスを定義する。
class cpu:public sc_module
{
public:
sc_port<tikIF,0>ctik //port to CPU Time Keeper
SC_CTOR(CPU){
SC_THREAD(main);
}
void main(void)
}
ここで、tikIFはタイムキーパーのメソッド関数を定義するインタフェース定義で、例えば以下のように定義される。
class tikIF:public sc_interface{
public:
virtual void break_time(uint64 bTsim,uint64 bTsys,void(TikIF::*method)())=0;
virtual void flush_time(void)=0;
virtual void sum_time(long time)=0;
virtual uint64 current_time(void)=0;
virtual void sync_time(uint64 sTsim)=0;
};
上記のCPUクラス定義における以下の記述は、tikIFインタフェースを持つ任意の数のチャネルをtikポートに接続可能であることを意味する。
sc_port<tikIF,0>ctik; //port to CPU Time Keeper
また、CPUクラス定義における以下の記述は、シミュレーション開始時にmain関数をCPUスレッドとして起動することを意味している。
SC_CTOR(CPU){
SC_THREAD(main);
}
CPUとタイムキーパーctikの接続は、これらのクラス定義の上位階層において以下のように行う。
cpu =new cpu(“cpu”); //CPUを生成
ctik =new tik(“ctik”); //CPU用タイムキーパーを生成
cpu->tik(*ctik); //CPUにCPU用タイムキーパーを接続
CPUのtikポートに接続されたどのタイムキーパーを参照するかは、上位階層においてタイムキーパーが接続された順に、tik[0],tik[1],…のように指定する。また、どのタイムキーパーを参照するかを指定するためのタイムキーパー識別氏のデータタイプtid_tを、例えば、以下のように定義する。
typedef enum{C_TID=0,P_TID=1,…
} tid_t;
ここで、C_TIDとP_TIDは、それぞれCPUとの周辺デバイスのタイムキーパー識別子である。このようにして、tikポートへのタイムキーパーの接続を、tid_tで定義しているタイムキーパー識別子の番号順に、CPUのタイムキーパー、周辺デバイスのタイムキーパー、…のように接続すれば、tik[C_TID]はCPUのタイムキーパーを参照し、tik[P_TID]は周辺デバイスのタイムキーパーを参照するということになる。
上記の上位階層におけるCPUへのタイムキーパーの接続では、CPUにタイムキーパーctikのみしか接続されないので、tik[C_TID]ポートを介したアクセスのみが可能である。これにより、CPUのmainスレッドからtik[C_TID]ポートを介してCPUのタイムキーパーctikのメソッド呼び出しが可能になる。
図2は、CPUのmainスレッド切り替え制御の説明図であり、縦軸はシミュレーション時刻を示している。
経過時間cT1,cT2,…,cTkは、CPUにおける命令実行時間で、CPUモデルとして例えば、命令セットシミュレータを使用する場合には、実行される各命令の実行時間となる。この場合、CPUのmainスレッド関数は、以下のように定義される。
void CPU::main(void){
tik[C_TID]->sum_time(cT1);
tik[C_TID]->sum_time(cT2);
tik[C_TID]->sum_time(cTK);
}
CPUのmainスレッドは、ctikポートを介してtik[C_TID]->sum_time(cT1),tik[C_TID]->sum_time(cT2),…,tik[C_TID]->sum_time(cTK)メソッドを呼び出すことにより、シミュレーション時刻Tsimを進める。この図に示すように、CPUスレッドがi番目の経過時間cTiを引数とするtik[C_TID]->sum_time(cTi)メソッドを呼び出すと、ctikのsum_timeメソッドにおいて、積算時間Tsumとシミュレーション時刻Tsimに、cTiの値が加算される。
tik[C_TID]->sum_time(cTK)メソッド呼び出しの後の積算時間cTsumKと、シミュレーション時刻cTsimKは次式で与えられる。
cTsumK=cT1+cT2+…+cTK
cTsimK=cTsum0+cTsumK=cT0+cT1+cT2+…+cTK
ここで、cTsum0は、tik[C_TID]->sum_time(cT1)メソッドを呼び出す前のシミュレーション時刻である。このように、スレッド内のシミュレーション時刻制御をSystemCシミュレータのwait関数呼び出しではなく、タイムキーパーのsum_timeメソッド呼び出しで行うことで、スレッド間のコンテキスト切り替え制御が省略され、シミュレーションが高速化される。
(B)スレッド間の同期制御
ハードウエアとソフトウエアの協調検証環境では、CPU、メモリ、周辺デバイスがバス経由で接続され、CPU上で動作するソフトウエアと周辺デバイスが協調して動作しながら処理を進める。バスに接続されるデバイスには、このバスに対して能動的にデータ転送を開始できるバスマスタと、受動的にバス要求を待つバススレーブがある。通常、CPUがバスマスタとなってデータ転送バス要求を出力し、バス経由でバススレーブであるメモリや周辺デバイスにアクセスすることで処理が進められる。ここでは、バスを経由したデータ転送のモデルを、トランザクションレベルでモデル化する場合の例を説明する。
バスマスタからのバス要求が発生した場合、バスアービタによってバス使用権を獲得した後、バススレーブへのアクセスが行われる。バススレーブへアクセスを行う場合のシミュレーション時刻の更新は、バスマスタのタイムキーパーに対して行う。バススレーブ側でどのバスマスタのタイムキーパーに対してシミュレーション時刻制御を行えば良いかを識別するため、バス要求を行うメソッドにバスマスタのタイムキーパーの識別子を引数として付加する。
例えば、CPUがバスマスタとなって、バススレーブである周辺デバイスへアクセスする場合、周辺デバイスはCPUのタイムキーパーctikに対して、tik[C_TID]->sum_time(Tacc)メソッドを呼び出してCPUのシミュレーション時刻を進める。ここで、Taccは、周辺デバイスのアクセス時間である。つまり、このメソッド呼び出しによって、周辺デバイスのアクセス時間TaccがCPUのシミュレーション時刻に加算され、CPUのシミュレーション時刻が進められる。
CPUがバスマスタとなってバス経由で周辺デバイスへアクセスし、周辺デバイスのスレッド動作を起動する場合、周辺デバイスのスレッドが起動した後、CPUにおけるソフトウエアの実行と周辺デバイスにおけるハードウエア動作が並行して行われる。つまり、周辺デバイスの起動後、CPUのタイムキーパーを用いたシミュレーション時刻制御と周辺デバイスのタイムキーパーを用いたシミュレーション時刻制御が独立して行われる。
この場合、周辺デバイスのスレッドの起動時刻をCPUによる周辺デバイスの起動時刻に設定し、この周辺デバイスのシミュレーション時刻をCPUのシミュレーション時刻に同期させる必要がある。このために用意されたものがsync_timeメソッドである。周辺デバイスは、スレッドを起動する際にcurrent_timeメソッドによってCPUのタイムキーパーのシミュレーション時刻を取り出し、取り出したシミュレーション時刻を引数として周辺デバイスのタイムキーパーに対してsync_timeメソッド呼び出しを行うことでシミュレーション時刻を設定する。
このようなシミュレーション時刻の同期制御を行うために、周辺デバイスにCPUと周辺デバイスの両方のタイムキーパーをチャネル接続する必要がある。このため、CPUの場合と同様に、以下のような周辺デバイスクラスpdevを定義する。
class pdev: public sc_module
{
public:
sc_port<tikIF,0>tik; //タイムキーパーアクセスのためのポート
sc_port<busIF>bus; //バスアクセスのためのポート
SC_CTOR(pdev){
SC_THREAD(main);
}
}
同様にバスbusのクラスを定義し、CPUや周辺デバイスpdevとCPUのタイムキーパーctikや周辺デバイスpdevのタイムキーパーPtikの接続、及びバスbusとの接続は、上位階層において以下のように行う。
cpu =new cpu(“cpu”); //CPUを生成
pdev =new pdev(“pdev”); //周辺デバイスを生成
bus =new bus(“bus”); //バスを生成
ctil =new tik(“ctik”); //CPU用タイムキーパーを生成
ptic =new tik(“ptik”); //周辺デバイス用タイムキーパーを生成
cpu->bus(*bus); //CPUにバスを接続
cpu->tik(*ctik); //CPUにCPU用タイムキーパーを接続
bus->pdev->(*pdev); //バスに周辺デバイスをスレーブとして接続
bus->tik(*ctik); //バスにCPU用タイムキーパーを接続
bus->tik(*ptik); //バスに周辺デバイス用タイムキーパーを接続
pdev->bus(*bus); //周辺デバイスにバスを接続
pdev->tik(*ctik); //周辺デバイスにCPU用タイムキーパーを接続
pdev->tik(*ptik); //周辺デバイスに周辺デバイス用タイムキーパーを接続
この場合、バスbusや周辺デバイスpdevのタイムキーパーポートには、最初にCPU用タイムキーパーctikが接続され、次に周辺デバイス用タイムキーパーpdevが接続される。従って、まずtik[0](つまり、tik[C_TID])によってタイムキーパーctikが参照可能となり、次にtik[1](つまり、tik[P_TID])によってタイムキーパーptikが参照可能となる。これにより、バスや周辺デバイスから、CPU用タイムキーパーctikと周辺デバイス用タイムキーパーptikの双方のメソッドを呼び出すことが可能になる。
例えば、データ書き込み転送用writeメソッドをバスと周辺デバイスに定義し、CPUがバス経由で周辺デバイスのレジスタへ書き込みを行うためのbus->writeメソッド呼び出しを行って、周辺デバイスを起動する場合を説明する。ここでは、書き込みを行うレジスタのアドレスaddress、書き込みデータdata、及びwriteメソッドを実行したCPUのタイムキーパー識別子C_TIDが、引数として使用される。この場合、CPUがバスマスタであるので、writeメソッドを実行したバスマスタのタイムキーパーはctikとなる。
図3は、CPUからの周辺デバイススレッドの起動制御の説明図である。この図3に示すように、CPUスレッドは、bus->write(address,data,C_TID)メソッド呼び出しを行い、バスモデルを起動する。バスモデルにおけるwriteメソッドの記述例は次のようになる。
void bus::(long address,long data,tid_t tid){
addressをデコードして周辺デバイスpdevを選択し、
バスアービタによりバス権を獲得;
pdev->write(address,data,tid);
}
ここで、tidはバス要求を出力したバスマスタのタイムキーパー識別子で、この場合はbus->write(address,data,C_TID)メソッド呼び出しによって与えられたCPUのタイムキーパー識別子C_TIDとなる。このwriteメソッドは、まず、アドレスaddressをデコードして周辺デバイスpdevを選択し、バスアービタによってバス使用権を獲得した後、周辺デバイスpdevに対してpdev->write(address,data,tid)メソッド呼び出しを行ってアドレスaddressで指定されるレジスタに対してデータdataの書き込みを行う。
また、周辺スレッドのスレーブ動作の記述例は次のようになる。
/*周辺デバイスにおけるwriteメソッドの記述例*/
void pdev::write(long address,long data,tid_t tid){
tid[tid]->sum_time(Tacc);
addressで指定されるレジスタにdataの書き込みを行う;
if(上記書き込みによって周辺デバイスが起動される場合){
tik[P_TID]->sync_time(tik[tid]->current_time());
notify(pdev_start);
}
}
上記のようにCPUがバスアービタによってバス使用権を獲得した後、周辺デバイスpdevのmainスレッドを起動する前にsync_timeメソッド呼び出しを行い、周辺デバイスのタイムキーパーのシミュレーション時刻をCPUが書き込みを完了したシミュレーション時刻sTsimに設定する必要がある。
周辺デバイスは、tid[tid]->sum_time(Tacc)メソッド呼び出しにより、CPUのシミュレーション時刻をTaccで指定されるアクセス時間だけ進める。CPUからの書き込み処理が完了した時点で、先ず、sTsim=tik[tid]->current_timeメソッド呼び出しを行ってCPUの現在のシミュレーション時刻sTsimを求め、周辺デバイスのタイムキーパーptikに対してtik[P_TID]->sync_time(sTsim)メソッドを呼び出して周辺デバイスのシミュレーション時刻をCPUのシミュレーション時刻sTsimに設定する。
その後、周辺デバイスのスレッドをSystemyCシミュレータのnotify(イベント)関数呼び出しによって起動する。ここで、notify(イベント)関数は、wait(イベント)関数によって指定されたイベントを待っているスレッドが有る場合、そのスレッド動作を起動する。
周辺デバイスpdevのmainスレッドは、例えば、次のように記述する。
void pdev::main(){
for(;;){ //以下の処理を繰り返す
Wair(pdev_start); //notify(pdev_start)が実行されるまで待つ
tik[P_TID]->sum_time(pT1); //ptikのシミュレーション時刻に経過時間pT1を加算
tik[P_TID]->sum_time(pT2); //ptikのシミュレーション時刻に経過時間pT2を加算
tik[P_TID]->sum_time(pTL); //ptikのシミュレーション時刻に経過時間pTLを加算
}
}
上記の周辺デバイスのスレッドは、起動された後、wait(pdev_start)関数呼び出しによってpdev_startイベントを待つ。この待ち状態は、上記の周辺デバイスにおけるwriteメソッドにおけるnotify(pdev_start)関数呼び出しが行われた時点で解除される。
このように、CPUは、周辺デバイスのスレッドを起動した後、その周辺デバイスの動作状況を確認する処理が必要になることがある。周辺デバイスの動作状況の確認には、大別して、CPUが周辺デバイスの特定のレジスタ(例えば、状態レジスタ)の内容を読み出して確認するポーリングと、周辺デバイスがCPUに対して割り込み通知する割り込みの2つの方法がある。
(C)ポーリング
ポーリングは、周辺デバイスがその動作状況に応じて特定のレジスタの内容を更新し、CPUがバス経由でその特定のレジスタの内容を読み出すためのreadメソッドを呼び出すことで実現される。
図4は、ポーリングによるCPUと周辺デバイス間のスレッドの切り替え制御の説明図である。
この例では、周辺デバイスpdevのmainスレッドが起動された後、経過時間pT1,pT2,…,pTLの順にシミュレーション時刻を進める場合を示している。ここで、経過時間pT1,pT2,…,pTLは、周辺デバイスにおける処理時間である。例えば、周辺デバイスをステートマシンとしてインプリメントしている場合には、これらの経過時間は各ステートの滞在時間となる。
周辺デバイスのmainスレッドは、そのタイムキーパーptikに対して、tik[P_TID]->sum_time(pT1),tik[P_TID]->sum_time(pT2),…,tik[P_TID]->sum_time(pTL)メソッドを呼び出す。tik[P_TID]->sum_time(pTL)メソッド呼び出し後の積算時間pTsumLと、シミュレーション時刻pTsimLは次式で与えられる。
pTsumL=pT1+pT2+…+pTL
pTsimL=pTsum0+pTsumL=pT0+pT1+pT2+…+pTL
ここで、pTsum0は、tik[P_TID]->sum_time(pT1)メソッドを呼び出す前のシミュレーション時刻である。
CPUは、周辺デバイススレッドを起動するbus->writeメソッドを読み出した後、経過時間cT1,cT2,…,cTKの順にシミュレーション時刻を進める。
ここで、CPUのmainスレッドがtik[C_TID]->sum_time(cTK)メソッド呼び出しを行った後、bus->read(address,C_TID)メソッド呼び出しを行い、周辺デバイスのレジスタの内容を読み出したとする。readメソッドは、読み出しを行うレジスタのアドレスaddress、及びreadメソッドを実行したバスマスタのタイムキーパー識別子を引数として持ち、読み出したデータを戻り値として返す。この場合、CPUのmainスレッドがバスマスタであるので、readメソッドを実行したバスマスタのタイムキーパー識別子はC_TIKとなる。
CPUのmainスレッドにおけるtik[C_TID]->sum_time(cTK)メソッド呼び出し後のタイムキーパーctikのシミュレーション時刻をcTsimKとし、以下の関係が成立するものとする。
pTsim0+(pT1+pT2+…+pTL-1)≦cTsimK≦pTsimL=pTsim0+(pT1+pT2+…+pTL)
この場合、バスアービタでは、下記に示すように周辺デバイスのタイムキーパーに対して、CPUのシミュレーション時刻、CPUのシステム時刻、及びflish_timeメソッドを引数としてbreak_timeメソッド呼び出しを行い、中断要求として登録する。これにより、周辺デバイスのシミュレーション時刻が、中断時刻として設定したCPUのシミュレーション時刻に達したとき、中断メソッドであるflush_timeメソッドが呼び出される。
tik[P_TID]->break_time(tik[C_TID]->currenttime()
,tik[C_TID]->current_sc_time()
,&TikIF::flush_time);
tik[C_TID]->flush_time();
上記のbreak_timeメソッドは、まず、タイムキーパー識別子C_TIDで指定されるCPUのタイムキーパーに対するcurrent_timeメソッドとcurrent_sc_timeメソッド呼び出しを行い、それぞれCPUの現在のシミュレーション時刻cTsimKとシステム時刻Tsysを求める。そして、周辺デバイスのタイムキーパーptikに対してcTsimKを中断時刻、Tsysを中断システム時刻として登録する。このときの対応する中断メソッドが、周辺デバイスのタイムキーパーptikに対するflush_timeメソッドであることを意味する。
break_timeメソッドの呼び出し後に実行されるCPUのタイムキーパーctikに対するflish_timeメソッド呼び出しでは、SystemyCシミュレータのwait関数呼び出しを行って他のスレッドへのコンテキスト切り替えを行い、そのスレッドに制御を渡す。このflush_timeメソッドの呼び出しにより、周辺デバイススレッドへ制御が渡され、周辺デバイススレッドによるwait(notify)メソッド呼び出し以降の処理が実行される。
周辺デバイススレッドは、tik[P_TID]->sum_time(pT1),tik[P_TID]->sum_time(pT2),…,tik[P_TID]->sum_time(pTL)メソッド呼び出しにおいて、シミュレーション時刻がCPUからのbreak_timeメソッドによって設定された中断時刻の値cTsimK以上に達したかどうかを調べる。周辺デバイスのタイムキーパーptikのシミュレーション時刻が中断時刻の値cTsimKに達しない場合、周辺デバイススレッドの実行が継続される。シミュレーション時刻がcTsimK以上に達した場合、つまり、シミュレーション時刻がpTsimLに達した場合、タイムキーパーptikは、対応する中断メソッドを呼び出してCPUスレッドへ制御を切り替える。これにより、CPUスレッドのbus->readメソッド呼び出し以降の処理が実行される。このような制御により、CPUスレッドからのbus->readメソッド呼び出しは、周辺デバイススレッドのシミュレーション時刻に同期して実行される。
(D)バスアービタ動作
バスには、複数のバスマスタが接続されることがある。例えば、複数のCPU間でバスを共有するときに、DMAC(Direct Memory Access Controller)のようにバスマスタとなり得る周辺デバイスをバスに接続する場合である。このような場合、複数のバスマスタ間のバス要求を調停するためのバスアービタが必要になる。
バスアービタは、複数のバスマスタからバス要求が同時に発生したときに、バス仕様によって予め指定された優先度判定条件に基づいて最も優先度の高いバスマスタを選択し、そのバスマスタにバス使用権を与えるものである。優先度判定条件としては、バスマスタに固有の優先度を設定する方法や、バスマスタ間で優先度を巡回させる方法等が使われている。
バス使用権が与えられたバスマスタは、バスを使用してバススレーブをアクセスする。バス使用権が与えられたバスマスタがバスを使用している間、それ以外のバスマスタは、バス使用権の待ち状態となる。
このようなバス調停機能を実現するため、シミュレーション・モデルにおいては、各バスマスタはそれぞれ独立したスレッドとして実現され、各バスマスタにはタイムキーパーが用意される。バスマスタは、バスアービタに対してそのタイムキーパーを引数としてread/writeメソッド呼び出しを行うことによりバス要求を出力する。
バスアービタは、バス要求が発生したときに以下のステップ(1)〜(6)の手順でバス調停を行う。
(1) バス要求の引数として与えられたアドレスを判別し、アクセスするバススレーブを決定し、下記に示すようにバスマスタのタイムキーパー識別子m_tidを引数として、バススレーブのタイムキーパーに対してbreak_timeメソッド呼び出しを行う。これにより、バスマスタのシミュレーション時刻をバススレーブのタイムキーパーの中断時刻bTsimとして登録する。このときの対応するメソッドは、バススレーブのタイムキーパーに対するflush_timeメソッドである。この動作の記述例を以下に示す。
アドレスをデコードし、バススレーブのタイムキーパー識別子s-tidを決定;
tik[s_tid]->break_time(tik[m_tid]->current_time()
,tik[m_tid]->current_sc_time()
,&TikIF::flush_time);
(2) バス要求、タイムキーパー識別子、及びバスマスタのシミュレーション時刻をバスアービタ内部のバス要求待ち行列に格納する。
(3) 引数として渡されたバスマスタのタイムキーパー識別子の指すタイムキーパーに対して、flush_timeメソッドを実行して積算時間Tsumの値をゼロクリアする。これにより、他のバスマスタのスレッドへのコンテキスト切り替えが行われる。他のバスマスタがバス要求を出力中である場合、バスマスタのスレッドへのコンテキスト切り替えにより、制御が渡されたバスマスタは、ステップ(1)からの処理を実行する。
(4) バス要求待ち行列に格納された最も小さいシミュレーション時刻を持つバス要求の内で、最も優先度の高いバス要求を選択する。
(5) 選択したバス要求のタイムキーパー識別子が、今回のバス要求の引数として与えられたタイムキーパー識別子と一致したとき、次のステップ(6)へ進む。そうでないとき、即ち、他のバスマスタのバス要求が選択されたときは、バスマスタのスレッドを待ち状態にする。この待ち状態は、ステップ(6)で解除される。待ち状態が解除された後、ステップ(4)へ進む。
(6) 選択したバス要求によるバススレーブのアクセスが完了してバスが解放されるまで、バスを占有する。バス開放時点で、他のバスマスタの待ち状態をnotifyメソッドによって解除する。
上記手順により、ステップ(3)におけるflush_timeメソッドの実行で、ある時刻に実行されたすべてのバスマスタのバス要求が待ち行列に格納され、ステップ(4)において、最も優先度の高いバス要求が選択される。
図5及び図6は、それぞれバスアービタによるCPUと周辺デバイス間のスレッドの切り替え制御(1及び2)の説明図である。
この図5では、CPUスレッドと周辺スレッドの2つのバスマスタがバスに接続され、CPUスレッドがbus->writeメソッドによってデータの書き込みアクセスを行うためのバス要求を出力し、周辺デバイススレッドがbus->readメソッドによってデータの読み出しアクセスを行うためのバス要求を出力する場合を示している。
ここでは、CPUのmainスレッドが経過時間cT1,cT2,…,cTKの順にシミュレーション時刻を進めた時点で、bus->writeメソッドの呼び出しを行い、周辺スレッドが経過時間pT1,pT2,…,pTLの順にシミュレーション時刻を進めた時点で、bus->readメソッドの呼び出しを行うものとする。また、tik[C_TID]->sum_time(cTK)メソッド呼び出し後のタイムキーパーctikのシミュレーション時刻をcTsimK、tik[P_TID]->sum_time(pTL)メソッド呼び出し後のシミュレーション時刻をpTsimL、tik[P_TID]->sum_time(pT1)メソッド呼び出し前のシミュレーション時刻をpTsim0とする。
CPUのスレッドがbus->writeメソッドの呼び出しを行った時点で、バスアービタが起動される。バスアービタは、ステップ(2)においてバス要求を待ち行列に格納し、ステップ(3)においてtik[C_TID]->flush_timeメソッドの呼び出しを行う。これにより、SystemyCシミュレータのwait関数呼び出しが行われる。このとき、cTsimKがpTsim0よりも大きいと、SystemyCシミュレータのカーネルは、周辺デバイスのスレッドへコンテキスト切り替えを行い、周辺デバイスのスレッドへ制御が渡される。
コンテキスト切り替えによって制御が渡された周辺デバイスのスレッドが、bus->readメソッドの呼び出しを行った時点でバスアービタが起動される。バスアービタは、ステップ(2)においてバス要求を待ち行列に格納し、ステップ(3)においてtik[PJID]->flush_time()メソッドの呼び出しを行う。これにより、SystemCのwait関数呼び出しが行われ、必要に応じてスレッド間のコンテキスト切り替えが行われる。
図5に示すように、cTsimKがpTsimLよりも小さい場合、バスアービタにおけるtik[P_TID]->flush_timeメソッド呼び出しにより、再度、CPUスレッドヘのコンテキスト切り替えが発生する。同図の折れ線で示している実線矢印は、このようなスレッド間の制御の流れを示している。バスアービタはステップ(4)において、最も優先度の高いバス要求を待ち行列から選択する。この場合、CPUのスレッドが要求したbus->writeメソッドの呼び出しが選択され、CPUによるバスアクセスが行われた後、以降のCPUスレッドのtik[C_TID]->sum_time(cTK+1),tik[C_TID]->sum_time(cTK+2),…メソッド呼び出しの処理が行われる。
図6は、図5と同様のスレッド実行制御が行われる場合に、cTsimKがpTsimLよりも大きい場合を示している。このとき、tik[P_TID]->sum_time(pTL)メソッドを呼び出した後のbus->readメソッド呼び出しでは、バスアービタにおけるtik[P_TID]->flush_timeメソッドの呼び出しによるコンテキスト切り替えは発生しない。
バスアービタはステップ(4)において、最も優先度の高いバス要求を待ち行列から選択する。この場合、周辺デバイスのスレッドが要求したbus->readメソッドの呼び出しが選択され、周辺デバイスのスレッドによるバスアクセスが行われた後、以降の周辺デバイススレッドのtik[P_TID]->sum_time(pTL+1),tik[P_TID]->sum_time(pTL+2),…メソッド呼び出し処理が行われる。図6中の折れ線で示している実線矢印は、このようなスレッド間の制御の流れを示している。
周辺デバイスが処理を進め、tik[P_TID]->flush_timeメソッド呼び出しを行った時点で、図6中の折れ線で示している破線矢印で示すように、再度、CPUスレッドにコンテキスト切り替えが行われ、bus->writeメソッドによるアクセスが処理される。
cTsimKがpTsimLと等しい場合、バスアービタにおけるtik[P_TID]->flush_time()メソッドの呼び出しによってCPUスレッドヘのコンテキスト切り替えが発生するか否かは、使用しているシミュレータに依存する。
CPUスレッドヘのコンテキスト切り替えが発生しなかった場合、バスアービタはステップ(4)において、待ち行列に格納された同一シミュレーション時刻に発行された2つのバス要求(即ち、CPUのスレッドからのbus->writeメソッドによるバス要求と、周辺デバイスのスレッドからのbus->readメソッドによるバス要求)の内で優先度の高いバス要求を選択する。
ステップ(4)において、CPUのスレッドのバス要求の優先度が、周辺デバイスのスレッドのバス要求の優先度よりも高い場合、周辺デバイスのスレッドは、ステップ(5)で選択されたバス要求が自タイムキーパーの発したバス要求でないことを知り、CPUのスレッドのバス要求が完了するまで待ち状態となる。これにより、CPUスレッドヘのコンテキスト切り替えが行われる。この場合、スレッド間の制御の流れは図5と同様となる。
逆に、ステップ(4)において、CPUのスレッドのバス要求の方が周辺デバイスのスレッドのバス要求よりも優先度が低いと、周辺デバイスのスレッドは、ステップ(5)において、選択されたバス要求が自タイムキーパーの発したバス要求であることを知り、周辺デバイスのスレッドによるバスアクセスが行われた後、以降の周辺デバイスの処理が行われる。この場合、スレッド間の制御の流れは図6と同じである。
(E1)割り込み制御(その1)
スレッドの起動後、外部からの非同期イベントの発生をスレッドに通知したい場合がある。例えば、CPUが周辺デバイスを起動した後、周辺デバイスが割り込み信号によってCPUに割り込みを発生させ、周辺デバイスの状態をCPUに通知したいような場合である。
割り込み信号は、通常、周辺デバイスの一種である割り込みコントローラに通知される。割り込みコントローラは、割り込み信号が通知された際、割り込み許可の判定や割り込みの優先順位判定を行い、発生した割り込みが許可されており、その割り込みの優先度が最も高いときCPUに割り込みを通知し、このCPUに設けられた割り込みハンドラを起動する。
割り込みハンドラは、周辺デバイスからの割り込み要求が発生したときに実行されるCPUの制御ソフトウエアで、下記のようにCPUのスレッドとして実現される。
class cpu:public sc_module

public:
sc_port<tikIF>ctik; // port to CPU Time Keeper
SC_CTOR(CPU){
SC_THREAD(main); //mainスレッドを起動
SC_THREAD(inthdr); //割り込みハンドラを起動

void main(void);
void inthdr(void);
以下、周辺デバイスが割り込みによってCPUの割り込みハンドラを起動する手順について述べる。
図7〜図13は、周辺デバイスからCPUへの割り込み制御(1〜7)の説明図であり、縦軸をシミュレーション時刻とした割り込みタイミングを示している。
図7は、CPUのmainスレッドが周辺デバイスを起動し、割り込み待ちになるまで制御の流れを示している。以下、その手順を述べる。
(1) CPUのmainスレッドによる周辺デバイスの起動
CPUのmainスレッドの記述例を以下に示す。
void cpu::main(void){
bus->write(address,data,C_TID); //周辺デバイススレッドを起動
intct1->no_wait_intreq(); //周辺デバイスからの割り込み要求待ち
tik[C_TID]->sum_time(cT1);
tik[C_TID]->sum_time(cT2);
tik[C_TID]->sum_time(cTK);
}
上記のCPUのmainスレッドは、bus->writeメソッド呼び出しの手段等により、バス経由の周辺デバイスアクセスで周辺デバイスのスレッドを起動する。この後、CPUのmainスレッドは割り込み要求を待つために割り込みコントローラintct1に対してintct1->no_wait_intreqメソッド呼び出しを行う。
このno_wait_intreqメソッドは、周辺デバイスからの割り込み要求を待つことなく、CPU動作と周辺デバイス動作を並行して動作させるような場合に、周辺デバイスの起動直後に呼び出すためのメソッドである。
このno_wait_intreqメソッドは、下記の記述例のように、CPUが割り込みの発生を待たずに周辺デバイスドライバと並行して動作することを意味するNO_WAIT_INTをcpu_wait_int変数に設定した後、wait(intreq_start)呼び出しを行って周辺デバイスからの割り込み通知待ちとなる。
void intct1::no_wait_intreq(void){
cpu_wait_int=NO_WAIT_INT;
wait(intreq_start);
}
これに対してCPUが割り込み発生まで待つような場合には、割り込みコントローラintct1に対してintct1->wait_intreqメソッド呼び出しを行い、cpu_wait_int変数にWAIT_INTの値を設定する。wait_intreqメソッドの記述例を下記に示す。
void intct1::wait_intreq(void){
cpu_wait_int=WAIT_INT;
wait(intreq_start);
}
cpu_wait_intへ設定する値のデータタイプwait_int_tの定義は、例えば以下のように与える。
typedef enum {NOJAIT_INT=O // no wait for interrupt request
,WAIT_INT=1 // wait for interrupt request
}wait_int_t;
cpu_wait_int変数は、割り込み要求処理スレッドint_requestで参照される。
(2) 周辺デバイススレッドからの割り込み要求の通知
周辺デバイスpdevは、CPUからのwriteメソッドによって起動された後、必要に応じてシミュレーション時刻を進める処理を行い、このCPUに対する割り込みを通知する必要が生じた際、割り込みコントローラintct1に対して割り込み通知を行う。
周辺デバイスpdevのスレーブ動作の記述例を示す。
void pdev::write(1ong address,1ong data,tid_t tid){
tik[tid]->sum_time(Tacc);
addressで指定されるレジスタにdataの書き込みを行う;
if(上記書き込みによって周辺デバイスが起動される場合){
tik[P_TID]->sync_time(tik[tid]->current_time());
notify(pdev_start);
}
}
起動された周辺デバイスpdevにおけるwriteメソッドは、tik[P_TID]->sync_time(tik[tid]->current_time)メソッド呼び出しによって周辺デバイスのシミュレーション時刻をCPUのシミュレーション時刻に設定した後、notify(pdev_start)メソッド呼び出しにより、下記に示す周辺デバイスのmainスレッドを起動する。
void pdev::main(){
for(;;){ //以下の処理を繰り返す
wait(pdev_start);//notify(pdev_start)が実行されるまで待つ
tik[PJID]->sum_time(pT1);//ptikのシミュレーション時刻にpT1経過時間を加算
tik[PJID]->sum_time(pT2);//ptikのシミュレーション時刻にpT2経過時間を加算
tik[PJID]->sum_time(pTL);//ptikのシミュレーション時刻にpTL経過時間を加算
//以下の手順によって割り込み要求をCPUに通知する。
tik[I_TID]->sync_time(tik[P_TID]->current_time());
intct1->intct1_start(); //割り込み要求を割り込コントローラに通知
tik[P_TID]->flush_time();
// 制御を割り込コントローラに渡す。
}
}
起動された周辺デバイスのmainスレッドは、必要に応じてsum_timeメソッド呼び出しによって周辺デバイスのシミュレーション時刻を進め、割り込みをCPUに通知する必要が発生した場合には、割り込みコントローラintct1に対してintct1->intct1_startメソッドを呼び出して、割り込み要求を割り込みコントローラに通知する。
図8は、周辺デバイスpdevのmainスレッドが割り込みをCPUのmainスレッドに通知し、割り込みハンドラを起動し、CPUのmainスレッドに制御を渡すまでの制御の流れを示している。以下、その手順を述べる。
(3) 割り込みコントローラによる割り込み優先度判定
割り込みコントローラintct1におけるintct1_startメソッドは、下記の記述例に示すようにnotify(intct1_start)メソッド呼び出しによって、割り込みコントローラのint_contro1スレッドを起動する。
void intct1::intct1_start(){
notify(intct1_start);
}
void intct1::int_request(){
for(;;){
wait(intct1_start); //割り込みの発生を待つ
tik[I_TID]->suM_time(iT);//itikのシミュレーション時刻にiT経過時間を加算割り込み優先度判定を行う。
if(割り込み要求が許可された){
if(cpu_wait_int==NO_WAIT_INT)
tik[C_TID]->break_time(tik[I_TID]−>current_time() // 割り込み発生時刻をCPUの中断時刻に設定
,tik[I_TID]->current_sc_time() // 割り込み発生システム時刻を設定
,&TikIF::flush_time //flush_timeをCPUの中断メソッドに設定
else
tik[C_TID]=sync_time(tik[I_TID]->current_time(); //
notify(intreq_start); //
tik[I_TID]->flush_time(); //
notify(inthdr?start); //
}
}
}
ここで、I_TIDは割り込みコントローラのタイムキーパー識別子で、下記のように、上述のtid_tにI_TIDを付加することによって定義される。
Typedef enum{C_TID=0 //Time Keeper#1=CPU
,P_TID=1 //Time Keeper#2=Peripheral
,I_TID=2 //Time Keeper#3=Interrupt Controller
}tid_t; //time keeper id type
上記のように、割り込みコントローラintct1のint_control1スレッドは、wait(intct1_start)によって周辺デバイスからの割り込み要求イベントintct1_startを待っており、周辺デバイスがintct1_startメソッド呼び出しによって、この割り込みの発生待ち状態を解除した場合、周辺デバイスからの割り込み要求の優先度判定を行う。
この割り込み要求の受付が許可されたならば、この例ではCPUのmainスレッドにおけるno_wait_intメソッド呼び出しによってcpu_wait_intの値はNO_WAIT_INTに設定されるので、CPUのタイムキーパーctikに対してbreak_timeメソッド呼び出しを行う。このときの引数は、割り込みコントローラの現在のシミュレーション時刻tik[I_TID]->current_time、現在のシステム時刻tik[I_TID]->current_sc_time、及びflush_timeメソッドである。この呼び出しにより、割り込み発生時刻をCPUタイムキーパーの中断時刻として設定し、flush_timeメソッドを中断メソッドとして設定する。
この後、notify(intreq_start)メソッド呼び出しによってCPUの待ち状態を解除し、flush_timeメソッド呼び出しを行う。これにより、CPUのmainスレッドに制御が渡される。この後、notify(inthdr_start)呼び出しによって割り込みハンドラを起動する。
(4) CPUのmainスレッドにおける割り込み起動までの処理を継続
上記notify(intreq_start)メソッド呼び出しにより、CPUのmainスレッドは、intct1->no_wait_intreq()メソッド呼び出しによる周辺デバイスからの割り込み要求待ち状態が解除され、以降に続くsum_timeメソッド呼び出しによってシミュレーション時刻を進める。シミュレーション時刻が、上記break_timeメソッド呼び出しによって設定した中断時刻以上に達した場合、対応する中断メソッド(CPUタイムキーパーに対するflush_timeメソッド)呼ぴ出しによって、上記notify(inthdr_start)メソッド呼び出しによって起動された割り込みハンドラに制御が渡される。
(5) CPUの割り込みハンドラの実行
下記にCPUの割り込みハンドラinthdrの記述例を示す。
void cpu::inthdr(){
for(;;){
intct1->wait_inthdr(); //割り込みコントローラによる割り込み通知待ち
tik[C_TID]->sum_time(hT1);
tik[C_TID]->sum_time(hT2);
tik[C_TID]->sum_time(hTM);
}
}
割り込みハンドラスレッドintdhrは、割り込みコントローラintct1に対してintct1->wait_inthdrメソッド呼び出しを行う。このwait_inthdrメソッドは、下記の記述例のようにwait(inthdr_start)メソッド呼び出しを行って、周辺デバイスからの割り込み通知待ちとなる。
void intct1::wait_inthdr(void){
wait(inthdr_start);
}
この割り込みハンドラintdhrにおける割り込み待ち状態は、上述の割り込みコントローラintct1における割り込み要求処理スレッドint_requestにおいてnotify(inthdr_start)メソッド呼び出しが行われた時点で解除される。
起動された割り込みハンドラが実行され、この割り込みハンドラ処理が完了した時点で割り込みハンドラは、再度intct1->wait_inthdrメソッド呼び出しを行って次の割り込み要求待ち状態になる。これにより、CPUのmainスレッドヘ再度、制御が渡される。
(6) CPUのmainスレッド処理の再開
割り込みハンドラ処理後のmainスレッド処理が再開される。
図9は、ステップ(3)において、break_timeメソッドを実行した際のシミュレーション時刻の様子を示している。
この図9に示すようにCPUのmainスレッドが周辺デバイスを起動し、この後、CPUのmainスレッドは周辺デバイスからの割り込み要求が発生するまで、割り込み待ち状態となる。周辺デバイスはsync_timeメソッド呼び出しにより、そのタイムキーパーのシミュレーション時刻をCPUが周辺デバイスを起動した時刻に設定し、以降、sum_time呼び出しによってシミュレーション時刻を進める。
この際、周辺デバイスがバス経由でメモリなどの他の周辺デバイスをアクセスした場合、flush_timeメソッド呼び出しにより、周辺デバイスのタイムキーパーの積算時間Tsumをゼロクリアすることがある。このflush_timeメソッド呼び出しにより、SystemCシミュレータのシステム時刻が、このタイムキーパーのシミュレーション時刻と一致するように更新される。この周辺デバイスのシステム時刻をbTsysとする。
周辺デバイスがflush_timeメソッド呼び出した後、sum_timeメソッド呼び出しによってそのタイムキーパーのシミュレーション時刻を進め、そのシミュレーション時刻がbTsimに違したときに、割り込みコントローラに割り込み要求を通知する。
割り込み要求を割り込みコントローラに通知した時点で、SystemCシミュレータで管理している周辺デバイスのシステム時刻は、flush_timeメソッド呼び出しを実行したときの値bTsysに設定されたままになっているが、タイムキーパーで管理しているシミュレーション時刻はその後のsum_timeメソッド呼び出しによってbTsimに更新されている。
割り込みコントローラのint_contro1スレッドは、割り込みの通知により起動され、bTsim、bTsys、及び、中断メソッドflush_timeを引数としてbreak_timeメソッド呼び出しを行う。
CPUのmainスレッドにおける割り込み待ち状態は、break_timeメソッド呼ぴ出しの直後のnotify(intreq_start)メソッド呼び出しによって解除される。このときのCPUのmainスレッドのSystemCシミュレータのシステム時刻は、notifyメソッド呼び出しを行った周辺デバイスのシステム時刻に設定される。この場合は、待ち状態を解除した周辺デバイスのシステム時刻bTsysの値に設定される。
これにより、CPUのタイムキーパーのシミュレーション時刻Tsimは、割り込みコントローラintct1に対して割り込み待ちを行った時刻のままであるが、そのシステム時刻はnotify(intreq_start)メソッド呼び出しによって解除されたシステム時刻bTsysとなり、両時刻が異なっているということになる。
以上のように、break_timeメソッドにおいて中断時刻待ち行列に中断時刻と中断メソッド以外に中断システム時刻を格納し、sum_timeメソッドにおいて中断時刻待ち行列が空でない場合に中断システム時刻を参照して積算時間を算出するのは、このシミュレーション時刻と中断システム時刻の違いを補正するためである。
break_timeメソッド呼び出しによって設定した周辺デバイスのシステム時刻をbTsysとした場合、CPUのmainスレッドにおけるsum_timeメソッド呼び出しにおいては、中断時刻待ち行列が空でないので、積算時間の設定は以下のように行われる。
CPUタイムキーパーのシミュレーションTsim時刻が中断システム時刻bTsysよりも小さいとき、Tsimが中断システム時刻bTsysに違していないため、積算時刻Tsumの値をゼロクリアする。
CPUタイムキーパーのシミュレーションTsim時刻が中断システム時刻bTsys以上に違したとき、積算時刻Tsumの値をTsim-bTsysの値に設定する。これにより、CPUタイムキーパーのシミュレーション時刻TsimはSystemCシミュレータのカーネルで管理しているシステム時刻と一致する。
図10に示すように、周辺デバイス起動後のCPUのmainスレッドの経過時間をcT1,cT2,…,cTKとし、周辺デバイス起動後の周辺デバイスのmainスレッドの割り込み要求発生までの経過時間をpT1,pT2,…,pTLとし、割り込みコントローラにおける割り込み優先度判定の経過時間をiTとすると、以下の関係が成立する。
(cT1+cT2+…+cTK-1)≦(pT1+pT2+…+PTL)+iT≦(cT1+cT2+…+cTK)
つまり、CPUのmainスレッドにおけるtik[C_TID]->sum_time(ctK)メソッド呼び出しを行った際に、CPUのシミュレーション時刻がそのタイムキーパーに設定した中断時刻(CPUに対する割り込み通知時刻)を越える場合を示している。CPUは、mainスレッドにおけるsum_timeメソッド呼び出し後、割り込みハンドラスレッドの実行を開始する。
なお、上記ステップ(3)の割り込みコントローラの処理では、複数の周辺デバイスからの割り込み要求を受け付けるために、実際にはバスアービタと同様に、割り込み要求の待ち行列管理を行う。下記に割り込みコントローラの詳細な処理を示す。
(3-1) 割り込みコントローラにおいて、割り込み要求と割り込みを要求した周辺デバイスのシミュレーション時刻を割り込み要求待ち行列に格納する。
(3-2) 割り込みを要求した周辺デバイスに対してflush_timeメソッドを実行する。これにより、割り込みを発生する可能性のある他の周辺デバイスヘ制御が渡され、上記(3-1)からの処理が繰り返される。
(3-3) 割り込み要求待ち行列に格納された最も小さいシミュレーション時刻の割り込み要求のうち最も優先度の高い割り込み要求を選択する。
(3-4) 選択した割り込み要求が今回の周辺デバイスからの割り込み要求であるとき、次のステップ(3-5)へ進む。そうでないとき、つまり、他の周辺デバイスの割り込み要求が選択されたとき、周辺デバイスのスレッドを待ち状態にさせる。この待ち状態は、ステップ(3-5)において解除される。待ち状態が解除された後、ステップ(3-3)へ進む。
(3-5) 選択した割り込み要求による割り込みハンドラ処理が起動された時点で、他の割り込み要求の待ち状態をnotifyにより解除する。
周辺デバイスは、割り込み要求が発生した時点で、割り込みコントローラ経由でCPUのタイムキーパーctikに対してシミュレーション時刻を周辺デバイスのシミュレーション時刻に設定するために、tik[C_TID]->sync_time(tik[P_TID]->current_time())メソッドを呼び出す。この後、CPUのソフトウェアとして定義されている割り込みハンドラを呼び出す。
(E2)割り込み制御(その2)
割り込み制御(その1)の特殊な場合として、CPUが周辺デバイスのmainスレッドを起動した後、直ちに割り込みハンドラ待ちになる場合がある。このような場合、図11に示すように、CPUのmainスレッドにおける周辺デバイスのスレッド起動のためのバスアクセスを行った後、割り込みコントローラintct1に対してintct1->wait_intreqメソッド呼び出しを行い、cpu_wait_int変数にWAIT_INTの値を設定して割り込み要求の発生を待った後、wait(inthdr_end)関数を呼び出して割り込みハンドラの完了待ちとなる。
このwait(inthdr_end)関数呼び出しによる割り込みハンドラ完了待ち状態は、割り込みハンドラにおける割り込みの受け付け処理が完了した後のnotify(inthdr_end)メソッド呼び出しによって解除される。つまり、CPUのmainスレッドと割り込みハンドラスレッドを以下の記述例に示すように変更すればよい。
void CPU: :main (void){
bus->write(address,data,C_TID);//周辺デバイススレッドを起動
intct1->wait_intreq(); //割り込み要求待ち
wait(inthdr_end); //割り込みハンドラの終了待ち
tik[C_TID]->sum_time(cT1);
tik[C_TID]->sum_time(cT2);
tik[C_TID]->sum_time(cTK);
}
void cpu::inthdr(){
for(;;){
wait(inthdr_start);
tik[C_TID]->sum_time(hT1);
tik[C_TID]->sum_time(hT2);
tik[C_TID]->sum_time(hTM);
notify(inthdr_end); //割り込みハンドラの完了をmainスレッドに通知
}
}
(E3)割り込み制御(その3)
上記2つの割り込み制御(その1及びその2)の拡張として、CPUのmainスレッドが周辺デバイスを起動した後、他の処理(例えば、次に周辺デバイスを起動するための準備)を実行しておき、次に周辺デバイスを起動する直前で、CPUが周辺デバイスからの割り込み通知があり、割り込みハンドラの実行が完了したかどうかを確認したい場合がある。
以下にそのような場合のCPUのmainスレッドの記述例を示す。
void CPU::main(void){
for(i=o; i<10; i++){
bus->write(address,data,C_TID); //周辺デバイススレッドを起動
intct1->no_wait_intreq(); //割り込みコントローラによる割り込み通知待ち
tik[C_TID]->sum_time(cT1);
tik[C_TID]->sum_time(cT2);
tik[C_TID]->sum_time(cTK);
if(!inthdr_end_flag) //既に割り込みハンドラ処理が完了しているとき
wait(inthdr_end); //割り込みハンドラの終了待ち
inthdr_end_flag=false;
}
}
上の例では、CPUのmainスレッドはbus->writeメソッドによって周辺デバイススレッドを起動し、その後、経過時間cT1,cT2,…,cTKの順にシミュレーション時刻を進める処理を行った後、wait(inthdr_end)関数呼び出しによって割り込みハンドラの実行完了待ちとなる場合を示している。この場合、割り込みハンドラinthdrの記述例は、以下のようになる。
void cpu: : inthdr O {
for(;;){
wait(inthdr_start);
tik[C_TID]->sum_time(hT1);
tik[C_TID]->sum_time(hT2);
tik[C_TID]->sum_time(hTM);
inthdr_end_flag=true;
notify(inthdr_end); //割り込みハンドラの完了をmainスレッドに通知
}
}
mainスレッドにおいて、bus->writeメソッドで周辺デバイススレッドを起動した後、intct1->no_wait_intreqメソッド呼び出しによって割り込みコントローラからの割り込み要求を待つのは、割り込み制御(その1)と同様である。
周辺デバイスからの割り込み要求によってwait(intreq_start)関数呼び出しによる待ち状態が解除されるとCPUのmainスレッドは、経過時間cT1,cT2,…,cTKの順にシミュレーション時刻を進める処理を行った後、wait(inthdr_end)関数呼び出しによって割り込みハンドラの実行完了待ちとなる。
CPUのmainスレッドは、tik[C_TID]->sum_time(cTK)メソッド呼び出しにより、経過時間cTKによるシミュレーション時刻を進める処理を行った後、割り込みハンドラ処理が完了したかどうかを調べるために、変数inthdr_end_flagをテストする。
上記の割り込みハンドラの記述例のように、変数inthdr_end_flagは割り込みハンドラが完了した際にtrueに設定される。この変数がfalseであれば、まだ割り込みハンドラの処理が完了していないことを示しており、wait(inthdr_end)呼び出しを行って割り込みハンドラの完了を待つ。この変数がtrueであれば、既に割り込みハンドラの処理が完了していることを示しており、wait(inthdr_end)をスキップして次の処理に進む。
(E4)割り込み制御(その4)
上記の割り込み制御(その1〜その3)では、いずれも割り込みコントローラや割り込みハンドラを独立したスレッドとしてインプリメントしている。このため、割り込みが発生する度にスレッド間のコンテキスト切り替えが発生し、シミュレーション速度が低下する。
このため、割り込みコントローラや割り込みハンドラをスレッドとしてインプリメントせずに、メソッドとしてインプリメントする方法がある。
割り込みコントローラにおいて、周辺デバイスからの割り込み要求の判定に要する経過時間iTは、数クロックサイクル程度の小さい値である。従って、割り込みコントローラを独立したスレッドとしてインプリメントしないで、近似的に周辺デバイスのスレッドからメソッドとして呼び出し、割り込み要求の判定に要する経過時間iTを割り込みハンドラ内部でCPUの経過時間として組み込んで近似することも可能である。
また、割り込みハンドラinthdrは、break_timeメソッドの機能を利用することにより、CPUタイムキーパーのsum_timeメソッドから呼び出すことが可能である。つまり、割り込みコントローラにおけるbreak_timeメソッドの呼び出しにおいて、CPUタイムキーパーの中断時刻を割り込み受け付け時刻に設定し、対応するメソッドを割り込みハンドラinthdrに設定する。
CPUのmainスレッドにおけるsum_timeメソッド呼び出しにより、CPUタイムキーパーのシミュレーション時刻が中断時刻(割り込み受け付け時刻)以上に達したことを検出する機能を利用し、割り込みハンドラinthdrをsum_timeメソッドから呼び出すことができる。この場合、割り込みハンドラinthdrや割り込みコントローラint_requestは、スレッドとしてではなく、下記の記述例のようにメソッドとして定義する。
void cpu::inthdr(){
tik[C_TID]->sum_time(iT);//CPUタイムキーパーのシミュレーション時刻に経過時間iTを加算
tik[C_TID]->sum_time(hTI);
tik[C_TID]->sum_time(hT2);
tik[C_TID]->sum_time(hTM);
}
void intct1::int_request(tid_t tid){
割り込み優先度判定を行う。
if(割り込み要求が許可された){
if(cpu_wait_int==NOJAIT_INT)
tik[C_TID]->break_time(tik[tid]->current_time()// 割り込み発生時刻をCPUの中断時刻として登録
,tik[tid]->current_sc_time()
,&TikIF::inthdr));//割り込みハンドラを中断メソッドとして登録
else
tik[C_TID]=sync_time(tik[I_TID]->current_time());//割り込み発生時刻をCPUの時刻に設定
notify(intreq_start);//CPUの割り込み待ち状態を解除
tik[tid]->flush_time();// CPUのmainスレッドに制御を渡す
}
}
ここで、&TikIF::inthdrは割り込みハンドラの呼び出しメソッドのアドレスで、例えば、このメソッドをタームキーパー内のメソッドとして以下のように定義する。
void TikIF::inthdr(){
cpu->inthdr();
}
つまり、タイムキーパー内で定義されているinthdrメソッドを中断メソッドとして呼び出した場合、CPU内で定義されている割り込みハンドラinthdrが呼び出される。周辺デバイスのmainスレッドは、下記の記述例のように、周辺デバイスのタイムキーパー識別子を引数として上記割り込みコントローラメソッドを呼び出す。
void pdev::main(){
for(;;){ //以下の処理を繰り返す
wait(pdev_start); //notify(pdev_start)が実行されるまで待つ
tik[P_TID]->sum_time(pT1);//ptikのシミュレーション時刻にpT1経過時間を加算
tik[P_TID]->sum_time(pT2);//ptikのシミュレーション時刻にpT2経過時間を加算
tik[P_TID]->sum_time(pTL);//ptikのシミュレーション時刻にpTL経過時間を加算
//以下の手順によって割り込み要求をCPUに通知する。
intct1->int_request(P_TID);//割り込みコントローラメソッドを呼び出す
}
}
CPUのmainスレッドの記述例は、割り込み制御(その1)と同様である。図12と図13は、このような制御を行った場合の、割り込み制御(その1)と割り込み制御(その2)に対応する割り込みタイミングを示している。
以上のように、この実施例1のシミュレータは、current_timeメソッド等の6個のメソッド関数を有しているので、SystemCシミュレータのwait関数を呼び出す回数を削減することが可能になる。これにより、wait関数呼び出しに伴うコンテキスト切り替え制御のオーバーヘッドが減少し、シミュレーション時間を短縮することができるという利点がある。
この実施例2は、実施例1のタイムキーパーにおけるsum_timeメソッドの機能を次のように拡張するものである。
即ち、この実施例2のsum_timeメソッドは、中断要求待ち行列が空でなく、更新したTsimが中断要求待ち行列の先頭に格納された中断時刻以上に達した場合、待ち行列の先頭から順にTsim以下の中断時刻bTsimに対応する中断メソッドmethodを呼び出した後、これらを待ち行列から削除する。この後、シミュレーション時刻Tsimに積算時間Tsumを加算してシミュレーション時刻Tsimを進めると共に、積算時間Tsumに経過時間timeを加算して積算時間Tsumを更新する。
積算時間Tsumが閾値Tthrを越えた場合、flush_timeメソッド呼び出しを行う。ここで閾値Tthrは、積算時間Tsumの最大値を指定するもので、積算時間Tsumがこの閾値Tthrを越えたときに、flush_timeメソッド呼び出しを行う。これによって、SystemCシミュレータのwait関数が呼び出され、スレッド間のコンテキスト切り替えが行われる。
つまり、閾値Tthrを適当な値に設定すれば、適当なシミュレーション時間間隔でスレッド間のコンテキスト切り替えが行われ、しかも高速なシミュレーションが実現できる。特殊な場合として、閾値Tthrの値を0に設定した場合、sum_timeメソッドの呼ぴ出しを行う度にflush_timeメソッドが呼び出され、SystemCシミュレータのwait関数が呼ぴ出されるので、実質的にsum_timeメソッド呼び出しを行う代わりにSystemCシミュレータのwait関数呼び出しを呼び出すのと等価になり、sum_timeメソッドの呼び出しを行う度にスレッド間のコンテキスト切り替えが行われる。
このように、この実施例2のシミュレータは、sum_timeメソッドの機能を拡張することにより、実施例1のシミュレータに比べて高速なシミュレーションが可能になるという利点がある。
この実施例3は、実施例1または実施例2のシミュレータに、タイムキーパーを統合するモジュールであるタイムキーパー統合モジュールtiksを追加したものである。
タイムキーパー統合モジュールtiksに、必要なすべてのタイムキーパーを接続し、各デバイスにタイムキーパー統合モジュールtiksを接続するようにすれば、各デバイスは、これらのタイムキーパーをタイムキーパー統合モジュールtiks経由で参照可能となる。
このようにタイムキーパー統合モジュールtiksを設け、各デバイスにタイムキーパー統合モジュールtiksを接続することにより、必要なタイムキーパーのメソッド呼び出しが行えるようになる。タイムキーパー統合モジュールtiksの接続は、あたかもクロック同期型シミュレーション・モデルにおけるクロックヘの接続と同様に、タイムキーパーの接続が簡略化される。
このタイムキーパー統合モジュールtiksは、少なくとも以下のメソッドを有している。
・break_time(tid_t d_tid,uint64 bTsim,uint64 bTsys,void(TikIF::*method)())メソッド(第7の関数):タイムキーパー識別子d_tidで指定されるタイムキーパーに対して、break_time(bTsim,bTsys,method)メソッド呼び出しを行う。
・flush_time(tid_t tid)メソッド(第8の関数):タイムキーパー識別子tidで指定されるタイムキーパーに対して、flush_time(time)メソッド呼び出しを行う。
・sum_time(tid_t tid,1ong time)メソッド(第9の関数):タイムキーパー識別子tidで指定されるタイムキーパーに対して、sum_time(time)メソッド呼び出しを行う。
・current_time(tid_t tid)メソッド(第10の関数):タイムキーパー識別子tidで指定されるタイムキーパーに対して、current_timeメソッド呼び出しを行い、結果を戻り値として返す。
・sync_time(tid_t tid,uint64 sTsim)メソッド(第11の関数):タイムキーパー識別子tidで指定されるタイムキーパーに対して、sync_time(sTsim)メソッド呼び出しを行う。
ここで、tidはどのタイムキーパーに対するメソッド呼び出しを行うかを示すタイムキーパー識別子である。下記にこれらのメソッドの記述例を示す。
void tiks::break_time(tid_td_tid,uint64 bTsim,uint64 bTsys,void(TikIF::*method)()){
tik[(d_tid]->break_time(bTsim,bTsys,method);
}
void tiks::flush_time(tid_t tid){
tik[tid]->flush_time();
}
void tiks::sum_time(tid_t tid,1ong time){
tik[tid]->sum_time(time);
}
uint64 tiks::current_time(tid_t tid){
return tik[tid]->current_time();
}
void tiks::sync_time(tid_t tid,uint64 sTim){
tik[tid]-〉sync_time(sTim);
}
このため、タイムキーパー統合モジュールtiksクラスを、例えば以下のように定義する。
class tiks
:public sc_module
,public tiksIF
{
public:
sc_port<tikIF,0〉tik; /*ports to CPU time keepers */
void break_time(tid_t d_tid,uint64 bTsim,uint64 bTsys,void(TikIF::*method)());
void flush_time(tid_t tid);
void sum_time(tid_t tid,1ong time);
uint64 current_time(tid_t tid);
void sync_time(tid_t tid,uint64 sTsim);
}
この機能を利用して下記のようにタイムキーパー統合モジュールtiksへのタイムキーパー接続を行う。
cpu = new cpu(“cpu”);
pdev = new pdev(“pdev”);
tdev = new tdev(“tdev”);
tiks = new tiks(“tiks”);
ctik = new tik(“ctik”);
ptik = new tik(“ptik”);
ttik = new tik(“ttik”);
cpu->tiks(*tiks);
pdev->tiks(*tiks);
tdev->tiks(*tiks);
tiks->ctik(*ctik);
tiks->ptik(*ptik);
tiks-〉ttik(*ttik);
このように各スレッドのポートにはタイムキーパー統合モジュールtiksを接続するだけで良く、タイムキーパー接続が簡素化される。以下、各デバイスからのタイムキーパー統合モジュールtiks経由のタイムキーパーのメソッド呼び出しの記述例を示す。
void CPU::main(void){
tiks->sum_time(C_TID,cT1);
tiks->sum_time(C_TID,cT2);
tiks->sum_time(C_TID,cTK);
}
void pdev::write (1ong address,1ong data,tid_t tid){
tiks->sum_time(tid,Tacc);
addressで指定されるレジスタにdataの書ぎ込みを行う;
if(上記書き込みによって周辺デバイスが起動される場合){
tiks->sync_time(P_TID,tiks->current_time(tid));
notify(pdev_start);
}
}
void pdev::main() {
for(;;){ //以下の処理を繰り返す
wait(pdev_start); //notify(pdev_start)が実行されるまで待つ
tiks->sum_time(P_TID,pTI);//ptikのシミュレーション時刻にpT1経過時間を加算
tiks->sum_time(P_TID,pT2);//ptikのシミュレーション時刻にpT2経過時間を加算
tiks->sum_time(P_TID,pTL);//ptikのシミュレーション時刻にpTL経過時間を加算
}
}
以上のように、この実施例3のシミュレータは、タイムキーパー統合モジュールtiksを追加したことにより、実施例1及び2のシミュレータに比べてタイムキーパーの接続が簡素化できるという利点がある。
この実施例4は、実施例3でflush_timeメソッドの呼び出しを行う代わりに、タイムキーパーで他のデバイスが動作中であることを検出し、他のデバイスが動作中のときにのみ、flush_timeメソッドの呼び出しを行うメソッドを用いるものである。
このため各タイムキーパーに、少なくともデバイスの状態を示す変数statusを設け、以下のようなメソッドを追加する。
・set_sleepメソッド(第12の関数):変数statusを休眠状態SLEEPに設定する関数である。
・set_activeメソッド(第13の関数):変数statusを動作状態ACTIVEに設定する関数である。
・get_statusメソッド(第14の関数):変数statusを戻り値として返す関数である。
各デバイスが起動されたとき、そのタイムキーパーtikに対してtik->set_activeソッド呼び出しを行って、デバイスを動作状態に設定する。デバイス動作が終了し、起動待ちになったとき、そのタイムキーパーtikに対してtik->set_sleepソッド呼び出しを行って、デバイスを休眠状態に設定する。任意の時刻において、デバイスの状態を調べたいとき、そのタイムキーパーtikに対してtik->get_statusメソッド呼び出しを行って、デバイス状態を得る。
前述の周辺デバイスにおけるスレッド起動の記述例を以下に示す。
void pdev::write(1ong address,1ong data,tid_t tid){
tik[tid]->sum_time(Tacc);
addressで指定されるレジスタにdataの書き込みを行う;
if(上記書き込みによって周辺デバイスが起動される場合){
tik[P_TID]->sync_time(tik[tid]->current_time());
tik[P_TID]->set_active(); //デバイスを動作状態に設定
notify(pdev_start);
}
}
void pdev::main(){
for(;;){ //以下の処理を繰り返す
wait(pdev_start); //notify(pdev_start)が実行されるまで特つ
tik[P_TID]->sum_time(pT1); //ptikのシミュレーション時刻にpT1経過時間を加算
tik[P_TID]->sum_time(pT2); //ptikのシミュレーション時刻にpT2経過時間を加算
tik[P_TID]->sum_time(pTL); //ptikのシミュレーション時刻にpTL経過時間を加算
//以下の手順によって割り込み要求をCPUに通知する。
tik[I_TID]->sync_time(tik[PJID]->current_time());
notify(intct1_start); //割り込み要求を割り込コントローラに通知
tik[P_TID]->flush_time(); //制御を割り込コントローラに渡す
tik[P_TID]->set_sleep(); //デバイスを休眠状態に設定
}
}
つまり、周辺デバイススレッド起動の前にtik[P_TID]->set_activeメソッド呼び出しによってデバイスを動作状態に設定し、周辺デバイススレッドにおける処理が終了し、次の起動を待つ前にtik[P_TID]->set_sleepメソッド呼び出しによってデバイスを休眠状態に設定する。
上記のメソッドに加えて、タイムキーパー統合モジュールtiksに、少なくとも以下のメソッドを用意する。
・switch_threads(tid_t
tid)メソッド:タイムキーパー識別子tidで指定されるタイムキーパー以外のデバイスが動作状態である場合に、タイムキーパー統合モジュールtiksに対してflush_time(tid)メソッドの呼び出しを行う。
他のタイムキーパーのデバイスが動作状態であるか否かは、get_status(tid)==ACTIVEによって判定する。
下記にこのswitch_threadsメソッドの記述例を示す。
void tiks::switch_threads(tid_t tid){
int i;
for(i=O; iくtik.size();i++){
if(tid==i)
continue;
if(tik[i]->get_status==ACTIVE){
tik[tid]->flush_time();
return;
}
}
}
ここで、tik.size()は、タイムキーパー統合モジュールtiksのtikポートに接続されているタイムキーパーの数を求めるSystemCシミュレータの関数である。
上記のように、switch_threadsメソッドは、引数として指定されたタイムキーパー識別子tid以外のtikポートに接続されている全てのタイムキーパーの状態を調べ、いずれからACTIVEであればflush_timeメソッド呼び出しを行いアクティブ状態にあるデバイスに制御を渡す。
CPU、周辺デバイス、及びバス等の各スレッドにおいてflush_timeメソッド呼び出しを行う替わりに、このswitch_threadsメソッド呼び出しを行うことによって、SystemCシミュレータのwait関数呼び出しの回数が削減され、シミュレーション性能が向上する。
以上のように、この実施例4のシミュレータは、デバイスの状態を示す変数statusとこの変数statusを操作するいくつかのメソッド関数を設けているので、flush_timeメソッドの呼び出しを行う回数が削減され、より高速の動作が可能になるという利点がある。
なお、本発明は、上記実施例に限定されず、種々の変形が可能である。この変形例としては、例えば、次のようなものがある。
(a) SystemCシミュレータをC言語ベースのシミュレータ本体として使用した例を示したが、SpecC等のハードウエアモデル記述用言語によるシミュレータを使用することができる。
(b) 関数や引数の名称は一例である。
(c) 図2〜図13の動作説明は一例であり、シミュレーション対象のハードウエアやソフトウエアの機能に応じて適宜変更する必要がある。
本発明の実施例を示すシミュレータの構成図である。 CPUのmainスレッド切り替え制御の説明図である。 CPUからの周辺デバイススレッドの起動制御の説明図である。 ポーリングによるCPUと周辺デバイス間のスレッドの切り替え制御の説明図である。 バスアービタによるCPUと周辺デバイス間のスレッドの切り替え制御(1)の説明図である。 バスアービタによるCPUと周辺デバイス間のスレッドの切り替え制御(2)の説明図である。 周辺デバイスからCPUへの割り込み制御(1)の説明図である。 周辺デバイスからCPUへの割り込み制御(2)の説明図である。 周辺デバイスからCPUへの割り込み制御(3)の説明図である。 周辺デバイスからCPUへの割り込み制御(4)の説明図である。 周辺デバイスからCPUへの割り込み制御(5)の説明図である。 周辺デバイスからCPUへの割り込み制御(6)の説明図である。 周辺デバイスからCPUへの割り込み制御(7)の説明図である。
符号の説明
1,2 シミュレーション・モデル
10 シミュレータ
11 SystemCシミュレータ
12 タイムキーパー
Q 中断要求待ち行列
X,Y 変数
current_time,current_sc_time,flush_time,break_time,sum_time,sync_time メソッド

Claims (5)

  1. ハードウエアとソフトウエアの協調検証を行うためのC言語ベースのハード・ソフト協調検証用シミュレータであって、
    前記ハードウエア及びソフトウエアに対応するシミュレーション・モデルを構成する複数のスレッド毎に設けられ、それぞれが対応するスレッドのシミュレーション時刻を制御するために、シミュレーション時刻を保持する第1の変数、積算時間を保持する第2の変数、中断時刻と対応する中断メソッドを格納する中断要求待ち行列、及び処理用の関数を備えた複数のタイムキーパーと、
    前記タイムキーパーからの要求に応じて、管理しているシステム時刻を与えられた要求時間だけ進めると共に、並行して動作している前記スレッド間のコンテキスト切り替えを制御するC言語ベースのシミュレータ本体とを、
    備えたことを特徴とするハード・ソフト協調検証用シミュレータ。
  2. 前記各タイムキーパーは、それぞれ、
    呼び出しに応じて前記第1の変数のシミュレーション時刻を返す第1の関数と、
    呼び出しに応じて前記シミュレーション時刻から前記積算時間を指しい引いた値を前記システム時刻として返す第2の関数と、
    呼び出しに応じて前記第2の変数の積算時間を前記要求時間として前記シミュレータ本体のシステム時刻を進めた後、該第2の変数をゼロクリアする第3の関数と、
    与えられた中断時刻、中断システム時刻及び中断メソッドを前記中断要求待ち行列に登録する第4の関数と、
    前記中断要求待ち行列が空の場合には、前記シミュレーション時刻に引数として与えられる経過時間を加算して該シミュレーション時刻を進めると共に前記積算時間に該経過時間を加算して該積算時間を更新し、前記中断要求待ち行列が存在しかつ前記シミュレーション時刻が中断時刻未満の場合には、該シミュレーション時刻に前記経過時間を加算してそのシミュレーション時刻を進め、前記中断要求待ち行列が存在しかつ前記シミュレーション時刻が中断時刻以上の場合には、該中断要求待ち行列の内で中断時刻がシミュレーション時刻以上である中断メソッドを呼び出す第5の関数と、
    引数として与えられた時刻が現在の前記シミュレーション時刻よりも大きいときに、該時刻と更新後のシミュレーション時刻の差分を引数とし前記第5の関数を呼び出す第6の関数とを、
    備えたことを特徴とする請求項1記載のハード・ソフト協調検証用シミュレータ。
  3. 前記第5の関数は、前記中断要求待ち行列が存在しかつ更新したシミュレーション時刻が該中断要求待ち行列の先頭に格納された中断時刻に達したときに、該中断待ち行列の先頭から順に中断メソッドを呼び出し、その後シミュレーション時刻に前記積算時間を加算してこのシミュレーション時刻を進めると共に、該積算時間に前記経過時間を加算して該積算時間を更新し、この更新した積算時間が所定の閾値を越えた場合に前記第3の関数を呼び出すように構成したことを特徴とする請求項2記載のハード・ソフト協調検証用シミュレータ。
  4. タイムキーパー識別子で指定されるタイムキーパーに対して前記第4の関数を呼び出す第7の関数と、
    前記タイムキーパー識別子で指定されるタイムキーパーに対して前記第3の関数を呼び出す第8の関数と、
    前記タイムキーパー識別子で指定されるタイムキーパーに対して前記第5の関数を呼び出す第9の関数と、
    前記タイムキーパー識別子で指定されるタイムキーパーに対して前記第1の関数を呼び出し、結果を戻り値として返す第10の関数と、
    前記タイムキーパー識別子で指定されるタイムキーパーに対して前記第6の関数を呼び出す第11の関数とを、
    有するタイムキーパー統合モジュールを設けたことを特徴とする請求項2または3記載のハード・ソフト協調検証用シミュレータ。
  5. 前記各タイムキーパーに、
    対応するスレッドの状態が休眠状態か動作状態かを示す第3の変数と、
    前記第3の変数を休眠状態に設定する第12の関数と、
    前記第3の変数を動作状態に設定する第13の関数と、
    前記第3の変数を戻り値として返す第14の関数とを、
    設けたことを特徴とする請求項4記載のハード・ソフト協調検証用シミュレータ。
JP2006234298A 2006-08-30 2006-08-30 ハード・ソフト協調検証用シミュレータ Pending JP2008059192A (ja)

Priority Applications (1)

Application Number Priority Date Filing Date Title
JP2006234298A JP2008059192A (ja) 2006-08-30 2006-08-30 ハード・ソフト協調検証用シミュレータ

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
JP2006234298A JP2008059192A (ja) 2006-08-30 2006-08-30 ハード・ソフト協調検証用シミュレータ

Publications (1)

Publication Number Publication Date
JP2008059192A true JP2008059192A (ja) 2008-03-13

Family

ID=39241867

Family Applications (1)

Application Number Title Priority Date Filing Date
JP2006234298A Pending JP2008059192A (ja) 2006-08-30 2006-08-30 ハード・ソフト協調検証用シミュレータ

Country Status (1)

Country Link
JP (1) JP2008059192A (ja)

Cited By (7)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2010009113A (ja) * 2008-06-24 2010-01-14 Fujitsu Microelectronics Ltd シミュレーション装置およびプログラム
JP2010049630A (ja) * 2008-08-25 2010-03-04 Fujitsu Ltd シミュレーション制御プログラム、シミュレーション制御装置、およびシミュレーション制御方法
JP2012509546A (ja) * 2009-12-23 2012-04-19 インチロン ゲーエムベーハー 組み込みシステムをシミュレートするための方法及びデータ処理システム
US20140325516A1 (en) * 2011-02-15 2014-10-30 Commissariat A L'energie Atomique Et Aux Energies Al Ternatives Device for accelerating the execution of a c system simulation
WO2015155839A1 (ja) * 2014-04-08 2015-10-15 株式会社 日立製作所 シミュレーションシステム、シミュレーション方法及びプログラム
CN112400162A (zh) * 2018-07-19 2021-02-23 日立汽车系统株式会社 模拟装置及其方法、以及ecu装置
CN114625108A (zh) * 2022-03-21 2022-06-14 北京经纬恒润科技股份有限公司 一种仿真测试方法及装置

Cited By (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JP2010009113A (ja) * 2008-06-24 2010-01-14 Fujitsu Microelectronics Ltd シミュレーション装置およびプログラム
JP2010049630A (ja) * 2008-08-25 2010-03-04 Fujitsu Ltd シミュレーション制御プログラム、シミュレーション制御装置、およびシミュレーション制御方法
JP2012509546A (ja) * 2009-12-23 2012-04-19 インチロン ゲーエムベーハー 組み込みシステムをシミュレートするための方法及びデータ処理システム
US8543369B2 (en) 2009-12-23 2013-09-24 Inchron, Gmbh Method and data processing system for simulating an embedded system
US20140325516A1 (en) * 2011-02-15 2014-10-30 Commissariat A L'energie Atomique Et Aux Energies Al Ternatives Device for accelerating the execution of a c system simulation
US9612863B2 (en) * 2011-02-15 2017-04-04 Commissariat A L'energie Atomique Et Aux Energies Alternatives Hardware device for accelerating the execution of a systemC simulation in a dynamic manner during the simulation
WO2015155839A1 (ja) * 2014-04-08 2015-10-15 株式会社 日立製作所 シミュレーションシステム、シミュレーション方法及びプログラム
CN112400162A (zh) * 2018-07-19 2021-02-23 日立汽车系统株式会社 模拟装置及其方法、以及ecu装置
CN114625108A (zh) * 2022-03-21 2022-06-14 北京经纬恒润科技股份有限公司 一种仿真测试方法及装置
CN114625108B (zh) * 2022-03-21 2024-01-30 北京经纬恒润科技股份有限公司 一种仿真测试方法及装置

Similar Documents

Publication Publication Date Title
US9552448B2 (en) Method and apparatus for electronic system model generation
US7957950B2 (en) Hard/soft cooperative verifying simulator
US7246052B2 (en) Bus master and bus slave simulation using function manager and thread manager
JP4667206B2 (ja) マルチコアモデルシミュレーションプログラム、該プログラムを記録した記録媒体、マルチコアモデルシミュレータ、およびマルチコアモデルシミュレーション方法
JP2008059192A (ja) ハード・ソフト協調検証用シミュレータ
CN114580344B (zh) 测试激励生成方法、验证方法、验证系统及相关设备
JP2004110785A (ja) メモリコントローラ
US20110265093A1 (en) Computer System and Program Product
US20130073765A1 (en) Semiconductor device and data processor
KR101704751B1 (ko) 모듈 간의 타이밍 정보를 이용하는 멀티코어 시스템의 시뮬레이터, 및 그 시뮬레이션 방법
AU2012227208B2 (en) Global clock handler object for HDL environment
JP2007011720A (ja) システムシミュレータ、システムシミュレート方法、制御プログラムおよび可読記録媒体
CN113946445A (zh) 一种基于asic的多线程模块及多线程控制方法
JP2013196245A (ja) シミュレーション方法、シミュレーション装置及びシミュレーションプログラム
US7761280B2 (en) Data processing apparatus simulation by generating anticipated timing information for bus data transfers
TW201310241A (zh) 全匯流排之交易層級模擬方法以快速與精確的爭用分析
KR102576707B1 (ko) 전자 시스템 및 그 동작 방법
WO2021036421A1 (zh) 多核架构的同步信号产生电路、芯片和同步方法及装置
JP2007048019A (ja) エミュレーション方法、エミュレータ、コンピュータ組込型デバイスおよびエミュレータ用プログラム
JP2004021907A (ja) 性能評価用シミュレーションシステム
JP2019016168A (ja) シミュレーションプログラム、方法、及び装置
US20240134718A1 (en) Apparatus and method for synchronizing participants of a simulation
US20240231956A9 (en) Apparatus and method for synchronizing participants of a simulation
CN117332742B (zh) 一种芯片设计阶段的仿真验证方法和装置
US11373024B1 (en) Circuit simulation based on a high-level language circuit specification

Legal Events

Date Code Title Description
A621 Written request for application examination

Free format text: JAPANESE INTERMEDIATE CODE: A621

Effective date: 20080922

A711 Notification of change in applicant

Free format text: JAPANESE INTERMEDIATE CODE: A712

Effective date: 20081210

RD02 Notification of acceptance of power of attorney

Free format text: JAPANESE INTERMEDIATE CODE: A7422

Effective date: 20090421

A977 Report on retrieval

Free format text: JAPANESE INTERMEDIATE CODE: A971007

Effective date: 20100106

A131 Notification of reasons for refusal

Free format text: JAPANESE INTERMEDIATE CODE: A131

Effective date: 20100202

A02 Decision of refusal

Free format text: JAPANESE INTERMEDIATE CODE: A02

Effective date: 20100727