我们可以在uvm中实现HDL的后门访问,具体包括的function有uvm_hdl_check_path,uvm_hdl_deposit, uvm_hdl_force,uvm_hdl_release,uvm_hdl_read, task 有uvm_hdl_force_time。 这么做与直接用SV中force, release 有什么区别,有什么好处?这么做的话函数的输入是字符串而不是HDL(hardware description language, 硬件描述语言 )的层次结构。有了字符串就可以模块化了(函数),首先来看uvm_hdl.svh的源代码,当定义了UVM_HDL_NO_DPI,而用户由调用了HDL DPI相关的函数,这时会报错。
// TITLE: UVM HDL Backdoor Access support routines.//// These routines provide an interface to the DPI/PLI// implementation of backdoor access used by registers.//// If you DON'T want to use the DPI HDL API, then compile your// SystemVerilog code with the vlog switch//: vlog ... +define+UVM_HDL_NO_DPI ...//`ifndef UVM_HDL__SVH`define UVM_HDL__SVH`ifndef UVM_HDL_MAX_WIDTH`define UVM_HDL_MAX_WIDTH 1024`endif/* * VARIABLE: UVM_HDL_MAX_WIDTH * Sets the maximum size bit vector for backdoor access. * This parameter will be looked up by the * DPI-C code using: * vpi_handle_by_name( * "uvm_pkg::UVM_HDL_MAX_WIDTH", 0); */parameter int UVM_HDL_MAX_WIDTH = `UVM_HDL_MAX_WIDTH;typedef logic [UVM_HDL_MAX_WIDTH-1:0] uvm_hdl_data_t; `ifndef UVM_HDL_NO_DPI // Function: uvm_hdl_check_path // // Checks that the given HDL ~path~ exists. Returns 0 if NOT found, 1 otherwise. // import "DPI-C" context function int uvm_hdl_check_path(string path); // Function: uvm_hdl_deposit // // Sets the given HDL ~path~ to the specified ~value~. // Returns 1 if the call succeeded, 0 otherwise. // import "DPI-C" context function int uvm_hdl_deposit(string path, uvm_hdl_data_t value); // Function: uvm_hdl_force // // Forces the ~value~ on the given ~path~. Returns 1 if the call succeeded, 0 otherwise. // import "DPI-C" context function int uvm_hdl_force(string path, uvm_hdl_data_t value); // Function: uvm_hdl_force_time // // Forces the ~value~ on the given ~path~ for the specified amount of ~force_time~. // If ~force_time~ is 0,is called. // Returns 1 if the call succeeded, 0 otherwise. // task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time = 0); if (force_time == 0) begin void'(uvm_hdl_deposit(path, value)); return; end if (!uvm_hdl_force(path, value)) return; #force_time; void'(uvm_hdl_release_and_read(path, value)); endtask // Function: uvm_hdl_release_and_read // // Releases a value previously set with . // Returns 1 if the call succeeded, 0 otherwise. ~value~ is set to // the HDL value after the release. For 'reg', the value will still be // the forced value until it has been procedurally reassigned. For 'wire', // the value will change immediately to the resolved value of its // continuous drivers, if any. If none, its value remains as forced until // the next direct assignment. // import "DPI-C" context function int uvm_hdl_release_and_read(string path, inout uvm_hdl_data_t value); // Function: uvm_hdl_release // // Releases a value previously set with . // Returns 1 if the call succeeded, 0 otherwise. // import "DPI-C" context function int uvm_hdl_release(string path); // Function: uvm_hdl_read() // // Gets the value at the given ~path~. // Returns 1 if the call succeeded, 0 otherwise. // import "DPI-C" context function int uvm_hdl_read(string path, output uvm_hdl_data_t value);`else function int uvm_hdl_check_path(string path); uvm_report_fatal("UVM_HDL_CHECK_PATH", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function int uvm_hdl_deposit(string path, uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_DEPOSIT", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function int uvm_hdl_force(string path, uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_FORCE", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction task uvm_hdl_force_time(string path, uvm_hdl_data_t value, time force_time=0); uvm_report_fatal("UVM_HDL_FORCE_TIME", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); endtask function int uvm_hdl_release(string path, output uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_RELEASE", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction function int uvm_hdl_read(string path, output uvm_hdl_data_t value); uvm_report_fatal("UVM_HDL_READ", $sformatf("uvm_hdl DPI routines are compiled off. Recompile without +define+UVM_HDL_NO_DPI")); return 0; endfunction`endif`endif
与之对应的uvm_hdl.c实现如下,由于每个EDA vendor 具体实现方式不同,所有分别包含在不同的文件中了。
// hdl vendor backends are defined for VCS,QUESTA,INCA#if defined(VCS) || defined(VCSMX)#include "uvm_hdl_vcs.c"#else#ifdef QUESTA#include "uvm_hdl_questa.c"#else#if defined(INCA) || defined(NCSC)#include "uvm_hdl_inca.c"#else#error "hdl vendor backend is missing"#endif#endif#endif
首先来看Synopsy家的uvm_hdl_vcs.c:
#include "uvm_dpi.h"#include#include "svdpi.h"#include "vcsuser.h"#ifdef VCSMX#include "mhpi_user.h"#include "vhpi_user.h"#endif/* * UVM HDL access C code. * *//* * This C code checks to see if there is PLI handle * with a value set to define the maximum bit width. * * If no such variable is found, then the default * width of 1024 is used. * * This function should only get called once or twice, * its return value is cached in the caller. * */static int uvm_hdl_max_width(){ vpiHandle ms; s_vpi_value value_s = { vpiIntVal, { 0 } }; ms = vpi_handle_by_name((PLI_BYTE8*) "uvm_pkg::UVM_HDL_MAX_WIDTH", 0); if(ms == 0) return 1024; /* If nothing else is defined, this is the DEFAULT */ vpi_get_value(ms, &value_s); return value_s.value.integer;}/* * Given a path, look the path name up using the PLI, * and set it to 'value'. */static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag){ static int maxsize = -1; vpiHandle r; s_vpi_value value_s = { vpiIntVal, { 0 } }; s_vpi_time time_s = { vpiSimTime, 0, 0, 0.0 }; //vpi_printf("uvm_hdl_set_vlog(%s,%0x)\n",path,value[0].aval); r = vpi_handle_by_name(path, 0); if(r == 0) { const char * err_str = "set: unable to locate hdl path (%s)\n Either the name is incorrect, or you may not have PLI/ACC visibility to that name"; char buffer[strlen(err_str) + strlen(path)]; sprintf(buffer, err_str, path); m_uvm_report_dpi(M_UVM_ERROR, (char*) "UVM/DPI/HDL_SET", &buffer[0], M_UVM_NONE, (char*)__FILE__, __LINE__); return 0; } else { if(maxsize == -1) maxsize = uvm_hdl_max_width(); if (flag == vpiReleaseFlag) { //size = vpi_get(vpiSize, r); //value_p = (p_vpi_vecval)(malloc(((size-1)/32+1)*8*sizeof(s_vpi_vecval))); //value = &value_p; } value_s.format = vpiVectorVal; value_s.value.vector = value; vpi_put_value(r, &value_s, &time_s, flag); //if (value_p != NULL) // free(value_p); if (value == NULL) { value = value_s.value.vector; } } return 1;}/* * Given a path, look the path name up using the PLI * and return its 'value'. */static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag){ static int maxsize = -1; int i, size, chunks; vpiHandle r; s_vpi_value value_s; r = vpi_handle_by_name(path, 0); if(r == 0) { const char * err_str = "get: unable to locate hdl path (%s)\n Either the name is incorrect, or you may not have PLI/ACC visibility to that name"; char buffer[strlen(err_str) + strlen(path)]; sprintf(buffer, err_str, path); m_uvm_report_dpi(M_UVM_ERROR, (char*)"UVM/DPI/HDL_GET", &buffer[0], M_UVM_NONE, (char*)__FILE__, __LINE__); // Exiting is too harsh. Just return instead. // tf_dofinish(); return 0; } else { if(maxsize == -1) maxsize = uvm_hdl_max_width(); size = vpi_get(vpiSize, r); if(size > maxsize) { const char * err_str = "uvm_reg : hdl path '%s' is %0d bits, but the maximum size is %0d. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH= "; char buffer[strlen(err_str) + strlen(path) + (2*int_str_max(10))]; sprintf(buffer, err_str, path, size, maxsize); m_uvm_report_dpi(M_UVM_ERROR, (char*)"UVM/DPI/HDL_SET", &buffer[0], M_UVM_NONE, (char*)__FILE__, __LINE__); return 0; } chunks = (size-1)/32 + 1; value_s.format = vpiVectorVal; vpi_get_value(r, &value_s); /*dpi and vpi are reversed*/ for(i=0;i = 0 ; i--) { tmp[0] = binVal[i]; bin = atoi(tmp); dec = dec+(bin*(pow(2,j))); j++; } return(dec);}/* *decimal to hex conversion */char *uvm_hdl_dtob(long int decimalNumber) { int remainder, quotient; int i=0,j, length; int binN[65]; static char binaryNumber[65]; char *str = (char*) malloc(sizeof(char)); quotient = decimalNumber; do { binN[i++] = quotient%2; quotient = quotient/2; } while (quotient!=0); length = i; for (i=length-1, j = 0; i>=0; i--) { binaryNumber[j++] = binN[i]?'1':'0'; } binaryNumber[j] = '\0'; return(binaryNumber);}/* * Mixed lanaguage API Get calls */#ifdef VCSMXint uvm_hdl_get_mhdl(char *path, p_vpi_vecval value) { long int value_int; char *binVal; int i = 0; vhpiValueT value1; p_vpi_vecval vecval; mhpi_initialize('/'); mhpiHandleT mhpiH = mhpi_handle_by_name(path, 0); vhpiHandleT vhpiH = (long unsigned int *)mhpi_get_vhpi_handle(mhpiH); value1.format=vhpiStrVal; value1.bufSize = vhpi_get(vhpiSizeP, vhpiH); value1.value.str = (char*)malloc(value1.bufSize*sizeof(char)+1); if (vhpi_get_value(vhpiH, &value1) == 0) { binVal = value1.value.str; value_int = uvm_hdl_btoi(binVal); value->aval = (PLI_UINT32) value_int; value->bval = 0; mhpi_release_parent_handle(mhpiH); free(value1.value.str); return(1); } else { mhpi_release_parent_handle(mhpiH); free(value1.value.str); return (0); }}#endif/* * Given a path, look the path name up using the PLI * or the VHPI, and return its 'value'. */int uvm_hdl_read(char *path, p_vpi_vecval value){#ifndef VCSMX return uvm_hdl_get_vlog(path, value, vpiNoDelay);#else mhpi_initialize('/'); mhpiHandleT h = mhpi_handle_by_name(path, 0); if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) { mhpi_release_parent_handle(h); return uvm_hdl_get_vlog(path, value, vpiNoDelay); } else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) { mhpi_release_parent_handle(h); return uvm_hdl_get_mhdl(path,value); }#endif}/* * Mixed Language API Set calls */#ifdef VCSMXint uvm_hdl_set_mhdl(char *path, p_vpi_vecval value, mhpiPutValueFlagsT flags) { mhpi_initialize('/'); mhpiRealT forceDelay = 0; mhpiRealT cancelDelay = -1; mhpiReturnT ret; mhpiHandleT h = mhpi_handle_by_name(path, 0); mhpiHandleT mhpi_mhRegion = mhpi_handle(mhpiScope, h); int val = value->aval; char *force_value = uvm_hdl_dtob(val); ret = mhpi_force_value(path, mhpi_mhRegion, force_value, flags, forceDelay, cancelDelay); mhpi_release_parent_handle(h); if (ret == mhpiRetOk) { return(1); } else return(0);}#endif/* * Given a path, look the path name up using the PLI * or the VHPI, and set it to 'value'. */int uvm_hdl_deposit(char *path, p_vpi_vecval value){#ifndef VCSMX return uvm_hdl_set_vlog(path, value, vpiNoDelay);#else mhpi_initialize('/'); mhpiHandleT h = mhpi_handle_by_name(path, 0); if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) { mhpi_release_parent_handle(h); return uvm_hdl_set_vlog(path, value, vpiNoDelay); } else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) { mhpi_release_parent_handle(h); return uvm_hdl_set_mhdl(path, value, mhpiNoDelay); } else return (0);#endif}/* * Given a path, look the path name up using the PLI * or the VHPI, and set it to 'value'. */int uvm_hdl_force(char *path, p_vpi_vecval value){#ifndef VCSMX return uvm_hdl_set_vlog(path, value, vpiForceFlag);#else mhpi_initialize('/'); mhpiHandleT h = mhpi_handle_by_name(path, 0); if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) { mhpi_release_parent_handle(h); return uvm_hdl_set_vlog(path, value, vpiForceFlag); } else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) { mhpi_release_parent_handle(h); return uvm_hdl_set_mhdl(path, value, mhpiForce); } else return (0);#endif}/* * Given a path, look the path name up using the PLI * or the VHPI, and release it. */int uvm_hdl_release_and_read(char *path, p_vpi_vecval value){ return uvm_hdl_set_vlog(path, value, vpiReleaseFlag);}/* * Given a path, look the path name up using the PLI * or the VHPI, and release it. */int uvm_hdl_release(char *path){ s_vpi_vecval value; p_vpi_vecval valuep = &value;#ifndef VCSMX return uvm_hdl_set_vlog(path, valuep, vpiReleaseFlag);#else mhpi_initialize('/'); mhpiHandleT h = mhpi_handle_by_name(path, 0); mhpiReturnT ret; if (mhpi_get(mhpiPliP, h) == mhpiVpiPli) { return uvm_hdl_set_vlog(path, valuep, vpiReleaseFlag); } else if (mhpi_get(mhpiPliP, h) == mhpiVhpiPli) { mhpiHandleT mhpi_mhRegion = mhpi_handle(mhpiScope, h); ret = mhpi_release_force(path, mhpi_mhRegion); if (ret == mhpiRetOk) { return(1); } else return(0); } else return (0);#endif}
再看Cadence家的uvm_hdl_inca.c:
// use -DINCA_EXTENDED_PARTSEL_SUPPORT to use extended support for vpi_handle_by_name#include "vhpi_user.h"#include "vpi_user.h"#include "veriuser.h"#include "svdpi.h"#include#include #include static void m_uvm_error(const char *ID, const char *msg, ...);static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);static void m_uvm_get_object_handle(const char* path, vhpiHandleT *handle,int *language);static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);static int uvm_hdl_max_width();// static print bufferstatic char m_uvm_temp_print_buffer[1024];/* * UVM HDL access C code. * */static void m_uvm_get_object_handle(const char* path, vhpiHandleT *handle,int *language){ *handle = vhpi_handle_by_name(path, 0); if(*handle) *language = vhpi_get(vhpiLanguageP, *handle);}// returns 0 if the name is NOT a slice// returns 1 if the name is a slicestatic int is_valid_path_slice(const char* path) { char *path_ptr = (char *) path; int path_len;#ifdef INCA_EXTENDED_PARTSEL_SUPPORT return 0;#endif path_len = strlen(path); path_ptr = (char*)(path+path_len-1); if (*path_ptr != ']') return 0; while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != ':') return 0; while(path_ptr != path && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != '[') return 0; return 1;}static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag){ char *path_ptr = path; int path_len; svLogicVecVal bit_value; if(!is_valid_path_slice(path)) return 0; path_len = strlen(path); path_ptr = (char*)(path+path_len-1); if (*path_ptr != ']') return 0; while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != ':') return 0; while(path_ptr != path && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != '[') return 0; int lhs, rhs, width, incr; // extract range from path if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) { char index_str[20]; int i; path_ptr++; path_len = (path_len - (path_ptr - path)); incr = (lhs>rhs) ? 1 : -1; width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1; // perform set for each individual bit for (i=0; i < width; i++) { sprintf(index_str,"%u]",rhs); strncpy(path_ptr,index_str,path_len); svGetPartselLogic(&bit_value,value,i,1); rhs += incr; if (uvm_hdl_set_vlog_partsel(path,&bit_value,flag)==0) { if(uvm_hdl_set_vlog(path,&bit_value,flag)==0) { return 0; }; } } return 1; } return 0;}/* * Given a path with part-select, break into individual bit accesses * path = pointer to user string * value = pointer to logic vector * flag = deposit vs force/release options, etc */static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag){ char *path_ptr = path; int path_len; svLogicVecVal bit_value; path_len = strlen(path); path_ptr = (char*)(path+path_len-1); if (*path_ptr != ']') return 0; while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != ':') return 0; while(path_ptr != path && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != '[') return 0; int lhs, rhs, width, incr; // extract range from path if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) { char index_str[20]; int i; path_ptr++; path_len = (path_len - (path_ptr - path)); incr = (lhs>rhs) ? 1 : -1; width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1; bit_value.aval = 0; bit_value.bval = 0; for (i=0; i < width; i++) { svLogic logic_bit; sprintf(index_str,"%u]",rhs); strncpy(path_ptr,index_str,path_len); if(uvm_hdl_get_vlog_partsel(path,&bit_value,flag) == 0) { if(uvm_hdl_get_vlog(path,&bit_value,flag)==0) { return 0; } } logic_bit = svGetBitselLogic(&bit_value,0); svPutPartselLogic(value,bit_value,i,1); rhs += incr; } return 1; } else { return 0; }}static void clear_value(p_vpi_vecval value) { int chunks; int maxsize = uvm_hdl_max_width(); chunks = (maxsize-1)/32 + 1; for(int i=0;i maxsize) { m_uvm_error("UVM/DPI/VHDL_SET","hdl path %s is %0d bits, but the current maximum size is %0d. You may redefine it using the compile-time flag: -define UVM_HDL_MAX_WIDTH= ", path, size,maxsize); tf_dofinish(); } chunks = (size-1)/32 + 1; value_s.format = vhpiObjTypeVal; value_s.bufSize = 0; value_s.value.str = NULL; vhpi_get_value(r, &value_s); switch(value_s.format) { case vhpiEnumVal: { value_s.value.enumv = vhpi2val(value[0].aval,value[0].bval); break; } case vhpiEnumVecVal: { value_s.bufSize = size*sizeof(int); value_s.value.enumvs = (vhpiEnumT *)malloc(size*sizeof(int)); vhpi_get_value(r, &value_s); chunks = (size-1)/32 + 1; bit = 0; for(i=0;i >=1; bval>>=1; bit++; } } break; } default: { m_uvm_error("UVM/DPI/VHDL_SET","Failed to set value to hdl path %s (unexpected type: %0d)", path, value_s.format); tf_dofinish(); return 0; } } vhpi_put_value(r, &value_s, flag); if(value_s.format == vhpiEnumVecVal) { free(value_s.value.enumvs); } return 1;}/* * Given a path, look the path name up using the PLI * and return its 'value'. */static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag){ static int maxsize = -1; int i, size, chunks; vpiHandle r; s_vpi_value value_s; r = vpi_handle_by_name(path, 0); if(r == 0) { m_uvm_error("UVM/DPI/VLOG_GET","unable to locate hdl path (%s)\n Either the name is incorrect, or you may not have PLI/ACC visibility to that name",path); // Exiting is too harsh. Just return instead. // tf_dofinish(); return 0; } else { if(maxsize == -1) maxsize = uvm_hdl_max_width(); size = vpi_get(vpiSize, r); if(size > maxsize) { m_uvm_error("UVM/DPI/VLOG_GET","hdl path '%s' is %0d bits, but the maximum size is %0d. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH= ", path,size,maxsize); //tf_dofinish(); vpi_release_handle(r); return 0; } chunks = (size-1)/32 + 1; value_s.format = vpiVectorVal; vpi_get_value(r, &value_s); /*dpi and vpi are reversed*/ for(i=0;i maxsize) { m_uvm_error("UVM/DPI/HDL_SET","hdl path %s is %0d bits, but the maximum size is %0d, redefine using -define UVM_HDL_MAX_WIDTH= ", path, size,maxsize); tf_dofinish(); } chunks = (size-1)/32 + 1; value_s.format = vhpiObjTypeVal; value_s.bufSize = 0; value_s.value.str = NULL; rtn = vhpi_get_value(r, &value_s); if(vhpi_check_error(0) != 0) { m_uvm_error("UVM/DPI/VHDL_GET","Failed to get value from hdl path %s",path); tf_dofinish(); return 0; } switch (value_s.format) { case vhpiIntVal: { value[0].aval = value_s.value.intg; value[0].bval = 0; break; } case vhpiEnumVal: { switch(value_s.value.enumv) { case vhpiU: case vhpiW: case vhpiX: { value[0].aval = 1; value[0].bval = 1; break; } case vhpiZ: { value[0].aval = 0; value[0].bval = 1; break; } case vhpi0: case vhpiL: case vhpiDontCare: { value[0].aval = 0; value[0].bval = 0; break; } case vhpi1: case vhpiH: { value[0].aval = 1; value[0].bval = 0; break; } } break; } case vhpiEnumVecVal: { value_s.bufSize = size; value_s.value.str = (char*)malloc(size); rtn = vhpi_get_value(r, &value_s); if (rtn > 0) { value_s.value.str = (char*)realloc(value_s.value.str, rtn); value_s.bufSize = rtn; vhpi_get_value(r, &value_s); } for(i=0; i<((maxsize-1)/32+1); ++i) { value[i].aval = 0; value[i].bval = 0; } bit = 0; for(i=0;i
最后,Mentor Graphic的uvm_hdl_questa.c:
#include "uvm_dpi.h"/* * UVM HDL access C code. * *//* * This C code checks to see if there is PLI handle * with a value set to define the maximum bit width. * * If no such variable is found, then the default * width of 1024 is used. * * This function should only get called once or twice, * its return value is cached in the caller. * */static int uvm_hdl_max_width(){ vpiHandle ms; s_vpi_value value_s = { vpiIntVal, { 0 } }; ms = vpi_handle_by_name((PLI_BYTE8*) "uvm_pkg::UVM_HDL_MAX_WIDTH", 0); if(ms == 0) return 1024; /* If nothing else is defined, this is the DEFAULT */ vpi_get_value(ms, &value_s); return value_s.value.integer;}#ifdef QUESTAstatic int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag);static int partsel = 0;/* * Given a path with part-select, break into individual bit accesses * path = pointer to user string * value = pointer to logic vector * flag = deposit vs force/release options, etc */static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag){ char *path_ptr = path; int path_len, idx; svLogicVecVal bit_value; path_len = strlen(path); path_ptr = (char*)(path+path_len-1); if (*path_ptr != ']') return 0; while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != ':') return 0; while(path_ptr != path && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != '[') return 0; int lhs, rhs, width, incr; // extract range from path if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) { char index_str[20]; int i; path_ptr++; path_len = (path_len - (path_ptr - path)); incr = (lhs>rhs) ? 1 : -1; width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1; // perform set for each individual bit for (i=0; i < width; i++) { sprintf(index_str,"%u]",rhs); strncpy(path_ptr,index_str,path_len); svGetPartselLogic(&bit_value,value,i,1); rhs += incr; if (!uvm_hdl_set_vlog(path,&bit_value,flag)) return 0; } return 1; }}/* * Given a path with part-select, break into individual bit accesses * path = pointer to user string * value = pointer to logic vector * flag = deposit vs force/release options, etc */static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag){ char *path_ptr = path; int path_len, idx; svLogicVecVal bit_value; path_len = strlen(path); path_ptr = (char*)(path+path_len-1); if (*path_ptr != ']') return 0; while(path_ptr != path && *path_ptr != ':' && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != ':') return 0; while(path_ptr != path && *path_ptr != '[') path_ptr--; if (path_ptr == path || *path_ptr != '[') return 0; int lhs, rhs, width, incr; // extract range from path if (sscanf(path_ptr,"[%u:%u]",&lhs, &rhs)) { char index_str[20]; int i; path_ptr++; path_len = (path_len - (path_ptr - path)); incr = (lhs>rhs) ? 1 : -1; width = (lhs>rhs) ? lhs-rhs+1 : rhs-lhs+1; bit_value.aval = 0; bit_value.bval = 0; partsel = 1; for (i=0; i < width; i++) { int result; svLogic logic_bit; sprintf(index_str,"%u]",rhs); strncpy(path_ptr,index_str,path_len); result = uvm_hdl_get_vlog(path,&bit_value,flag); logic_bit = svGetBitselLogic(&bit_value,0); svPutPartselLogic(value,bit_value,i,1); rhs += incr; if (!result) return 0; } partsel = 0; return 1; }}#endif/* * Given a path, look the path name up using the PLI, * and set it to 'value'. */static int uvm_hdl_set_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag){ static int maxsize = -1; vpiHandle r; s_vpi_value value_s = { vpiIntVal, { 0 } }; s_vpi_time time_s = { vpiSimTime, 0, 0, 0.0 }; //vpi_printf("uvm_hdl_set_vlog(%s,%0x)\n",path,value[0].aval); #ifdef QUESTA int result = 0; result = uvm_hdl_set_vlog_partsel(path,value,flag); if (result < 0) return 0; if (result == 1) return 1; if (!strncmp(path,"$root.",6)) r = vpi_handle_by_name(path+6, 0); else #endif r = vpi_handle_by_name(path, 0); if(r == 0) { const char * err_str = "set: unable to locate hdl path (%s)\n Either the name is incorrect, or you may not have PLI/ACC visibility to that name"; char buffer[strlen(err_str) + strlen(path)]; sprintf(buffer, err_str, path); m_uvm_report_dpi(M_UVM_ERROR, (char*) "UVM/DPI/HDL_SET", &buffer[0], M_UVM_NONE, (char*)__FILE__, __LINE__); return 0; } else { if(maxsize == -1) maxsize = uvm_hdl_max_width(); if (flag == vpiReleaseFlag) { //size = vpi_get(vpiSize, r); //value_p = (p_vpi_vecval)(malloc(((size-1)/32+1)*8*sizeof(s_vpi_vecval))); //value = &value_p; } value_s.format = vpiVectorVal; value_s.value.vector = value; vpi_put_value(r, &value_s, &time_s, flag); //if (value_p != NULL) // free(value_p); if (value == NULL) { value = value_s.value.vector; } }#ifndef VCS vpi_release_handle(r);#endif return 1;}/* * Given a path, look the path name up using the PLI * and return its 'value'. */static int uvm_hdl_get_vlog(char *path, p_vpi_vecval value, PLI_INT32 flag){ static int maxsize = -1; int i, size, chunks; vpiHandle r; s_vpi_value value_s; #ifdef QUESTA if (!partsel) { maxsize = uvm_hdl_max_width(); chunks = (maxsize-1)/32 + 1; for(i=0;imaxsize) { const char * err_str = "uvm_reg : hdl path '%s' is %0d bits, but the maximum size is %0d. You can increase the maximum via a compile-time flag: +define+UVM_HDL_MAX_WIDTH= "; char buffer[strlen(err_str) + strlen(path) + (2*int_str_max(10))]; sprintf(buffer, err_str, path, size, maxsize); m_uvm_report_dpi(M_UVM_ERROR, (char*)"UVM/DPI/HDL_SET", &buffer[0], M_UVM_NONE, (char*)__FILE__, __LINE__); //tf_dofinish();#ifndef VCS vpi_release_handle(r);#endif return 0; } chunks = (size-1)/32 + 1; value_s.format = vpiVectorVal; vpi_get_value(r, &value_s); /*dpi and vpi are reversed*/ for(i=0;i