仕様によりますが、当然、検証部隊にはどのベンダーのメモリモデルでもそのCHIPが動作する事をSimulation上で確認する事が要求される訳です。特定の1社のSPI-Flashのみ動作可能で他ベンダーは保障外なんて仕様があるはずもなく、そんな仕様にしたらユーザも黙っていないですし。
そこで検証担当者は各ベンダーからメモリモデルをダウンロードし、せっせと検証環境に組み込みます。
最初になにも考えずにChipに接続します。
各ベンダーで微妙にInterface名が違いますのでここでは、A社、B社、C社のメモリモデルが存在し、それぞれSCK、SI、SO、CS信号を持つ物として記述しています。CHIPのMoudleのTop名はCHIPAとしています。そのポートは製品では1portしかなく1対1の接続である前提とします。
CHIPA dut( (an omission) // SPI Flash Interface. .SCK(SCK), .CS(CS), .SI(SI), .SO(SO), (an omission) ); // A社のメモリモデル SPIFlashA SPIFlashA( .SCK(SCK), .CS(CS), .SI(SI), .SO(SO) ); // B社のメモリモデル SPIFlashB SPIFlashB( .SCK(SCK), .CS(CS), .SI(SI), .SO(SO) ); // C社のメモリモデル SPIFlashB SPIFlashC( .SCK(SCK), .CS(CS), .SI(SI), .SO(SO) );
このままでは3つのモデルが同時に動作してしまいます。そこでそれぞれの3つが同時に動作しないようにスイッチを入れます。
私がRTL設計から検証に移った頃は下記のようにifdefを使用していました。
ifdefはコンパイラ指示子と呼ばれます。
私が居た職場では"compile switch"と呼んでいました。これはSynopsys社のSimulatorのVCSやCadence社のNCシリーズのSimulatorではcompile用のoptionで指定していたのでこう呼ぶようになっていました。
CHIPA dut( (an omission) // SPI Flash Interface. .SCK(SCK), .CS(CS), .SI(SI), .SO(SO), . (an omission) ); // A社のメモリモデル 'ifdef BENCHUSE_SPI_A SPIFlashA SPIFlashA( .SCK(SCK), .CS(CS), .SI(SI), .SO(SO) ); 'endif // 'ifdef BENCHUSE_SPI_A // B社のメモリモデル 'ifdef BENCHUSE_SPI_B SPIFlashB SPIFlashB( .SCK(SCK), .CS(CS), .SI(SI), .SO(SO) ); 'endif // 'ifdef BENCHUSE_SPI_B // C社のメモリモデル 'ifdef BENCHUSE_SPI_C SPIFlashC SPIFlashC( .SCK(SCK), .CS(CS), .SI(SI), .SO(SO) ); 'endif // 'ifdef BENCHUSE_SPI_C
compile時に"+define+BENCHUSE_SPI_A"のようにOption指定することで必要なベンチが接続されるようになります。
実はこれだと規模の巨大なchip検証環境ではかなり致命的な問題が発生します。
単体検証環境では再compileしても数分もかからないのですが、chip検証単位では規模にもよりますがcompileだけで数時間かかってしまう事もあります。さらにcompileによる中間ファイルの容量は作業用ディスクを圧迫してしまいます。
そこで"runtime switch"による制御に切り替えるのです。次のページで説明します。