UVM中有需要从cmmand line 输入参数的需求,所有uvm_svcmd_dpi.svh和uvm_svcmd_dpi.cc 文件就是实现功能。
uvm_svcmd_dpi.svh的源代码如下,我们可以看SV采用import的方式导入C代码函数,所有者写函数的实现在uvm_svcmd_dpi.cc 中。当定义了UVM_CMDLINE_NO_DPI的宏时,所有函数返回值要么是NULL,要么是“?”。
// Import DPI functions used by the interface to generate the // lists. `ifndef UVM_CMDLINE_NO_DPI import "DPI-C" function string uvm_dpi_get_next_arg_c (int init); import "DPI-C" function string uvm_dpi_get_tool_name_c (); import "DPI-C" function string uvm_dpi_get_tool_version_c (); function string uvm_dpi_get_next_arg(int init=0); return uvm_dpi_get_next_arg_c(init); endfunction function string uvm_dpi_get_tool_name(); return uvm_dpi_get_tool_name_c(); endfunction function string uvm_dpi_get_tool_version(); return uvm_dpi_get_tool_version_c(); endfunction import "DPI-C" function chandle uvm_dpi_regcomp(string regex); import "DPI-C" function int uvm_dpi_regexec(chandle preg, string str); import "DPI-C" function void uvm_dpi_regfree(chandle preg); `else function string uvm_dpi_get_next_arg(int init=0); return ""; endfunction function string uvm_dpi_get_tool_name(); return "?"; endfunction function string uvm_dpi_get_tool_version(); return "?"; endfunction function chandle uvm_dpi_regcomp(string regex); return null; endfunction function int uvm_dpi_regexec(chandle preg, string str); return 0; endfunction function void uvm_dpi_regfree(chandle preg); endfunction `endif
看完了uvm_svcmd_dpi.svh的源代码,让我们再看看uvm_svcmd_dpi.cc的源代码,这里面的函数是采用vpi方式实现的。
#include "uvm_dpi.h" #include <assert.h> #define ARGV_STACK_PTR_SIZE 32 // the total number of arguments (minus the -f/-F minus associated filenames) int argc_total; // the ptr to the array of ptrs to the args char** argv_stack=NULL; char ** argv_ptr=NULL; void push_data(int lvl,char *entry, int cmd) { if(cmd==0) argc_total++; else *argv_ptr++=entry; } // walk one level (potentially recursive) void walk_level(int lvl, int argc, char**argv,int cmd) { int idx; for(idx=0; ((lvl==0) && idx<argc) || ((lvl>0) && (*argv));idx++,argv++) { if(strcmp(*argv, "-f") && strcmp(*argv, "-F")) { push_data(lvl,*argv,cmd); } else { argv++; idx++; char **n=(char**) *argv; walk_level(lvl+1,argc,++n,cmd); } } } const char *uvm_dpi_get_next_arg_c (int init) { s_vpi_vlog_info info; static int idx=0; if(init==1) { // free if necessary free(argv_stack); argc_total=0; vpi_get_vlog_info(&info); walk_level(0,info.argc,info.argv,0); argv_stack = (char**) malloc (sizeof(char*)*argc_total); argv_ptr=argv_stack; walk_level(0,info.argc,info.argv,1); idx=0; argv_ptr=argv_stack; } if(idx++>=argc_total) return NULL; return *argv_ptr++; } extern char* uvm_dpi_get_tool_name_c () { s_vpi_vlog_info info; vpi_get_vlog_info(&info); return info.product; } extern char* uvm_dpi_get_tool_version_c () { s_vpi_vlog_info info; vpi_get_vlog_info(&info); return info.version; } extern regex_t* uvm_dpi_regcomp (char* pattern) { regex_t* re = (regex_t*) malloc (sizeof(regex_t)); int status = regcomp(re, pattern, REG_NOSUB|REG_EXTENDED); if(status) { const char * err_str = "uvm_dpi_regcomp : Unable to compile regex: |%s|, Element 0 is: %c"; char buffer[strlen(err_str) + strlen(pattern) + 1]; sprintf(buffer, err_str, pattern, pattern[0]); m_uvm_report_dpi(M_UVM_ERROR, (char*)"UVM/DPI/REGCOMP", &buffer[0], M_UVM_NONE, (char*) __FILE__, __LINE__); regfree(re); free (re); return NULL; } return re; } extern int uvm_dpi_regexec (regex_t* re, char* str) { if(!re ) { return 1; } return regexec(re, str, (size_t)0, NULL, 0); } extern void uvm_dpi_regfree (regex_t* re) { if(!re) return; regfree(re); free (re); }