基于VCS使用VPI在verilog中调用c调用python进行仿真
遇到了这样一个需求,许多验证人员用python用的很熟练,但是只能通过vpi调用c代码,要用c代码实现相同功能的python代码过于繁琐,所以想着能不能在c中调用python中的方法,将其包一层变为c函数,然后用vpi调用这个c函数来实现:VPI—>C—>Python首先解决c调用pythonmain.c代码如下(引入头文件 Python.h ):代码中展示了调用有参python方法和
·
遇到了这样一个需求,许多验证人员用python用的很熟练,但是只能通过vpi调用c代码,要用c代码实现相同功能的python代码过于繁琐,所以想着能不能在c中调用python中的方法,将其包一层变为c函数,然后用vpi调用这个c函数来实现:
首先解决c调用python
main.c代码如下(引入头文件 Python.h ):
代码中展示了调用有参python方法和无参python方法两种用法
#include <stdio.h>
#include <Python.h>
/*
function callPythonFun();
pyName ----> python文件名
funcName---> python文件中要调用的函数名
pArg ------> 通过Py_BuildValue()格式化好的参数
*/
PyObject* callPythonFun(char* pyName,char* funcName,PyObject* pArg){
PyObject* pModule = NULL;
// PyObject* pDict = NULL;
PyObject* pFunc = NULL;
PyObject* result = NULL;
// PyRun_SimpleString("import os");
PyRun_SimpleString("import sys");
// PyRun_SimpleString("print(os.listdir(\"./\"))");
// PyRun_SimpleString("sys.path.append(\"/netapp/home/wenqi/tools/runpyinc\")");
PyRun_SimpleString("sys.path.append(\"./\")");// change path to current file
pModule = PyImport_ImportModule(pyName); //引入py file
if (!pModule)
{
printf("[ERROR]can't import python file\n");
return ;
}
pFunc = PyObject_GetAttrString(pModule, funcName); //从字典属性中获取函数
// printf("[NOTE]loading......\n");
// pFunc = PyObject_GetAttrString(pModule, "add");
if (!pFunc || !PyCallable_Check(pFunc))
{
printf("[ERROR]can't find function in python file\n");
return ;
}
result = PyEval_CallObject(pFunc, pArg); //调用函数,并得到python类型的返回值
return result;
}
int main()
{
// 直接调用python脚本的方法
// FILE * fp;
// char buffer[80];
// fp=popen("python test.py","r");
// fgets(buffer,sizeof(buffer),fp);
// printf("%s",buffer);
// pclose(fp);
//init python environment
Py_Initialize();
if (Py_IsInitialized())
{
// printf("init\n");
}else{
printf("[ERROR]py init fail\n");
return ;
}
// example 1
PyObject* pArg = Py_BuildValue("(i, i)", 1, 2); //参数类型转换,传递两个整型参数
PyObject* result = callPythonFun("mypy","add",pArg);// 使用接口调用python脚本中函数add(a,b)
int sum = 0;
PyArg_Parse(result, "i", &sum); //将python类型的返回值转换为c/c++类型, "i" ->>> int
printf("result = %d\n", sum);
// example 2
callPythonFun("mypy","printcharint",NULL);//无参数的情况
//close python environment
Py_Finalize();
return 0;
}
makefile文件:
all: run
run: main.o
@gcc -L/usr/lib64/python3.4/ -lpython3 main.o -o run
main.o: main.c
@gcc -c -w main.c -I/usr/include/python3.4/
clean:
@rm -rf *.pyc run
这里重点是链接上Python To C的库,具体的头文件和库文件位置需要对应自己的环境
mypy.py:
#!/tools/bin/python3
import os
import re
import sys
def add(a,b):
print("in python function add")
return a + b
def testout():
print ("in python function testout")
def printcharint():
charf = "charinfo"
intf = 1
print(charf + " " + str(intf))
if __name__=="__main__":
print("in python")
make后运行run结果如下:
[lee@ubuntu runpyinc]$ ./run
in python function add
result = 3
charinfo 1
解决基于VCS使用vpi调用包含了python的c
首先c文件要引入vpi_user.h
mod_info.c:
#include <stdio.h>
#include "vpi_user.h"
#include <Python.h>
void module_info()
{
vpiHandle moditH, topmodH;
moditH = vpi_iterate(vpiModule, NULL);
if(!moditH) {
vpi_printf(" Error: no modules in the design\n");
}
while (topmodH = vpi_scan(moditH)) {
vpi_printf("Top module Full Name: %s\n",vpi_get_str(vpiFullName, topmodH));
vpi_printf(" Top module Name: %s\n", vpi_get_str(vpiName, topmodH));
}
}
void register_my_systfs()
{
s_vpi_systf_data task_data_s;
p_vpi_systf_data task_data_p = &task_data_s;
task_data_p->type = vpiSysTask;
task_data_p->tfname = "$module_info";
task_data_p->calltf = (int(*)()) module_info;
task_data_p->compiletf = 0;
vpi_register_systf(task_data_p);
}
PyObject* callPythonFun(char* pyName,char* funcName,PyObject* pArg){
//………………………………略
}
void hello_world(){
vpi_printf("*********this is print by vpi************\n");
Py_Initialize();
if (Py_IsInitialized())
{
// printf("init\n");
}else{
printf("[ERROR]py init fail\n");
return ;
}
// example 1
PyObject* pArg = Py_BuildValue("(i, i)", 1, 2); //参数类型转换,传递两个整型参数
PyObject* result = callPythonFun("mypy","add",pArg);// 使用接口调用python脚本中函数add(a,b)
int sum = 0;
PyArg_Parse(result, "i", &sum); //将python类型的返回值转换为c/c++类型, "i" ->>> int
printf("result = %d\n", sum);
// example 2
callPythonFun("mypy","printcharint",NULL);//无参数的情况
//close python environment
Py_Finalize();
}
hello_world()即为包了一层的c调用python的方法,就是上面的main函数,因为只是被vpi调用,c中不需要有主函数的概念了
然后编译生成mod_info.o
makefile如下:
mod_info.o: mod_info.c
@gcc -c -w -fPIC mod_info.c -I/usr/include/python3.4/ -I/tools/install/synopsys/vcs_mx/vO-2018.09-SP2/include
clean:
@rm -rf *.o
这里与上面的不同是要添加上vpi_user.h头文件所在的目录,并且只需要生成.o,具体的路径还是要对应自己的环境,我这里是在VCS的目录下找到的
然后构建VCS仿真环境
已一个简单的案例为例:
pipe.v:
module pipe ( out, in, clk );
output out; reg out;
input in, clk;
always @ (in)
@ (posedge clk)
out <= repeat (2) @ (posedge clk) in;
endmodule
test.v:
module hello;
wire a, b, c;
initial
begin
$hello_world; //调用c中的调用python的方法
$module_info;
end
pipe p1 (a, b, c);
//stimuli
//monitor response
endmodule
vpi.tab:
$module_info call=module_info
$hello_world call=hello_world
启动脚本runvcs.sh:
vcs -R -full64 -fsdb -sverilog +vpi \
-v pipe.v \
test.v \
-lpython3 \
-P vpi.tab mod_info.o
最终的VCS仿真报告
../simv up to date
Chronologic VCS simulator copyright 1991-2018
Contains Synopsys proprietary information.
Compiler version O-2018.09-SP2-11_Full64; Runtime version O-2018.09-SP2-11_Full64; May 17 16:15 2022
*********this is print by vpi************
in python function add
result = 3
charinfo 1
Top module Full Name: hello
Top module Name: hello
V C S S i m u l a t i o n R e p o r t
Time: 0
CPU Time: 0.290 seconds; Data structure size: 0.0Mb
可以看到python中有参数和无参数的方法都已被正确调用,实际使用时还会向c中传参,还要交互等等,就看具体需求具体修改了,本文只是拼凑出了一种基于VCS使用VPI调用c再调用python的方法,具体效果不再详述。
更多推荐
所有评论(0)