= !DocumentForDpiSample = ご注意 : 開発中のため、実際の動作と違っている箇所や、未実装な部分があります。 必要なドキュメント * クラス・ソースファイルとその機能 * ユーザプログラムの作り方 * ユーザプログラムを実機で使うためには * 対応プロセッサを追加するには * どうやって動いているのか(技術解説) == クラス・ソースファイルとその機能 == === c/c_side.cpp === このソースファイルが、シミュレータとC++実装部とのインタフェースです。 MPU.vをvlog -dpiheaderで処理して作ったヘッダ MPU_dpi.hを#includeして、 インポート対象となっている関数を実装しています。 === !MpuIf (c/cMpuIf.h) 基底クラス === ユーザプログラムに対して、プロセッサのインスタンスを操作(read,write)する方法を提供するインタフェースクラスです。 プロセッサに依存させないために、ユーザプログラムでは!MpuIfの派生クラスのヘッダ(Sh7751.hなど)は#includeしてはいけません。 === Mpu (c/cMpu.h) !MpuIfから派生 === ライブラリプログラムに対して、プロセッサのインスタンスを操作(createなど)する方法を提供するクラスです。 対応プロセッサを追加するときは、Sh7751クラスと同様にしてMpuクラスをpublic継承したクラスを作ります。 このクラスはmodel/MPU.vと対になっています。 === Sh7751 (c/cSh7751.h) Mpuから派生 === プロセッサの動作を実装するクラスの一例です。 このクラスはmodel/SH7751.vと対になっています。 === !MpuFactory (c/cMpuFactory.h) 基底クラス === Singleton(インスタンスが一個だけ)のクラスです。 Mpu派生クラスのインスタンスを生成するのが役割です。 === !MpuFactoryEnlarger (c/cMpuFactoryEnlarger.h) 基底クラス === !MpuFactoryに対して、実行時(ライブラリがロードされて静的オブジェクトの初期化が行われるとき)にプロセッサの作り方を 教える役割を持つクラスです。 Sh7751.cppなどの、Mpuから派生したクラスの実装の中で使います。 === Absorber (c/cAbsorber.h) クラスのテンプレート === シミュレータと実機の違いを吸収するためのテンプレートです。 テンプレートから作られたu32_c, u16_cなどが、FPGA構造体を定義するヘッダで使用されます。 なお、マクロREALWORLDが未定義の場合は、u32_cなどはCの組み込み型(unsigned int)のtypedefになり、Cでコンパイル 可能になります。 === Fpga (c/cFpga.h) 基底クラス === ''csvファイルの名前''クラスの基底クラスになります。 === ''csvファイルの名前'' (dpisample/msimv/''csvファイルの名前''.h) === csvファイルを元に自動作成されるクラスです。メンバ変数に、csvに書いたレジスタ群が入ります。 マクロ REALWORLD が定義されている場合はC++でなくCコンパイラでもコンパイル可能です。 === dpisample/c/accessfpga.cpp === ユーザプログラムの例です。Tcl実装版のaccessfpga.cを移植したものですが、 レジスタの参照および代入がより自然に行えるようになっています。 == ユーザプログラムの作り方 == FPGAのレジスタ情報が記述されたFpganame.csvファイルを作ります。 csvファイルからFpganame.hとFpganame.cppが自動作成されるので、 ユーザプログラム(以降user.cppと表記)で#include "Fpganame.h"します。 そうすると、Fpganameの持つレジスタfooは fpganame.foo = 0x12345678; のような代入をしたり、 unsigned value = fpganame.foo;のような参照をしたりできるようになります。 ユーザプログラムの中で時間待ちをしたいときは、fpganame.nop(uint32_t clocks)を呼び出してください。 クロック数ですから、時間を指定したい場合はnop(時間/クロック周期)としてください。 なお、fpganame.nop(uint32_t clocks)はマクロREALWORLDが定義されている場合はコンパイルエラーになります。 == ユーザプログラムを実機で使うためには == マクロ REALWORLD を定義した状態で、hoge.cppとuser.cppをコンパイルします。 REALWORLDが定義されているとhoge.cppはC++でなくCコンパイラでもコンパイル可能なので、 実機ではC++コンパイラが使えないというときでも大丈夫です。 user.cppは、C++の機能に依存しないように書けばCコンパイラでコンパイルできます。 == 対応プロセッサを追加するには == SH7751.vを参考にしてNEWCPU.vを作成し、Sh7751.hとSh7751.cppを参考にしてNewcpu.hとNewcpu.cppを作ります。 注意点 * 制御系の信号(CS,OE,WEなど)は、Verilog側とC++側で添え字を一致させなければなりません。 備考 * Newcpu::create(int mpu_id, const char *mpu_name)の 実装で、複数の文字列とマッチするようにすれば、仕様が少しだけ異なるプロセッサを同一のC++実装でサポートすることも可能です。