はじめに
Xilinx ZynqMP SoC VIP の中を調べる(その12)
今回は、xelab コマンドへの --dpiheader オプションによって生成された dpi.h をみてみます。
dpi.h
--dpiheader dpi.h にて生成された dpi.h は、次のようになっています。4つの関数のプロトタイプ宣言になります。SystemVerilog 側の export task は戻り値の型が int になっています。
- DPI_LINKER_DECL DPI_DLLESPEC int dpi_main();
- DPI_LINKER_DECL int vip_nop( int count );
- DPI_LINKER_DECL int vip_write32( unsigned int addr, unsigned int data );
- DPI_LINKER_DECL int vip_read32( unsigned int addr, unsigned int* data );
/**********************************************************************/
/* ____ ____ */
/* / /\/ / */
/* /___/ \ / */
/* \ \ \/ */
/* \ \ Copyright (c) 2003-2020 Xilinx, Inc. */
/* / / All Right Reserved. */
/* /---/ /\ */
/* \ \ / \ */
/* \___\/\___\ */
/**********************************************************************/
/* NOTE: DO NOT EDIT. AUTOMATICALLY GENERATED FILE. CHANGES WILL BE LOST. */
#ifndef DPI_H
#define DPI_H
#ifdef __cplusplus
#define DPI_LINKER_DECL extern "C"
#else
#define DPI_LINKER_DECL
#endif
#include "svdpi.h"
/* Imported (by SV) task */
DPI_LINKER_DECL DPI_DLLESPEC int dpi_main(
);
/* Exported (from SV) task*/
DPI_LINKER_DECL int vip_nop(
int count
);
/* Exported (from SV) task*/
DPI_LINKER_DECL int vip_write32(
unsigned int addr, unsigned int data
);
/* Exported (from SV) task*/
DPI_LINKER_DECL int vip_read32(
unsigned int addr, unsigned int* data
);
#endif
上記の4つの関数の内、dpi_main 関数は、テストプログラム内で定義します。それ以外の3つの関数はどこで定義されているんでしょうか?
DPI export task はどこで定義されている?
これら3つのファイルは、xsim.dir/tb_behv/obj/xsim_27.c の中で定義されています。
extern "C" {
extern "C" {
DPI_DLLESPEC
int vip_nop(int arg0)
{
int result ;
DPIVerifyScope();
int functionToCall = staticScopeCheck("vip_nop") ;
switch(functionToCall)
{
case 0:
{
DPI_DLLESPEC
int vip_write32(unsigned int arg0, unsigned int arg1)
{
int result ;
DPIVerifyScope();
int functionToCall = staticScopeCheck("vip_write32") ;
switch(functionToCall)
{
case 1:
{
DPI_DLLESPEC
int vip_read32(unsigned int arg0, unsigned int* arg1)
{
int result ;
DPIVerifyScope();
int functionToCall = staticScopeCheck("vip_read32") ;
switch(functionToCall)
{
switch(functionToCall)
{
case 2:
{
3つの関数の最初は、ほぼ同じです。staticScopeCheck 関数の引数の文字列が各関数名になっているだけです。staticScopeCheck 関数の戻り値の使い方がちょっと違うようで、vip_nop が 0、vip_write32 が 1、vip_read32 が 2 になっているので、各関数の番号がそうなっているんでしょうね。
int result ;
DPIVerifyScope();
int functionToCall = staticScopeCheck("vip_XXX") ;
switch(functionToCall)
{
case 1:
{
それ以降のコードでは、だいたい同じでDPIInitialzeTask からDPIInvokeTask までが違うようです。
{
DPIFlushAll();
int staticIndex = 0 ;
char* IP = NULL ;
staticIndex = svGetScopeStaticId() ;
IP = svGetScopeIP();
int callingProcessOffset = DPIGetTaskCaller() ;
char* SP ;
void* oldSPcontext = DPIGetCurrentContext();
// この部分が違う
DPIYieldCurrentContext() ;
DPIDeleteTaskInvocation(SP) ;
*((char**)(IP + callingProcessOffset + 80)) = oldSP ;
DPISetCurrentContext(oldSPcontext);
DPIFlushAll();
if (*(unsigned int*)(SP + 155) == 1)
{
result = 1 ;
}
else
{
result = 0 ;
}
}
おわりに
今回は、xelab コマンドが生成した、dpi.h と DPI-C export task に対応する Cの関数 (vip_nop, vip_read32, vip_write32) の中身をみてみました。
次回は、シミュレーションの実行について、説明します。