非常有用的将参数从verilog传送到c自行寫一個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 / C1#include <stdlib.h>2#include "vpi_user.h"34PLI_INT32 show_value_compiletf(PLI_BYTE8 *user_data) {5 vpiHandle systf_handle, arg_iterator, arg_handle;6 PLI_INT32 arg_type;78// obtain a handle to the system task instance9 systf_handle = vpi_handle(vpiSysTfCall, NULL);10if (systf_handle == NULL) {11 vpi_printf("ERROR: $show_value failed to obtain systf handle\n");12 vpi_control(vpiFinish, 0);1314return -1;15 }1617// obtain handles to system task arguments18 arg_iterator = vpi_iterate(vpiArgument, systf_handle);19if (arg_iterator == NULL) {20 vpi_printf("ERROR: $show_value requires 1 argument\n");21 vpi_control(vpiFinish, 0);2223return -1;24 }2526// check the type of object in system task arguments27 arg_handle = vpi_scan(arg_iterator);28 arg_type = vpi_get(vpiType, arg_handle);29if (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);3334return -1;35 }3637// check only 1 system task argument38 arg_handle = vpi_scan(arg_iterator);39if (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);4344return -1;45 }4647return0;48}50PLI_INT32 show_value_calltf(PLI_BYTE8 *user_data) {51 vpiHandle systf_handle, arg_iterator, arg_handle, net_handle;52 s_vpi_value current_value;5354// obtain a handle to the system task instance55 systf_handle = vpi_handle(vpiSysTfCall, NULL);5657// obtain hadle to system task argument58 // compiletf has already verified only 1 arg with corret type59 arg_iterator = vpi_iterate(vpiArgument, systf_handle);60 net_handle = vpi_scan(arg_iterator);61 vpi_free_object(arg_iterator);6263// read current value64 current_value.format = vpiHexStrVal; // read a value as a string65 vpi_get_value(net_handle, ¤t_value);66 vpi_printf("Signal %s ", vpi_get_str(vpiFullName, net_handle));67 vpi_printf("has the value %s\n", current_value.value.str);6869return0;70}7172void show_value_register() {73 s_vpi_systf_data tf_data;7475 tf_data.type = vpiSysTask;76 tf_data.tfname = "$show_value";77 tf_data.calltf = show_value_calltf;78 tf_piletf = show_value_compiletf;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 instancesystf_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 argumentsarg_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 argumentsarg_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 argumentarg_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 instancesystf_handle = vpi_handle(vpiSysTfCall, NULL);// obtain hadle to system task argument// compiletf has already verified only 1 arg with corret typearg_iterator = vpi_iterate(vpiArgument, systf_handle);net_handle = vpi_scan(arg_iterator);vpi_free_object(arg_iterator);// read current valuecurrent_value.format = vpiHexStrVal; // read a value as a stringvpi_get_value(net_handle, ¤t_value);systf_handle -> arg_iterator -> net_handle -> current_value66行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進位字串顯示。