|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
+ D, M' N5 O- Z x) l; E引言* N: L5 x8 e0 B1 Y. j5 b# F
; O' w" f8 h, P& X. |
对于SV,无论是构造测试激励,还是模拟硬件的并行行为,DPI都是非常方便的。上次我们介绍了SV里面通过“import”导入并调用C函数。8 ^ W+ N7 {. f, p
3 v3 d& s& f% O# V% l本小节,我们通过一个简单的例子来说明C语言函数如何调用SV的task和function。4 Y4 z. A9 ^* c; J# i- r2 }& O
: b; O' x, k( w
& P( v* V9 {. Q1 r+ E1,SV部分# [- ` | L" G. O% y
. S! W$ e% y! P
. N- h4 b) T8 Q- /*
- * test.v Rill create for dpi test at 2014-10-20
- */
- : a+ V$ c, R8 l1 }
- `timescale 1ns/1ns
* ^; j* M' a, k& |+ B- 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
- 4 ^9 k) _% u, x$ Z8 T+ s; t- E
- m1 M1();
- m2 M2();
- endmodule // top
$ m% u! a2 t6 ~ g) I, L- module m1;
- import "DPI-C" context function void c_get_m1_scope();
- export "DPI" function m1_add;
- - g/ N1 K! k2 V5 ^4 O% x
- 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
9 G8 W1 a# e; {( k- initial begin
- c_get_m1_scope();
- m1_value = 8'd100;
- end
- endmodule // m1
- , J! l( X; l7 t, u$ \$ `2 _
- 7 [; x; ~1 o8 N
- module m2;
- import "DPI-C" context function void c_get_m2_scope();
- export "DPI-C" task m2_add;
- , Y4 l" S1 H9 d8 D% X3 ]# \
- reg tmp;
- reg [31:0] m2_value;
- task m2_add(input int num,output int sum);
- sum = num + m2_value;
- endtask // m2_add
8 O, G1 U$ ]4 k7 @ _0 N# X- initial begin
- c_get_m2_scope();
- m2_value = 32'd200;
- end
- 4 k. c$ T& R* a
- endmodule // m1
% t% M# F0 N F2 t5 D
3 G1 R+ ^: C# X" l! \) A& _4 `9 y( j, P* c6 c
2,C部分
3 k1 X7 |6 w% T, X& ^+ A R: b8 z' z U) T( j0 m& x8 e
! u6 ?" B* r& g h7 X! M$ G* r7 `- /*
- * test.c Rill create for dpi test at 2014-10-20
- */
6 A7 g3 j/ ^' d% s0 r- #include <stdio.h>
- #include <svdpi.h>
7 I1 N# n% E3 s* o! F- svScope tmp_scope;
- svScope m1_scope;
- svScope m2_scope;
- ( m x4 d' `, g
- //import task/funcs from sv
- extern int m1_add();
- extern int m2_add();
H. K! Y$ t( g5 f. I2 `. t- //==scope switch
- void c_get_tmp_scope(void)
- {
- tmp_scope = svGetScope();
- }
- 3 J0 @' n: P/ f2 s3 O2 V: k+ f' M
- void c_set_tmp_scope(void)
- {
- svSetScope(tmp_scope);
- }
+ C+ i$ P( K( b: b- void c_get_m1_scope(void)
- {
- m1_scope = svGetScope();
- }
- % o3 s8 X0 O D {0 e( n$ r
- void c_set_m1_scope(void)
- {
- svSetScope(m1_scope);
- }
- 4 \$ r* |" S: U' l9 i0 L
- void c_get_m2_scope(void)
- {
- m2_scope = svGetScope();
- }
- 1 k. M: y) S$ u% w& x
- void c_set_m2_scope(void)
- {
- svSetScope(m2_scope);
- }
2 Z$ I5 Q0 `) [+ A- //==export c funcs to sv
- int c_func(int num)
- {
- int m1 = 0;
- int m2 = 0;
, S& A/ s8 J5 `* a" E) a- c_get_tmp_scope();
- c_set_m1_scope();
- m1 = m1_add(num);
- c_set_tmp_scope();
- printf("m1:%d\n",m1);
# I( _% C7 E9 d8 t9 d- c_get_tmp_scope();
- c_set_m2_scope();
- m2_add(num,&m2);
- c_set_tmp_scope();
- printf("m2:%d\n",m2);
, J! _. u! k: D& t J6 J1 J- return 0;
- }
3 [+ o( v9 \ Y- |- B$ N: u' v: K 2 c: b" e& P$ x' _7 ? a6 I# R
3 ~# r3 X- q9 y7 h1 A8 F9 [6 n) A" J
3,脚本) _8 l7 z0 _6 D, H
% b4 t8 @1 T: [2 t* N$ i' G
$ _' @: s3 r! Y5 i9 P4 L# d- #! /bin/bash
! A* A6 ~. f8 s K* Q4 k' D- #
- # test.sh
- # usage: ./test.sh c/w/r
- # Rill create 2014-10-20
- #
8 m( ?% I- f8 A
. v8 S* `* \) o5 B5 }- TOP_MODULE=tb
- C9 L' ?$ r. q' g- tcl_file=run.tcl
- : L2 W: \2 T0 A' v! V! I
- CDS_INST_DIR=/home/openrisc/opt/edatools/IUS08.20
- ' [5 ^) F# s% e& ]
% W+ t' \8 N5 b' c+ ?) G F; @- if [ $# != 1 ];then
- echo "args must be c/w/r"
- exit 0
- fi
- 2 Q- Y# h% G; J; ^
- 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}
; S' e v$ {% h/ N$ S X5 T, S- echo "compile dpi lib"
- if [ -e libdpi.so ];then
- rm libdpi.so -f
- fi
- - ^$ Z6 E% O1 h. L1 L! u7 q
- gcc -fPIC -shared -o libdpi.so test.c -I$CDS_INST_DIR/tools/inca/include
- exit 0
- fi
- / A4 ~4 C8 s* ?1 w
- & ^2 c }, J9 I
- if [ -e ${tcl_file} ];then
- rm ${tcl_file} -f
- fi
- touch ${tcl_file}
) f" q; h; j9 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
- # d; z6 x4 A5 T4 `1 `; z$ T
- if [ $1 == "w" -o $1 == "r" ];then
- echo "sim start..."
- ncsim ${TOP_MODULE} -input ${tcl_file}
- fi
- " X' K% D6 D2 u
- echo "$(date) sim done!"7 V, L7 @- j2 P
M5 o, j/ s# u
3 T( K' Z3 l( Z. N1 }0 S! U
4,说明6 Y/ F; A8 j9 \+ R
仔细体会我们上面构造的例子,有几个问题需要弄清楚。+ \6 q ^( Y2 j8 O
4 h6 u+ C; e" x" j7 ~a,scope的含义:
. h! v M% |3 \
) ]- J4 R' _7 U c* w9 m在SV端,m1是不能直接调用m2中的task/function的,所以m1里面调用的C函数也不能直接调用m2中export出来的task/function,如果想调用,必须进行scope切换。
k5 R8 X5 \" |. P/ F, O
( H, t' {1 _( u/ n* Sb,SV端,有task和function的区分,但是在C端,并没有区分,一律是C函数。" A3 }; S$ Z8 {+ }/ g9 @" f6 u
$ n5 l9 y7 V% z1 U& g
- n$ o$ u7 ^% K* h( l
5,关于用C模拟硬件的并行行为
% [8 I9 q3 m0 i5 F9 J. ]; n* s( n
方式a,将流水后面的模块写在前面。
( F# Y* D2 ?" m
" n7 ?2 d2 Y+ Q D方式b,将所有并行的信号写成如下形式:
# S* e. P3 l! Y/ q$ [7 g, E2 x3 h, D; _' k( m& w
用c,n两个变量模拟reg的值。
2 K2 F$ u; C; k# i; F# B6 T$ N4 t
用init和update两个函数模拟reg的行为。- s% C0 ?9 C( O9 ]# Z
1 H, j% D" x) V, i7 Y1 }. [$ t9 q
- /*
- * parallel.c Rill create for simulater test at 2014-10-20
- */
4 C9 d1 d: U) G+ y i A ?# R
( g3 p/ o4 @7 k: D- struct signal;
- , s) V: I6 X8 x$ f( R
- struct sig_ops
- {
- int (*init) (struct signal*);
- int (*update) (struct signal*);
- };
: w3 d) k+ H5 c& @$ A" b. w( L- struct signal
- {
- unsigned int c; //current cycle value
- unsigned int n; //next cycle value
- char name[32];
- struct sig_ops* ops;
- };
- 1 d" R7 n! K. i' x
- /* veritual functions
- int sig_init(struct signal* signal)
- {
- return signal->ops->init(signal);
- }
- f$ i2 I8 Z: e+ y- _- int sig_update(struct signal* signal)
- {
- return signal->ops->update(signal);
- }
- */
- , K6 |2 {' o! y( ?% d& ], P
- //actual functions
- int test_init(struct signal* signal)
- {
- signal->c = 0;
- signal->n = 0;
- return 0;
- }
- , j$ _% ]5 y3 o! c& ]6 t
- int test_update(struct signal* signal)
- {
- signal->c = signal->n;
- return 0;
- }
2 k( G+ J/ X% v: v4 s- 1 P( ~1 ^& `! g" O8 q7 f1 C; K
3 Y! G S6 t: D$ ?+ S, j9 }- int signal_create(struct signal* signal,char * name)
- {
- signal->name = name;
- }
7 \( Z: b& S; t; n2 }# X/ _- //============main.c====================//
- //example signal
- struct signal test;
- struct sig_ops test_ops =
- {
- test_init,
- test_update,
- };
- ; M8 g- V( T6 {* Y( p1 u6 m5 T6 a+ N
- int main()
- {
- signal_create(&test,"test");
- //when reset
- test->ops->init(&test);
- //per cycle
- test->ops->update(&test);
- return 0;
- }
1 n- D E% C( o, j7 `9 t( n 3 w/ e8 F( }8 o
' M) p* S6 o# J
- g. b |7 b$ E
' B5 S/ K+ _/ o9 O
' ~6 j0 G! c0 T' d3 s3 H
3 o9 |; C" l6 B' Q- U. K4 m% s* @. l2 t# R1 b2 ]
& l _" ]. m) I9 G
|
|