数字集成电路设计-15-DPI(续)

来源:互联网 发布:安装包制作工具 知乎 编辑:程序博客网 时间:2024/03/29 06:23

引言


对于SV,无论是构造测试激励,还是模拟硬件的并行行为,DPI都是非常方便的。上次我们介绍了SV里面通过“import”导入并调用C函数。

本小节,我们通过一个简单的例子来说明C语言函数如何调用SV的task和function。


1,SV部分


/** test.v  Rill create for dpi test at 2014-10-20*/`timescale 1ns/1nsmodule 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 // topmodule 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 // m1module 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;   endendmodule // 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 svextern int m1_add();extern int m2_add();//==scope switchvoid 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 svint 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\n",m1);  c_get_tmp_scope();  c_set_m2_scope();  m2_add(num,&m2);  c_set_tmp_scope();  printf("m2:%d\n",m2);  return 0; }




3,脚本


#! /bin/bash## test.sh# usage: ./test.sh c/w/r# Rill create 2014-10-20#TOP_MODULE=tbtcl_file=run.tclCDS_INST_DIR=/home/openrisc/opt/edatools/IUS08.20if [ $# != 1 ];thenecho "args must be c/w/r"exit 0fiif [ $1 == "c" ]; thenecho "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 ];thenrm libdpi.so -ffigcc -fPIC -shared -o libdpi.so test.c -I$CDS_INST_DIR/tools/inca/includeexit 0fiif [ -e ${tcl_file} ];thenrm ${tcl_file} -ffitouch ${tcl_file}if [ $1 == "w" ];thenecho "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}fiif [ $1 == "w" -o $1 == "r" ];thenecho "sim start..."ncsim  ${TOP_MODULE} -input ${tcl_file}fiecho "$(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 valueunsigned int n; //next cycle valuechar name[32];struct sig_ops* ops;};/* veritual functionsint sig_init(struct signal* signal){return signal->ops->init(signal);}int sig_update(struct signal* signal){return signal->ops->update(signal);}*///actual functionsint 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 signalstruct signal test;struct sig_ops test_ops ={test_init,test_update,};int main(){signal_create(&test,"test");//when resettest->ops->init(&test);//per cycletest->ops->update(&test);return 0;}





2 0
原创粉丝点击