2003年12月12日
仮想デバイスモデル構築を体験しよう「IFビルダー」の使い方講座
GAIO CLUB 特集
GAIO CLUB【2003/12月号】
仮想デバイスモデル構築を体験しよう
IFビルダーを使ってハードウエアタイマーを設計
シミュレータで利用する仮想ハードウエアの考え方を学習する
IFビルダーとは
ガイオ「シミュレータファミリ」は、組み込みソフトの設計、動作検証を行うための、シミュレーション技術を用いた開発環境の総称です。一般的な組み込みシステムは、マイコンを中心に様々な周辺回路、周辺ハードウエアが追加されて構成されています。
シミュレータファミリでは、これらの周辺ハードウエアをPC上で動作する仮想的なソフトウエアで実装し、実際のターゲットデバイスと同様の開発環境を構築する仕組みを取っています。
-
このコーナーで紹介する「IFビルダー」とは、組み込みシステムに必要な周辺デバイスをソフトウエア化するための支援ツールです。作成した仮想ハードモデルは、ガイオの全てのシミュレータ製品で共通な部品として使用することができます。
-
シミュレータカーネルとの接続インタフェースを自動生成
IFビルダーは、マイクロソフト社の開発環境「Visual Studio .NET」(以下.NET)の上に構築されているSDK(SoftwareDevelopment Kit)です。IFビルダーのインストーラにより、.NETのC++開発環境の上に次のような機能がアドオンされます。
・i/oアドレス、割り込みなど、ソフトと仮想ハードのインタフェース設定機能
・ソフトと仮想ハードの同期タイミング、時間精度の設定機能・ロジアナのような波形、メモリアクセスログなどの各種ビューアー生成機能
・ カーネルと共有メモリで接続するためのdll化機能
ユーザーは、シミュレータカーネルとの特殊なインタフェース方法を知らなくとも、提供されるAPIを使用するだけで、シミュレータが持つメモリモデルに自由に読み書きしたり、シミュレータに割り込みを発生させたりすることが可能です。
実際のハードと仮想ハードとの動作概念の違い
まず、ハードウエアをソフトウエアで実装するときには、動作概念の違いを理解する必要があります。マスタークロックを持つデジタルハードウエアの場合、実際は、マイコンの動作とは無関係に並列して動作しており、マスタークロックの時間を最小単位として、これに同期して動作しています。
これをソフトウエア化してPC上で動作させる場合、PCのCPUは1つしかありませんから、マイコンの処理と仮想化されたハードウエアの動作は同時には実行されず、常に、設定した時間単位で、交互に動作することになります。
このため、マイコンが一定時間動作したらマイコンをウエイトさせて、次にその時間分だけハード処理を動作させると言う考え方になります。
タイマーデバイスをモデル化する
次のように、メモリマップされた4つのレジスタと割り込みピンを持つタイマーデバイスを考えます。
a.TIM_ENABELEレジスタ(R/W,0A000000h)
動作イネーブル信号(1の時動作)
b.TIM_PERIODレジスタ(R/W,0A000004h)
割り込み周期設定(クロックがこのレジスタ値に達すると割り込み発生)
c.IRQ_COUNTレジスタ(R/W,0B000000h)
IRQ割り込み発生回数を保持(ソフトから書き込み)
d.FIQ_COUNTレジスタ(R/W,0B000004h)
FIQ割り込み発生回数を保持(ソフトから書き込み)
e.IRQ割り込み(タイプ 3)
タイマーからマイコンへの外部割り込み
基本的なタイマー動作として、クロックに同期してタイマー内部のカウンタがインクリメントされ、この値が「TIM_PERIOD」レジスタに設定された値に達すると、IRQ割り込みを発生させるモデルを考えます。
シミュレータとアクセスするためのメモリマップの指定
-
シミュレータカーネル内のメモリモデルにアクセスするために、各レジスタのメモリマップを作成します。この部分は、.NET環境にアドオンされたウィザード機能で行い、指定された内容のソースコードを自動生成します。ユーザーは、ウィザードのダイアログに必要な情報を入力するだけで、メモリマッピングを行うことができます。
-
タイマーが発生する割り込みの設定
-
割り込みの設定も、シミュレータカーネルと関連する特殊な部分です。これも、.NET環境にアドオンされたウィザード機能で行い、指定された内容のソースコードを自動生成する仕組みになっています。
-
シミュレータと仮想ハードの同期タイミング設定
前述の様に、マイコンシミュレータと仮想ハードモデルは、一定時間間隔で交互に実行されます。ここでは、その同期の間隔を指定します。
-
ガイオのシミュレータファミリでは、この同期間隔の最小単位はマイコンの1インストラクションとなっています。マイコンが1命令を実行すると、その時間(命令により実行クロック数は異なります)分だけの仮想ハード処理が呼び出されます。
-
シミュレータカーネルと仮想ハードは、dllにより接続されており、シミュレータカーネルが仮想ハード処理の関数を呼び出す様なイメージです。
仮想ハードのソフトウエアとして、マイコン1クロック分に相当する処理を関数(AlwaysClock())として作成しておき、そのスケジューリング(時間呼び出し)の設定を適切に行ったとします。例えば、8クロックで実行されるマイコン命令が実行されると、その次には8クロック分に相当する仮想ハード側の処理、すなわち、AlwaysClock()関数が8回呼び出される様な仕組みになっています。
仮想ハードウエア部品を定義クラス化されたライブラリを使用
では、ここからタイマーの機能を記述してゆきます。IFビルダーが自動生成するライブラリは、クラス化されており、C++を使用して記述してゆきます。示されたクラスの構造図の中心にある「CSsHwModule」が、タイマーなどの仮想ハードを作成するためのテンプレートとなる基底クラスであり、この派生クラスを作成して、ここにタイマーを作成します。タイマーの他に仮想ハードが複数ある場合でも、この派生クラスを追加さえすれば良いことになります。
CSsHwModuleの派生クラスでタイマー部品を作成
実際にタイマー部品のための派生クラスを作ってみます。派生クラスのソースファイル作成は、.NETにアドオンされたクラス追加ウィザードを使用して行います。
-
ウィザードのダイアログに、クラス名、ソースファイル名、ヘッダファイル名を指定すると、スケルトンを自動生成します。CSsHwModuleの派生クラス「CTimer」クラスを作成します。
-
作成したCTimerクラスにメンバー変数を追加
生成されたクラスに、レジスタとして扱うための変数と、IRQ割り込みのための変数を定義します。これは、作成されたヘッダファイル CTimer.h を編集して行います。
派生クラスCTimerの信号初期化仮想ハード関数呼び出しの設定
次に、作成した派生クラスCTimerの初期化を行います。メンバ関数 Create()にその記述を行います。これは、CTimerクラス作成時に呼び出される関数です。作成したメンバ関数を、ハードウエアの信号として使用するための定義と、この後で作成する仮想タイマーの処理関数(1クロック相当の処理内容)を、クロックに同期して呼び出すための定義を行います。ソースコードは、次のようになります。
ソースコード中の「CREATE_SIG()」は、信号の入出力の指定、クロックとして扱うなどの役目の指定を行うマクロです。また、最後にある「SetHandler()」関数は、指定した信号変数の変化に対するイベントハンドラを定義する関数です。ここでは、クロック「m_clock」の立ち上がりエッジに対して、AlwaysClock()関数を呼び出すように設定しています。
1クロック相当のタイマー処理関数AlwaysClock()を作成
次には、上のSetHandler()で設定したタイマー動作の関数を作成します。
動作としては、イネーブル信号「m_enable」が有効な時にのみ動作を行い、本関数呼び出し毎にインクリメントされるカウンタ「m_counter」が、割り込み周期を指定する変数「m_period」よりも大きい場合に、カウンタをリセットして割り込みを発生させる様になっています。
割り込みは、CSsEventクラスの「Notify()」関数で発生させることができます。
定義したCTimerクラスを仮想ハードとして組み込む
以上で、CTimerクラスの定義は終わりました。これをタイマーとして動作させるために、IFビルダーのクラス構造の中のトップHWモジュールのクラス「CTopHwModule」にCTimerクラスのメンバを追加します。
さらに、このトップHWモジュール「CTopHwModule」の生成時に呼び出される初期化関数Create()に、メモリマップされた信号とCTimerクラスのメンバ変数を関連付ける記述(Join()関数)を加えます。以上で終了です。
ご理解いただけましたか?
WindowsやC++プログラミングに不慣れな方も多いと思いますが、仮想モデル作成は、想像よりも容易であると感じられたのではないでしょうか?より詳細な内容については、無料の定期セミナーを開催しておりますので、是非ご利用下さい。