Vengineerの妄想(準備期間)

人生は短いけど、長いです。人生を楽しみましょう!

Xilinx ZynqMP SoC VIP の中を調べる(その12)

はじめに

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) の中身をみてみました。

次回は、シミュレーションの実行について、説明します。