(筆記) 如何將參數從Verilog傳到C? (SOC) (Verilog) (Verilog PLI)

Abstract
自行寫一個System Task,能夠接受由Verilog的reg或wire傳給C的值。

Introduction
使用環境 : Cadense NC-Verilog 5.4 + Visual C++ 6.0

在此文件,將學習到
1.如何將參數從Verilog傳到C?
2.如何撰寫簡單的compiletf?
3.如何從C抓到Verilog傳來的參數?

show_value.c / C

1 #include <stdlib.h>
2 #include "vpi_user.h"
3 
4 PLI_INT32 show_value_compiletf(PLI_BYTE8 *user_data) {
5   vpiHandle systf_handle, arg_iterator, arg_handle;
6   PLI_INT32 arg_type;
7  
8   // obtain a handle to the system task instance
9   systf_handle = vpi_handle(vpiSysTfCall, NULL);
10   if (systf_handle == NULL) {
11     vpi_printf("ERROR: $show_value failed to obtain systf handle\n");
12     vpi_control(vpiFinish, 0);
13    
14     return -1;
15   }
16  
17   // obtain handles to system task arguments
18   arg_iterator = vpi_iterate(vpiArgument, systf_handle);
19   if (arg_iterator == NULL) {
20     vpi_printf("ERROR: $show_value requires 1 argument\n");
21     vpi_control(vpiFinish, 0);
22    
23     return -1;
24   }
25  
26   // check the type of object in system task arguments
27   arg_handle = vpi_scan(arg_iterator);
28   arg_type   = vpi_get(vpiType, arg_handle);
29   if (arg_type != vpiNet && arg_type != vpiReg) {
30     vpi_printf("ERROR: $show_value arg must be a net or a reg\n");
31     vpi_free_object(arg_iterator);
32     vpi_control(vpiFinish, 0);
33    
34     return -1;
35   }
36  
37   // check only 1 system task argument
38   arg_handle = vpi_scan(arg_iterator);
39   if (arg_handle != NULL) {
40     vpi_printf("ERROR: $show_value can only have 1 argument\n");
41     vpi_free_object(arg_iterator);
42     vpi_control(vpiFinish, 0);
43    
44     return -1;
45   }
46  
47   return 0
48 }
49 
50 PLI_INT32 show_value_calltf(PLI_BYTE8 *user_data) {
51   vpiHandle systf_handle, arg_iterator, arg_handle, net_handle;
52   s_vpi_value current_value;
53  
54   // obtain a handle to the system task instance
55   systf_handle = vpi_handle(vpiSysTfCall, NULL);
56  
57   // obtain hadle to system task argument
58   // compiletf has already verified only 1 arg with corret type
59   arg_iterator = vpi_iterate(vpiArgument, systf_handle);
60   net_handle = vpi_scan(arg_iterator);
61   vpi_free_object(arg_iterator);
62  
63   // read current value
64   current_value.format = vpiHexStrVal; // read a value as a string
65   vpi_get_value(net_handle, &current_value);
66   vpi_printf("Signal %s ", vpi_get_str(vpiFullName, net_handle));
67   vpi_printf("has the value %s\n", current_value.value.str);
68  
69   return 0;
70 }
71 
72 void show_value_register() {
73   s_vpi_systf_data tf_data;
74  
75   tf_data.type = vpiSysTask;
76   tf_data.tfname = "$show_value";
77   tf_data.calltf = show_value_calltf;
78   tf_data.compiletf = show_value_compiletf;
79  
80   vpi_register_systf(&tf_data);
81 }


Step 1:
撰寫compiletf,判斷由Verilog傳給C的參數是否合法

第5行

vpiHandle systf_handle, arg_iterator, arg_handle;


vpiHandle是VPI自訂的型態,為pointer to Verilog object。systf_handle為pointer to system task,arg_iterator為pointer to argument iterator,arg_handle為pointer to argument。

第8行

// obtain a handle to the system task instance
systf_handle = vpi_handle(vpiSysTfCall, NULL);
if (systf_handle == NULL) {
  vpi_printf(
"ERROR: $show_value failed to obtain systf handle\n");
  vpi_control(vpiFinish,
0);
   
 
return -1;
}


由vpi_handle()取得system task的handle,若為NULL,則顯示錯誤訊息並且結束模擬。

17行

// obtain handles to system task arguments
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
if (arg_iterator == NULL) {
  vpi_printf(
"ERROR: $show_value requires 1 argument\n");
  vpi_control(vpiFinish,
0);
   
 
return -1;
}


由vpi_itrator()獲得argument iterator,為參數的集合,若為NULL,則顯示錯誤訊息並且結束模擬。

26行

// check the type of object in system task arguments
arg_handle = vpi_scan(arg_iterator);
arg_type  
= vpi_get(vpiType, arg_handle);
if (arg_type != vpiNet && arg_type != vpiReg) {
  vpi_printf(
"ERROR: $show_value arg must be a net or a reg\n");
  vpi_free_object(arg_iterator);
  vpi_control(vpiFinish,
0);
   
 
return -1;
}


檢查參數是否為reg或者wire型態,由vpi_scan()從argument iterator萃取出argument handle,再由vpi_get()獲得參數的型別做判斷,若不是wire或reg,則顯示錯誤訊息並結束模擬。

37行

// check only 1 system task argument
arg_handle = vpi_scan(arg_iterator);
if (arg_handle != NULL) {
  vpi_printf(
"ERROR: $show_value can only have 1 argument\n");
  vpi_free_object(arg_iterator);
  vpi_control(vpiFinish);
   
 
return -1;
}


由於$show_value()只允許Verilog傳入一個參數,在此判斷user是否只傳入一個參數,若由vpi_scan()抓取argument iterator還能抓到值,表示不只一個參數,則顯示錯誤訊息並結束模擬。

Step 2
撰寫calltf,讀取Verilog傳給C的參數。

由於compiletf已經驗證了參數的正確性,calltf可大膽的假設參數都已經正確。

52行

s_vpi_value current_value;


C所抓到的Verilog參數值,為一個struct。

54行

// obtain a handle to the system task instance
systf_handle = vpi_handle(vpiSysTfCall, NULL);
 
// obtain hadle to system task argument
// compiletf has already verified only 1 arg with corret type
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
net_handle
= vpi_scan(arg_iterator);
vpi_free_object(arg_iterator);
 
// read current value
current_value.format = vpiHexStrVal; // read a value as a string
vpi_get_value(net_handle, &current_value);


systf_handle -> arg_iterator -> net_handle -> current_value

66行

vpi_printf("Signal %s ", vpi_get_str(vpiFullName, net_handle));
vpi_printf(
"has the value %s\n", current_value.value.str);


顯示參數值,vpi_get_str()顯示reg或wire的完整hierarchy架構名稱,並以16進位字串顯示。

Step 3:
建立C function與Verilog system task的連結資料。

void show_value_register() {
  s_vpi_systf_data tf_data;
 
  tf_data.type
= vpiSysTask;
  tf_data.tfname
= "$show_value";
  tf_data.calltf
= show_value_calltf;
  tf_data.compiletf
= show_value_compiletf;
 
  vpi_register_systf(
&tf_data);
}


與Hello World的差別是,多指定了compiletf部分。

Step 4:
一個簡單的Verilog counter

counter.v / Verilog

1 `timescale 1ns/1ns
2 
3 module Counter (
4   input iCLK,
5   input iRST_N,
6   output reg [7:0] oCnt
7 );
8 
9 reg [7:0] cnt;
10 
11 always@(posedge iCLK, negedge iRST_N) begin
12   if (!iRST_N)
13     oCnt <= 8'h00;
14   else
15     oCnt = oCnt + 1'b1;
16 end
17 
18 endmodule


Step 5:
Testbench中使用$show_value

counter_tb.v / Verilog

1 `timescale 1ns/1ns
2 
3 module Counter_tb;
4 
5 reg clk;
6 reg rst_n;
7 wire [7:0] cnt;
8 
9 initial begin
10   clk   = 0;
11   rst_n = 0;
12  
13   #1
14   rst_n = 1;
15  
16   #10 
17   $show_value(cnt);
18   $display("$display for cnt = %h", cnt);
19  
20   #10 
21   $show_value(cnt);
22   $display("$display for cnt = %h", cnt);
23  
24   #10 $finish;
25 end
26 
27 always #5 clk = ~clk;
28 
29 Counter counter (
30   .iCLK(clk),
31   .iRST_N(rst_n),
32   .oCnt(cnt)
33 );
34 
35 endmodule


Step 6:
使用NC-Verilog模擬

ncverilog  +access+r  Counter.v  Counter_tb.v


ncverilog: 05.40-s011: (c) Copyright 1995-2005 Cadence Design Systems, Inc.
TOOL:    ncverilog   
05.40-s011: Started on Mar 25, 2009 at 16:53:38 台北標準時間
ncverilog
    +access+r
    Counter.v
    Counter_tb.v
Recompiling reason: file '.\Counter_tb.v' is newer than expected.
    expected: Wed Mar
25 16:53:17 2009
    actual:   Wed Mar
25 16:53:34 2009
file: Counter.v
file: Counter_tb.v
    module worklib.Counter_tb:v
        errors:
0, warnings: 0
        Caching library 'worklib' . Done
    Elaborating the design hierarchy:
    Building instance overlay tables: .. Done
    Generating native compiled code:
        worklib.Counter_tb:v <0x24a5152d>
            streams:  
2, words:  1787
    Loading native compiled code:     .. Done
    Building instance specific data structures.
    Design hierarchy summary:
                         Instances  Unique
        Modules:                
2       2
        Registers:              
4       4
        Scalar wires:           
2       -
        Vectored wires:         
1       -
        Always blocks:          
2       2
        Initial blocks:         
1       1
        Simulation timescale:  1ns
    Writing initial simulation snapshot: worklib.Counter_tb:v
Loading snapshot worklib.Counter_tb:v .. Done
ncsim> source
"C:/Program Files/Cadence Design Systems/IUS/tools/inca/files/ncsimrc"
ncsim> run
Signal Counter_tb.cnt has the value
01
$display for cnt
= 01
Signal Counter_tb.cnt has the value
02
$display for cnt
= 02
Simulation complete via $finish(
1) at time 31 NS + 0
.\Counter_tb.v:
24   #10 $finish;
ncsim> exit
TOOL:    ncverilog   
05.40-s011: Exiting on Mar 25, 2009 at 16:53:41 台北標準時間  (total: 00:00:03)


完整程式碼下載
pli_show_value.7z

Reference
The Verilog PLI Handbook Ch.1

posted on 2009-03-30 21:41 真 OO无双 阅读(...) 评论(...) 编辑 收藏

导航

统计