4.8 Import ( Direct Programming Interface)


4.8.1 Hello World


It's very simple as below.

program hello_dpi_world;

	import "DPI-C" function void hello_world();


	initial begin
			hello_world();
	end
endprogram 


We recommend to use "vpi_printf" instead of using "printf".

#include "vpi_user.h"

#include "svdpi.h"
#include "..\source\dpi_veritak_header.h"

DPI_LINK_DECL DPI_DLLESPEC
void hello_world()
{
	vpi_printf("Hello DPI World! \n"); 


}


4.8.2 Call System
@
VeritakSV has not implemented $system function yet. However, you can simply write your own $system by DPI.
program dos_command_test;
	import "DPI-C" function int dos_command(string );

	initial dos_command("dir");

endprogram

In this project, we check No Bufffer on project setting.

The result is as follows.

***** Veritak SV6464 Engine Version 446 Build May 20 2013*****

 Volume in drive C has no label.
 Volume Serial Number is 422E-BEA3

 Directory of C:\Users\tak.sugawara\Documents\Visual Studio 2012\Projects\veritak_sv52\test\dpi_samples\system_call\source

2013/05/20  15:37    <DIR>          .
2013/05/20  15:37    <DIR>          ..
2013/05/20  15:37               512 dpi_veritak_header.h
2013/05/20  15:36             4,683 gen_header.vtakprj
2013/05/20  15:37               191 system_call.cpp
2013/05/20  15:39               123 system_call.sv
2013/05/20  15:38             4,715 system_call_x64_debug.vtakprj
2013/05/20  16:41               225 veritak_command.txt
               6 File(s)         10,449 bytes
               2 Dir(s)  877,000,818,688 bytes free

---------- Simulation finished. time=0ns


Here is c++ source.

#include "vpi_user.h"

#include "svdpi.h"
#include "..\source\dpi_veritak_header.h"

DPI_LINK_DECL DPI_DLLESPEC
int dos_command(const char*command)
{
	
	return system(command);
	
}





4.8.3 Passing Simple Values

Small integral values of inputs can be passed directly
However, for output or inout ports, they can not be passed directly. They can be passed by reference.

        import "DPI-C" function int  pass_simple_values(bit , reg , shortint,int ,longint, shortreal ,real,chandle ,string);
        import "DPI-C" function int  pass_simple_values_output(output bit , reg , shortint,int ,longint, shortreal ,real,chandle ,string);
        import "DPI-C" function int  pass_simple_values_inout(inout bit , reg , shortint,int ,longint, shortreal ,real,chandle ,string);
        import "DPI-C" function int  pass_str(output string);

        bit b1=1;
        reg r1=1'bz;
        shortint si=16'haabb;
        int      i=32'habcd_1234;
        longint l=64'hdead_beef_abcd_1234;
        shortreal sr=1.1;
        real r=1.11;
        chandle ptr=null;
        string s="Passing Simple Values";


        initial begin

                $display("returnd value=%x",pass_simple_values(b1,r1,si,i,l,sr,r,ptr,s));

                pass_simple_values_output(b1,r1,si,i,l,sr,r,ptr,s);
                $display("b1=%b r1=%b si=%x i=%x l=%x sr=%f r=%f ptr=%x s=%s",b1,r1,si,i,l,sr,r,ptr,s);

                $display("");

                pass_simple_values_inout(b1,r1,si,i,l,sr,r,ptr,s);
                $display("b1=%b r1=%b si=%d i=%d l=%d sr=%f r=%f ptr=%x s=%s",b1,r1,si,i,l,sr,r,ptr,s);

        end
endprogram 

You'll know how to pass the values by checking generated header file.
In "pass_simple_values" function all ports are input.Small integral values can be passed directly.
The other function's ports are output or inout. ( You can not declare ref in DPI.) In those cases, you must access the values by reference.

/* Copyright 2013 www.sugawara-systems.com 
* Note:
*   This file is automatically generated.
*   Please do not edit this file - you will lose your edits.*/

#ifndef INCLUDED_DPIHEADER
#define INCLUDED_DPIHEADER
#ifdef __cplusplus
#define DPI_LINK_DECL  extern "C" 
#else
#define DPI_LINK_DECL
#endif
#include "svdpi.h"

DPI_LINK_DECL DPI_DLLESPEC
int pass_simple_values(svBit 
			,svLogic 
			,short 
			,int 
			,int64_t 
			,float 
			,double 
			,const void* 
			,const char* );

DPI_LINK_DECL DPI_DLLESPEC
int pass_simple_values_inout(svBit* 
			,svLogic* 
			,short* 
			,int* 
			,int64_t* 
			,float* 
			,double* 
			,void** 
			,char** );

DPI_LINK_DECL DPI_DLLESPEC
int pass_simple_values_output(svBit* 
			,svLogic* 
			,short* 
			,int* 
			,int64_t* 
			,float* 
			,double* 
			,void** 
			,char** );

DPI_LINK_DECL DPI_DLLISPEC
 int run_sc_task_vthread(unsigned sc_back_patch_no, void* first_arg_address);
#endif


Below is an example source of c++.

#include "vpi_user.h"

#include "svdpi.h"
#include "..\source\dpi_veritak_header.h"

extern "C" __declspec(dllexport)
int pass_simple_values(svBit  bit
			,svLogic reg
			,short si
			,int i
			,int64_t l
			,float f //float is not Supported in VeritakSV. Use real(double) 
			,double d
			,const void* ptr
			,const char* s )
{
    
	
 vpi_printf("bit=%hhd reg=%hhd si=%hx int=%x, longint=%llx,f=%hf d=%g ptr=%x,s=%s \n",bit,reg,si,i,l,f,d,ptr,s);
	

	 
	return i;

}
DPI_LINK_DECL DPI_DLLESPEC
int pass_str(char**pp)
{
	static char buffer[100]="Hi, I'm C.";
	*pp=buffer;
	return 0;
}
DPI_LINK_DECL DPI_DLLESPEC
int pass_simple_values_inout(svBit* bit_p 
			,svLogic* logic_p
			,short*  short_p
			,int* int_p
			,int64_t* ll_p
			,float*  float_p
			,double* double_p
			,void** void_p
			,char** str_p)
{

	
	
	vpi_printf("I'm C. SV passing values are;bit=%hhd reg=%hhd si=%hx int=%x, longint=%llx,f=%hf d=%g ptr=%x,s=%s \n",*bit_p,*logic_p,*short_p,*int_p,*ll_p,*float_p,*double_p,*void_p,*str_p);
	


	*bit_p=1;
	*logic_p=0;
	*short_p=1234;
	*int_p=123456;
	*ll_p=123456789;
	*float_p=1110.1;
	*double_p=11110.1;
	*void_p=(void*)0;
	static char buffer[100]="Hi, I'm C again.";
	*str_p=buffer;
	return 0;
}

DPI_LINK_DECL DPI_DLLESPEC
int pass_simple_values_output(svBit* bit_p 
			,svLogic* logic_p
			,short* short_p
			,int* int_p
			,int64_t* ll_p
			,float* float_p
			,double* double_p
			,void** void_p
			,char** str_p)
{
	*bit_p=0;
	*logic_p=1;
	*int_p=0x5678abcd;
	*ll_p=0x123456789abcdef0;
	*float_p=110.1;
	*double_p=1110.1;
	*void_p=(void*)0;
	static char buffer[100]="Hi, I'm C.";
	*str_p=buffer;
	return 0;
}


***** Veritak SV6464 Engine Version 446 Build May 20 2013*****

bit=1 reg=2 si=aabb int=abcd1234, longint=deadbeefabcd1234,f=1.100000 d=1.11 ptr=0,s=Passing Simple Values 
returnd value=abcd1234
b1=0 r1=1 si=aabb i=5678abcd l=123456789abcdef0 sr=110.099998 r=1110.100000 ptr=0000000000000000 s=Hi, I'm C.

I'm C. SV passing values are;bit=0 reg=1 si=aabb int=5678abcd, longint=123456789abcdef0,f=110.099998 d=1110.1 ptr=0,s=Hi, I'm C. 
b1=1 r1=0 si=  1234 i=     123456 l=            123456789 sr=1110.099976 r=11110.100000 ptr=0000000000000000 s=Hi, I'm C again.

---------- Simulation finished. time=0ns

**** Test Done. Total 0.00[msec] ****

Data types mapping between SystemVerilog and C for small values

SystemVerilog C(input) C(output/inout)
byte char char*
shortint short short*
int int int*
longint long long int long long int*
shortreal float float*
real double double*
string const char* char**
chandle void* void**
bit char svBit*
logic char svLogic*

4.8.12 Call OpenCV

4.8.13 Call Python

@You can embed your Python in C and bind them to SystemVerilog functions using DPI.

Here is an example of Python called by C. A function named "multiply" receives 2 arguments from C, then return the result to C.

def multiply(a,b):
    print ("I'm Python,will compute", a, "times", b) 
    c = 0
    for i in range(0, a):
        c = c + b
    return c
def add (a,b):
    return a+b


4.8.13.1 Python Installation

First, you need python installation for your configuration.

Please note main program is simulator and python is now embeded program wrapped in C. Python itself can run both in 32bit and 64bit since it is interpreter based.. But interface to C needs explicit native linkage, such as x64(64bit) or X86(32bit).

In "libs" folder on Python, you'll find pythonxx.lib which should be imported to C program.

Native Language Python Insallation Remarks
VeritakWinSV6464 X64 (64bit) X86-64 MSI 64/64bit
VeritakWinSV6432 X86(32bit) X86 MSI 64/32bit
VeritakWinSV3232 X86(32bit) X86 MSI 32/32

4.8.13.2 C routine

We revised C program for DPI as below..

#include "vpi_user.h"

#include "svdpi.h"
#include "..\source\dpi_veritak_header.h"
#include 
#include 

__declspec(dllexport)
int  call_python(const char* file_name,const char* function_name,int arg1,int arg2)
{
        //vpi_printf("%s %s %d %d\n",file_name,function_name,arg1,arg2);
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue;
    int i;
        int result=0;
   
        int argc=5;//[0] call [1]:file_name [2]:function_name [3] arg1 [4] arg2
    
   try {
                Py_Initialize();
                pName = PyUnicode_FromString(file_name);
                // Error checking of pName left out 

                 pModule = PyImport_Import(pName);
                 Py_DECREF(pName);

                 if (pModule != NULL) {
                        pFunc = PyObject_GetAttrString(pModule, function_name);
                        //Func is a new reference 

                        if (pFunc && PyCallable_Check(pFunc)) {
                                pArgs = PyTuple_New(argc - 3);
                        
                                 for (i = 0; i < argc - 3; ++i) {
                                        switch (i){
                                                case 0: pValue=PyLong_FromLong(arg1); break;
                                                case 1: pValue=PyLong_FromLong(arg2); break;
                                                default: assert(0);

                                        }       
                
                                        if (!pValue) {
                                                Py_DECREF(pArgs);
                                                Py_DECREF(pModule);
                                                throw("Cannot convert argument\n");
                    
                                        }
                                        // pValue reference stolen here: 
                                         PyTuple_SetItem(pArgs, i, pValue);
                                }
                                pValue = PyObject_CallObject(pFunc, pArgs);
                                Py_DECREF(pArgs);
                                if (pValue != NULL) {
                                        result= PyLong_AsLong(pValue);
                                        printf("I'm C, Result of call: %ld\n",result);
                                        Py_DECREF(pValue);
                                }
                                else {
                                        Py_DECREF(pFunc);
                                        Py_DECREF(pModule);
                                        PyErr_Print();
                                        throw("Call failed\n");
                
                                }
                        }
                         else {
                                if (PyErr_Occurred())
                                        PyErr_Print();
                                throw("Cannot find function \n");
                        }
                        Py_XDECREF(pFunc);
                        Py_DECREF(pModule);
                }
                else {
                        PyErr_Print();
                        throw("Failed to load \n");
        
                }
                Py_Finalize();
                return result;
   }
   catch (const char* str )  //catach the exception.
        {
                
                vpi_printf("Python Call Exception %s(%d)\n", __FILE__,__LINE__);
                printf("%s",str);
                vpi_control(vpiFinish);
                return 0;
        }

}

4.8.3.3 SystemVerilog Routine

Finally, we call C as DPI function.

program call_python_test;

        import "DPI-C" function int call_python(string python_file, string function_name,int arg1,int arg2);

        int i;

        initial begin
                i=call_python("multiply","multiply",2,3);
                $display("I'm SV, result=%d\n",i);      
        
        end


endprogram

4.8.13.4 Result

We got the result of multiply from Python via C.


***** Veritak SV6464 Engine Version 446 Build May 18 2013*****

I'm C, Result of call: 6
I'm Python,will compute 2 times 3
I'm SV, result= 6

You'll find out displaying order is strange. This is caused by different C-runtime libraries on DLLs. For C, we can use the same version of C compiler, but Python may use another version if we don't compile it from source.