简介
供SV,无论是构建测试激励,或模拟硬件的并行行为,DPI这是非常方便。上次我们介绍SV内通“import”导入和电话C性能。
在本节,通过一个简单的例子来说明C什么语言的函数调用SV的task和function。
1,SV部分
/* * test.v Rill create for dpi test at 2014-10-20 */ `timescale 1ns/1ns module tb; import "DPI-C" context function int c_func(input int num);// or import "DPI-C" context task c_display(input int num); reg tmp; initial begin #10 tmp = c_func(1); end m1 M1(); m2 M2(); endmodule // top module m1; import "DPI-C" context function void c_get_m1_scope(); export "DPI" function m1_add; reg tmp; reg [7:0] m1_value; function int m1_add(input [7:0] num); m1_add = num + m1_value; //or return (num + m1_value); endfunction // m1_add initial begin c_get_m1_scope(); m1_value = 8'd100; end endmodule // m1 module m2; import "DPI-C" context function void c_get_m2_scope(); export "DPI-C" task m2_add; reg tmp; reg [31:0] m2_value; task m2_add(input int num,output int sum); sum = num + m2_value; endtask // m2_add initial begin c_get_m2_scope(); m2_value = 32'd200; end endmodule // m1
2,C部分
/* * test.c Rill create for dpi test at 2014-10-20 */ #include <stdio.h> #include <svdpi.h> svScope tmp_scope; svScope m1_scope; svScope m2_scope; //import task/funcs from sv extern int m1_add(); extern int m2_add(); //==scope switch void c_get_tmp_scope(void) { tmp_scope = svGetScope(); } void c_set_tmp_scope(void) { svSetScope(tmp_scope); } void c_get_m1_scope(void) { m1_scope = svGetScope(); } void c_set_m1_scope(void) { svSetScope(m1_scope); } void c_get_m2_scope(void) { m2_scope = svGetScope(); } void c_set_m2_scope(void) { svSetScope(m2_scope); } //==export c funcs to sv int c_func(int num) { int m1 = 0; int m2 = 0; c_get_tmp_scope(); c_set_m1_scope(); m1 = m1_add(num); c_set_tmp_scope(); printf("m1:%d ",m1); c_get_tmp_scope(); c_set_m2_scope(); m2_add(num,&m2); c_set_tmp_scope(); printf("m2:%d ",m2); return 0; }
3,脚本
#! /bin/bash # # test.sh # usage: ./test.sh c/w/r # Rill create 2014-10-20 # TOP_MODULE=tb tcl_file=run.tcl CDS_INST_DIR=/home/openrisc/opt/edatools/IUS08.20 if [ $# != 1 ];then echo "args must be c/w/r" exit 0 fi if [ $1 == "c" ]; then echo "compile rtl lib..." ncvlog -f ./vflist -sv -update -LINEDEBUG; ncelab -delay_mode zero -access +rwc -timescale 1ns/10ps ${TOP_MODULE} echo "compile dpi lib" if [ -e libdpi.so ];then rm libdpi.so -f fi gcc -fPIC -shared -o libdpi.so test.c -I$CDS_INST_DIR/tools/inca/include exit 0 fi if [ -e ${tcl_file} ];then rm ${tcl_file} -f fi touch ${tcl_file} if [ $1 == "w" ];then echo "open wave..." echo "database -open waves -into waves.shm -default;" >> ${tcl_file} echo "probe -shm -variable -all -depth all;" >> ${tcl_file} echo "run" >> ${tcl_file} echo "exit" >> ${tcl_file} fi if [ $1 == "w" -o $1 == "r" ];then echo "sim start..." ncsim ${TOP_MODULE} -input ${tcl_file} fi echo "$(date) sim done!"
4,说明
细致体会我们上面构造的样例,有几个问题须要弄清楚。
a。scope的含义:
在SV端。m1是不能直接调用m2中的task/function的。所以m1里面调用的C函数也不能直接调用m2中export出来的task/function。假设想调用,必须进行scope切换。
b。SV端,有task和function的区分。可是在C端,并没有区分,一律是C函数。
5,关于用C模拟硬件的并行行为
方式a,将流水后面的模块写在前面。这样的方式我们之前介绍过(http://blog.csdn.net/rill_zhen/article/details/8464930),这里不再赘述。
方式b,将全部并行的信号写成例如以下形式:
用c,n两个变量模拟reg的值。
用init和update两个函数模拟reg的行为。
/* * parallel.c Rill create for simulater test at 2014-10-20 */ struct signal; struct sig_ops { int (*init) (struct signal*); int (*update) (struct signal*); }; struct signal { unsigned int c; //current cycle value unsigned int n; //next cycle value char name[32]; struct sig_ops* ops; }; /* veritual functions int sig_init(struct signal* signal) { return signal->ops->init(signal); } int sig_update(struct signal* signal) { return signal->ops->update(signal); } */ //actual functions int test_init(struct signal* signal) { signal->c = 0; signal->n = 0; return 0; } int test_update(struct signal* signal) { signal->c = signal->n; return 0; } int signal_create(struct signal* signal,char * name) { signal->name = name; } //============main.c====================// //example signal struct signal test; struct sig_ops test_ops = { test_init, test_update, }; int main() { signal_create(&test,"test"); //when reset test->ops->init(&test); //per cycle test->ops->update(&test); return 0; }