|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
3 Z7 R0 S: J9 F) r3 U( y+ B: g引言6 c9 ~5 z+ z$ [) Z
- h4 B$ g! r! C7 @* a
对于SV,无论是构造测试激励,还是模拟硬件的并行行为,DPI都是非常方便的。上次我们介绍了SV里面通过“import”导入并调用C函数。8 ]6 y. s( }/ r9 A
7 K$ d) r. A. r8 B" ]
本小节,我们通过一个简单的例子来说明C语言函数如何调用SV的task和function。6 o: n, C2 O! q8 a
: n* r7 |% `. u5 [4 m% n# Q: T. ~6 E" p
1,SV部分4 ^4 i* E) I) O' l3 |: K
/ Y. g( v* b8 Z
6 s% {: r: T" v- /*
- * test.v Rill create for dpi test at 2014-10-20
- */
- # i* @! F6 j& U3 Z
- `timescale 1ns/1ns
+ q/ M: k; J. ?$ I7 S* j- 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
- * A, j" c* o, R) G7 U) y
- m1 M1();
- m2 M2();
- endmodule // top
9 w9 i. F: r2 a: {- module m1;
- import "DPI-C" context function void c_get_m1_scope();
- export "DPI" function m1_add;
- , X0 F2 ?' t. s8 B- S5 E( T1 Y
- 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
- : w w; j" V) c: ^( u u0 \/ V) Q! {1 g' }
- initial begin
- c_get_m1_scope();
- m1_value = 8'd100;
- end
- endmodule // m1
- ' H+ ?4 ]5 N V9 e; X- Y, [
4 U: o, f7 ]! [6 f. X. l- module m2;
- import "DPI-C" context function void c_get_m2_scope();
- export "DPI-C" task m2_add;
: @* U' l0 c2 D! a8 j$ `- reg tmp;
- reg [31:0] m2_value;
- task m2_add(input int num,output int sum);
- sum = num + m2_value;
- endtask // m2_add
: s' n( Z3 ?- t; {. @- initial begin
- c_get_m2_scope();
- m2_value = 32'd200;
- end
- 6 ]7 A# m$ A0 K. T1 w7 L; W
- endmodule // m1
" y2 Y% e( h1 h! ~ o+ m9 k F# O# G7 P( T9 b
+ t" @* @' X. j4 I2 m [- I( P- `) P8 C2,C部分
; Z; f4 Q4 \- s4 A4 H# v3 L% Y+ d {. E t0 b1 A. A& v- g7 L
7 ]8 @6 @! U3 \! v- T8 |- /*
- * test.c Rill create for dpi test at 2014-10-20
- */
- ) I2 j+ k5 f5 F6 m7 p* Z: E' n0 q
- #include <stdio.h>
- #include <svdpi.h>
% p1 a4 s6 R- I' a1 S- svScope tmp_scope;
- svScope m1_scope;
- svScope m2_scope;
- ' V; D* C& {- w. {+ k, u& N
- //import task/funcs from sv
- extern int m1_add();
- extern int m2_add();
" v8 ?0 v k6 F- //==scope switch
- void c_get_tmp_scope(void)
- {
- tmp_scope = svGetScope();
- }
- 6 E9 Q M( @# a( v( R' ?6 }' K
- void c_set_tmp_scope(void)
- {
- svSetScope(tmp_scope);
- }
- h7 o3 t( u* ~; C" b. L9 H" o
- void c_get_m1_scope(void)
- {
- m1_scope = svGetScope();
- }
- & S5 I) k) H# A% X, F' w
- void c_set_m1_scope(void)
- {
- svSetScope(m1_scope);
- }
. Q4 I3 P6 X7 \" p- void c_get_m2_scope(void)
- {
- m2_scope = svGetScope();
- }
/ N- x/ `% O& ]# t1 E- g- void c_set_m2_scope(void)
- {
- svSetScope(m2_scope);
- }
- , `1 ^5 w$ `" L/ A
- //==export c funcs to sv
- int c_func(int num)
- {
- int m1 = 0;
- int m2 = 0;
% o( A/ V, \0 t: l- c_get_tmp_scope();
- c_set_m1_scope();
- m1 = m1_add(num);
- c_set_tmp_scope();
- printf("m1:%d\n",m1);
& j. w, ~7 p* x; C$ A @7 Z- c_get_tmp_scope();
- c_set_m2_scope();
- m2_add(num,&m2);
- c_set_tmp_scope();
- printf("m2:%d\n",m2);
; p. Z7 u6 a! _, j) `) T% o- return 0;
- }
3 b7 \1 R4 n8 O) f6 V9 l
$ J8 G* q+ J5 c, U- u0 b
( {# G0 J9 M( X3,脚本7 S0 W$ n5 I* f g8 v
3 n' T( W5 O+ |, x/ g
% Z* S& x: @8 n1 S- v6 Y5 r0 ]' n& W- #! /bin/bash
- 5 i N3 j Q: T/ I) c" j
- #
- # test.sh
- # usage: ./test.sh c/w/r
- # Rill create 2014-10-20
- #
; w( i' f$ r8 ]! ?4 c4 R- ) R; j8 z/ j0 ~* J7 e. ]1 f
- TOP_MODULE=tb
. i; y M2 [. O* ^" g. T& \- tcl_file=run.tcl
( @* q* K* _& L, x( o! W7 A- CDS_INST_DIR=/home/openrisc/opt/edatools/IUS08.20
- ; n$ S2 |- M. n2 s8 W
- 2 Z3 Z8 C1 @( N! q' H% Q
- if [ $# != 1 ];then
- echo "args must be c/w/r"
- exit 0
- fi
- 6 t& w! N/ p. ~/ ?( l4 n* w1 o
- 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}
X6 L% j+ \: A2 k+ x- echo "compile dpi lib"
- if [ -e libdpi.so ];then
- rm libdpi.so -f
- fi
) s6 t% d2 r4 |* \- gcc -fPIC -shared -o libdpi.so test.c -I$CDS_INST_DIR/tools/inca/include
- exit 0
- fi
- - i/ E1 |' H/ w6 m+ a
8 [% E2 t+ ]( Z, J. w( l- if [ -e ${tcl_file} ];then
- rm ${tcl_file} -f
- fi
- touch ${tcl_file}
- # C6 t/ J: T2 t1 q
- 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
) ~- @' M, B" U5 K6 @6 V- if [ $1 == "w" -o $1 == "r" ];then
- echo "sim start..."
- ncsim ${TOP_MODULE} -input ${tcl_file}
- fi
6 {2 K6 |- |) T' I- echo "$(date) sim done!"
- e! d0 e- E. X/ K2 \ + }7 q( I5 \- C6 Q4 U8 q: f
( K% A) w A9 l4,说明2 o3 M1 f7 G0 q, x6 h8 ~9 W b$ G
仔细体会我们上面构造的例子,有几个问题需要弄清楚。
& T- q s: B' w6 r7 G, ~4 ]% x/ D4 H7 r% ~+ Y' y& M. k
a,scope的含义:# \5 E# \4 z5 {$ G7 ?
' K7 K& a9 [9 _. x; Q' F7 N在SV端,m1是不能直接调用m2中的task/function的,所以m1里面调用的C函数也不能直接调用m2中export出来的task/function,如果想调用,必须进行scope切换。
/ J& x( l8 q* ?4 ^# X( \7 P4 O1 U
b,SV端,有task和function的区分,但是在C端,并没有区分,一律是C函数。
) ~# G3 k& i5 t8 t" D2 a+ e2 x& Z' \) U% c! S" f# u6 G/ w
% n$ k% H# c1 S! @9 X( { q5,关于用C模拟硬件的并行行为+ B" O4 u" b! w, O( z
' F( p) F7 k9 B# Y+ K3 {方式a,将流水后面的模块写在前面。" Q N* d( F' \
2 R5 R3 G3 s& b. q4 G8 E方式b,将所有并行的信号写成如下形式:
! n! w# _% L3 m z$ \' x1 V. I0 E; r9 d! s$ X% D0 X! F
用c,n两个变量模拟reg的值。/ P. F1 F& U, K# ~) X1 w8 v
) b+ L( l# `* V( m* I' y7 J* a用init和update两个函数模拟reg的行为。
! {' K" A: ^* M: p3 u% F" U( h, l# Z# c, S$ C: z! ~
- /*
- * parallel.c Rill create for simulater test at 2014-10-20
- */
- ; Y" S+ F; {) D5 Y T
- / F+ D" C3 M- T& I/ N3 p
- struct signal;
: K9 l( g8 g N. u- struct sig_ops
- {
- int (*init) (struct signal*);
- int (*update) (struct signal*);
- };
# z, [( |" B; P& k- struct signal
- {
- unsigned int c; //current cycle value
- unsigned int n; //next cycle value
- char name[32];
- struct sig_ops* ops;
- };
- 8 {9 X4 b* o/ W j# o
- /* veritual functions
- int sig_init(struct signal* signal)
- {
- return signal->ops->init(signal);
- }
- 8 T" V2 @8 i9 r$ Z' W
- int sig_update(struct signal* signal)
- {
- return signal->ops->update(signal);
- }
- */
- t1 L' \, b6 X- //actual functions
- int test_init(struct signal* signal)
- {
- signal->c = 0;
- signal->n = 0;
- return 0;
- }
5 b6 A) a+ D0 k- int test_update(struct signal* signal)
- {
- signal->c = signal->n;
- return 0;
- }
- / D- m' F) D q8 R1 |6 f
6 E9 L* w, c: B8 @* t) E) w9 v( @
( c% |" ^* j8 w1 `' @8 ?6 L6 C- int signal_create(struct signal* signal,char * name)
- {
- signal->name = name;
- }
- ; J ^1 G+ J3 {# Z, j
- //============main.c====================//
- //example signal
- struct signal test;
- struct sig_ops test_ops =
- {
- test_init,
- test_update,
- };
! M) U4 [) K8 x1 v! a& b" I- ]- int main()
- {
- signal_create(&test,"test");
- //when reset
- test->ops->init(&test);
- //per cycle
- test->ops->update(&test);
- return 0;
- }$ ]6 \" W6 Y% F( T
" F: [- ? |: h" X3 o7 J0 q
" e5 w- Z, w. `/ i1 c& @% {! _/ D M. f1 V/ P
- M1 \) G9 K6 u2 B) [8 n7 k
* ^. }9 M& Y. y% ?' U# M% h
6 P1 a. n+ N, ^; J/ G- @$ k0 k
i' T9 S# u+ k
$ i |7 E2 j [! ? |
|