|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
: U8 s9 e+ }5 O) ~5 y引言; @' w/ o$ n; c1 ~# b6 T" f
, a; ` Y# M/ T/ c
对于SV,无论是构造测试激励,还是模拟硬件的并行行为,DPI都是非常方便的。上次我们介绍了SV里面通过“import”导入并调用C函数。8 K% T% H7 j! u7 s% ^% [+ p
! l% V6 J5 ~. U* b7 K- Y5 n+ Q; g本小节,我们通过一个简单的例子来说明C语言函数如何调用SV的task和function。
$ ^4 F9 w- _/ O
: Q0 J4 S) V2 n8 `, q; m" E! p r
* D5 w' O9 D8 p5 u+ {9 f- ~' |7 ?1,SV部分
* q$ Y* }& A4 I3 S8 H( w+ N0 ^8 z: W! f- l4 o5 s
2 g8 S7 t% m% c
- /*
- * test.v Rill create for dpi test at 2014-10-20
- */
- e* J+ R2 }" z. ?/ ~
- `timescale 1ns/1ns
% z. ?7 L; z1 Y1 _7 |( }3 }- 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
^- l2 Q6 P* `, f9 d+ L& p* [- m1 M1();
- m2 M2();
- endmodule // top
3 k }" k$ q2 m; r3 |1 C" _- module m1;
- import "DPI-C" context function void c_get_m1_scope();
- export "DPI" function m1_add;
! y" G; C) r$ C2 K3 d) E" a- 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
* g! D% F/ k+ Z1 X( z1 O0 W- initial begin
- c_get_m1_scope();
- m1_value = 8'd100;
- end
- endmodule // m1
* ?8 j: S6 o" @4 l- % ?8 `% I. G% J9 X5 u
- module m2;
- import "DPI-C" context function void c_get_m2_scope();
- export "DPI-C" task m2_add;
- $ X' ^& c# L/ A
- reg tmp;
- reg [31:0] m2_value;
- task m2_add(input int num,output int sum);
- sum = num + m2_value;
- endtask // m2_add
- 5 b" H( k; T, o5 U& g
- initial begin
- c_get_m2_scope();
- m2_value = 32'd200;
- end
; |3 Q2 B' T. J4 A- endmodule // m18 p- g/ P: q" k
) u j6 `( N m" C S/ K: X
: C: A1 b' _& C* e o, r2,C部分+ ]* ^( t( d1 m& B1 n, L" \+ N
. ~0 j" X4 R0 N3 x; N5 ^5 X$ j
$ n7 {8 n) S: d# [" `6 q
- /*
- * test.c Rill create for dpi test at 2014-10-20
- */
- ; r8 e( u8 I" c S ^; e
- #include <stdio.h>
- #include <svdpi.h>
- ! e% F' _' O7 Y' A* t* [% I
- svScope tmp_scope;
- svScope m1_scope;
- svScope m2_scope;
- : p( Q4 T; g# j H
- //import task/funcs from sv
- extern int m1_add();
- extern int m2_add();
+ i: {% b& G0 G* @) w- //==scope switch
- void c_get_tmp_scope(void)
- {
- tmp_scope = svGetScope();
- }
- ( V) p- z1 R3 P" w# L- S
- void c_set_tmp_scope(void)
- {
- svSetScope(tmp_scope);
- }
- ! g5 }) i: l$ n! {' k
- void c_get_m1_scope(void)
- {
- m1_scope = svGetScope();
- }
- , h5 t6 h( ?- _: [
- void c_set_m1_scope(void)
- {
- svSetScope(m1_scope);
- }
/ R7 y4 W# s: g' b+ x5 J) p( V- void c_get_m2_scope(void)
- {
- m2_scope = svGetScope();
- }
; N& X" v" J1 E, R& g! Z8 i- void c_set_m2_scope(void)
- {
- svSetScope(m2_scope);
- }
) e3 d8 T6 C3 \* k1 M- //==export c funcs to sv
- int c_func(int num)
- {
- int m1 = 0;
- int m2 = 0;
9 h# Q# z: U9 ?- c_get_tmp_scope();
- c_set_m1_scope();
- m1 = m1_add(num);
- c_set_tmp_scope();
- printf("m1:%d\n",m1);
* @( B9 e: h9 m& c( H& i- c_get_tmp_scope();
- c_set_m2_scope();
- m2_add(num,&m2);
- c_set_tmp_scope();
- printf("m2:%d\n",m2);
% p0 T6 ^3 X; d7 D- return 0;
- }' G+ T! t& ^) |: G' |( y( c
& A; s5 N/ V+ o$ x( S
" N5 y# x; ?) \1 \3 g" |3,脚本* v# p/ s5 ~- `
2 _! Q8 V$ H& i* z1 f' F7 z# R, R
+ ]( f) k1 \: {7 t N- #! /bin/bash
- # `2 D T( { P: l
- #
- # test.sh
- # usage: ./test.sh c/w/r
- # Rill create 2014-10-20
- #
- ; A$ [3 L0 S2 {+ f- J, E' v
9 m" @- X+ L" z, f8 m7 S: G( h- TOP_MODULE=tb
- ; ^0 D" f/ T; K) Y" b
- tcl_file=run.tcl
- 3 N, }; J& ~/ M- s7 c9 ^ I0 L J
- CDS_INST_DIR=/home/openrisc/opt/edatools/IUS08.20
- 7 I2 I/ h5 o+ s/ h- \ c1 B
- _+ v) U# x9 X8 L3 O2 b+ F- if [ $# != 1 ];then
- echo "args must be c/w/r"
- exit 0
- fi
- 9 y6 f4 x/ k! t5 v
- 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}
- . z X5 x$ l' ^# V* G; ]
- echo "compile dpi lib"
- if [ -e libdpi.so ];then
- rm libdpi.so -f
- fi
- . ^! V4 y1 T' m1 e2 m4 l
- gcc -fPIC -shared -o libdpi.so test.c -I$CDS_INST_DIR/tools/inca/include
- exit 0
- fi
- , c# {8 X, K0 _/ R
- ( [/ h9 [* T1 U& r9 h, U
- if [ -e ${tcl_file} ];then
- rm ${tcl_file} -f
- fi
- touch ${tcl_file}
- + I; `# L0 Y1 H$ ^
- 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
7 F8 q: ~ k4 f- V& i6 L- if [ $1 == "w" -o $1 == "r" ];then
- echo "sim start..."
- ncsim ${TOP_MODULE} -input ${tcl_file}
- fi
- ' y$ Z7 y4 F9 \7 C1 O
- echo "$(date) sim done!"2 n* ?$ m9 |; a/ W2 M1 l
2 c: h" ?) d/ V4 w
0 N+ B( _" b* j( T; V' \7 k& s4,说明
6 Z9 L$ U; ^ D G仔细体会我们上面构造的例子,有几个问题需要弄清楚。/ l9 c. R' k# g: B7 ?6 E
( D5 f9 o5 E! ~' l0 e( s, f3 Q3 p
a,scope的含义:. N- R2 g% [4 J
% ^6 Z: K; @* P& z; F在SV端,m1是不能直接调用m2中的task/function的,所以m1里面调用的C函数也不能直接调用m2中export出来的task/function,如果想调用,必须进行scope切换。- Z5 [" P; M1 `/ W* }" e+ G
) P. `( w+ S& \
b,SV端,有task和function的区分,但是在C端,并没有区分,一律是C函数。8 Q+ h# Y0 f& u* i( r
0 I# ^8 w7 g2 v q5 H. r/ r, v
! w$ D! {' U/ |7 k+ n5,关于用C模拟硬件的并行行为4 u" L# I4 K1 l8 r9 [& S; M2 f v4 W1 E
|3 R# V& O$ V! T方式a,将流水后面的模块写在前面。
8 |' Y; y. Y3 Z# i, s3 I3 t+ I! ^# I; Y
方式b,将所有并行的信号写成如下形式:
6 v4 m$ L# @# F5 I% j" v, I5 B
, w' w* ]9 h3 [6 k用c,n两个变量模拟reg的值。
+ c3 @3 L) K }7 A! y& u. T# b
用init和update两个函数模拟reg的行为。2 L/ b1 \ E& j- r2 [% S0 r
4 P c/ Z6 G3 Z9 f4 E- /*
- * parallel.c Rill create for simulater test at 2014-10-20
- */
- ! X) T; ?' m8 H6 Y6 q# t; e j
: M Q! O' ]7 m4 u* h- struct signal;
- N A, L) t) K- `
- struct sig_ops
- {
- int (*init) (struct signal*);
- int (*update) (struct signal*);
- };
- " s) y) ? v/ {6 d C; X
- struct signal
- {
- unsigned int c; //current cycle value
- unsigned int n; //next cycle value
- char name[32];
- struct sig_ops* ops;
- };
- & D" E H0 C- J. _
- /* veritual functions
- int sig_init(struct signal* signal)
- {
- return signal->ops->init(signal);
- }
- + n* I W* l; c3 F& m- J
- int sig_update(struct signal* signal)
- {
- return signal->ops->update(signal);
- }
- */
# u) k' ] k, F! m0 `: q- //actual functions
- int test_init(struct signal* signal)
- {
- signal->c = 0;
- signal->n = 0;
- return 0;
- }
- - a8 s' O3 P: N6 z( @
- int test_update(struct signal* signal)
- {
- signal->c = signal->n;
- return 0;
- }
- # [6 Z' h/ R/ X" g; v& s! K+ k
- , L* v: o+ V6 N) _8 X' n
- ) w2 u0 P Y- p! z/ E* r$ H9 Q5 P
- int signal_create(struct signal* signal,char * name)
- {
- signal->name = name;
- }
5 `' I8 ?- {' j- //============main.c====================//
- //example signal
- struct signal test;
- struct sig_ops test_ops =
- {
- test_init,
- test_update,
- };
: t4 \' _3 ]. g v$ C4 `- int main()
- {
- signal_create(&test,"test");
- //when reset
- test->ops->init(&test);
- //per cycle
- test->ops->update(&test);
- return 0;
- }" I& C8 y) L7 C. @2 j
9 n5 J& X$ b0 J2 S9 [3 \3 V1 K7 R
8 j+ C9 o/ D& B5 O
$ x+ E& W" P/ w! E+ }0 Z: w% J9 |# _2 r! S, {+ {* n
* T5 A/ J! e/ z" A! J
( c* T$ L8 |# M& m' _
]$ I% I$ n! l& `" ^* `* i$ J3 J4 Z5 q
|
|