URL
https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk
Subversion Repositories uart2bus_testbench
[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [dpi/] [uvm_hdl_inca.c] - Rev 16
Compare with Previous | Blame | View Log
//---------------------------------------------------------------------- // Copyright 2007-2013 Cadence Design Systems, Inc. // Copyright 2009-2010 Mentor Graphics Corporation // Copyright 2010-2011 Synopsys, Inc. // All Rights Reserved Worldwide // // Licensed under the Apache License, Version 2.0 (the // "License"); you may not use this file except in // compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in // writing, software distributed under the License is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See // the License for the specific language governing // permissions and limitations under the License. //---------------------------------------------------------------------- // 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 <malloc.h> #include <string.h> #include <stdio.h> 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 buffer static 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 slice static 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<chunks-1; ++i) { value[i].aval = 0; value[i].bval = 0; } } /* * This C code checks to see if there is PLI handle * with a value set to define the maximum bit width. * * This function should only get called once or twice, * its return value is cached in the caller. * */ static int UVM_HDL_MAX_WIDTH = 0; static int uvm_hdl_max_width() { if(!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); vpi_get_value(ms, &value_s); UVM_HDL_MAX_WIDTH= value_s.value.integer; } return UVM_HDL_MAX_WIDTH; } /* * 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 }; r = vpi_handle_by_name(path, 0); if(r == 0) { m_uvm_error("UVM/DPI/HDL_SET","set: unable to locate hdl path (%s)\n Either the name is incorrect, or you may not have PLI/ACC visibility to that name", path); return 0; } else { if(maxsize == -1) maxsize = uvm_hdl_max_width(); if (flag == vpiReleaseFlag) { // FIXME //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; } } vpi_release_handle(r); return 1; } static vhpiEnumT vhpiEnumTLookup[4] = {vhpi0,vhpi1,vhpiZ,vhpiX}; // idx={b[0],a[0]} static vhpiEnumT vhpi2val(int aval,int bval) { int idx=(((bval<<1) || (aval&1)) && 3); return vhpiEnumTLookup[idx]; } static int uvm_hdl_set_vhdl(char* path, p_vpi_vecval value, PLI_INT32 flag) { static int maxsize = -1; int size, chunks, bit, i, j, aval, bval; vhpiValueT value_s; vhpiHandleT r = vhpi_handle_by_name(path, 0); if(maxsize == -1) maxsize = uvm_hdl_max_width(); if(maxsize == -1) maxsize = 1024; size = vhpi_get(vhpiSizeP, r); if(size > 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=<value>", 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<chunks && bit<size; ++i) { aval = value[i].aval; bval = value[i].bval; for(j=0;j<32 && bit<size; ++j) { value_s.value.enumvs[size-bit-1]= vhpi2val(aval,bval); aval>>=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=<value>", 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<chunks; ++i) { value[i].aval = value_s.value.vector[i].aval; value[i].bval = value_s.value.vector[i].bval; } } //vpi_printf("uvm_hdl_get_vlog(%s,%0x)\n",path,value[0].aval); vpi_release_handle(r); return 1; } static int uvm_hdl_get_vhdl(char* path, p_vpi_vecval value) { static int maxsize = -1; int i, j, size, chunks, bit, aval, bval, rtn; vhpiValueT value_s; vhpiHandleT r = vhpi_handle_by_name(path, 0); if(maxsize == -1) maxsize = uvm_hdl_max_width(); if(maxsize == -1) maxsize = 1024; size = vhpi_get(vhpiSizeP, r); if(size > 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=<value>", 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<chunks && bit<size; ++i) { aval = 0; bval = 0; for(j=0;(j<32) && (bit<size); ++j) { aval<<=1; bval<<=1; switch(value_s.value.enumvs[bit]) { case vhpiU: case vhpiW: case vhpiX: { aval |= 1; bval |= 1; break; } case vhpiZ: { bval |= 1; break; } case vhpi0: case vhpiL: case vhpiDontCare: { break; } case vhpi1: case vhpiH: { aval |= 1; break; } } bit++; } value[i].aval = aval; value[i].bval = bval; free (value_s.value.str); } break; } default: { m_uvm_error("UVM/DPI/VHDL_GET","Failed to get value from hdl path %s (unexpected type: %0d)", path, value_s.format); tf_dofinish(); return 0; } } return 1; } /* * Given a path, look the path name up using the PLI, * but don't set or get. Just check. * * Return 0 if NOT found. * Return 1 if found. */ int uvm_hdl_check_path(char *path) { vhpiHandleT handle; int language; m_uvm_get_object_handle(path,&handle,&language); return (handle!=0); } static void m_uvm_error(const char *id, const char *msg, ...) { va_list argptr; va_start(argptr,msg); vsprintf(m_uvm_temp_print_buffer,msg, argptr); va_end(argptr); m_uvm_report_dpi(M_UVM_ERROR, (char *) id, &m_uvm_temp_print_buffer[0], M_UVM_NONE, (char*) __FILE__, __LINE__); } /* * Given a path, look the path name up using the PLI * or the FLI, and return its 'value'. */ int uvm_hdl_read(char *path, p_vpi_vecval value) { vhpiHandleT handle; int language; if(is_valid_path_slice(path)) { clear_value(value); return uvm_hdl_get_vlog_partsel(path, value, vpiNoDelay); } m_uvm_get_object_handle(path,&handle,&language); switch(language) { case vhpiVerilog: return uvm_hdl_get_vlog(path, value, vpiNoDelay); case vhpiVHDL: return uvm_hdl_get_vhdl(path, value); default:m_uvm_error("UVM/DPI/NOBJ1","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0; } } /* * Given a path, look the path name up using the PLI * or the FLI, and set it to 'value'. */ int uvm_hdl_deposit(char *path, p_vpi_vecval value) { vhpiHandleT handle; int language; if(is_valid_path_slice(path)) return uvm_hdl_set_vlog_partsel(path, value, vpiNoDelay); m_uvm_get_object_handle(path,&handle,&language); switch(language) { case vhpiVerilog: return uvm_hdl_set_vlog(path, value, vpiNoDelay); case vhpiVHDL: return uvm_hdl_set_vhdl(path, value, vhpiDepositPropagate); default:m_uvm_error("UVM/DPI/NOBJ2","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0; } } /* * Given a path, look the path name up using the PLI * or the FLI, and set it to 'value'. */ int uvm_hdl_force(char *path, p_vpi_vecval value) { vhpiHandleT handle; int language; if(is_valid_path_slice(path)) return uvm_hdl_set_vlog_partsel(path, value, vpiForceFlag); m_uvm_get_object_handle(path,&handle,&language); switch(language) { case vhpiVerilog: return uvm_hdl_set_vlog(path, value, vpiForceFlag); case vhpiVHDL: return uvm_hdl_set_vhdl(path, value, vhpiForcePropagate); default:m_uvm_error("UVM/DPI/NOBJ3","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0; } } /* * Given a path, look the path name up using the PLI * or the FLI, and release it. */ int uvm_hdl_release_and_read(char *path, p_vpi_vecval value) { vhpiHandleT handle; int language; if(is_valid_path_slice(path)) { uvm_hdl_set_vlog_partsel(path, value, vpiReleaseFlag); clear_value(value); return uvm_hdl_get_vlog_partsel(path, value, vpiNoDelay); } m_uvm_get_object_handle(path,&handle,&language); switch(language) { case vhpiVerilog: uvm_hdl_set_vlog(path, value, vpiReleaseFlag); return uvm_hdl_get_vlog(path, value, vpiNoDelay); case vhpiVHDL: uvm_hdl_set_vhdl(path, value, vhpiReleaseKV); return uvm_hdl_get_vhdl(path, value); default:m_uvm_error("UVM/DPI/NOBJ4","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0; } } /* * Given a path, look the path name up using the PLI * or the FLI, and release it. */ int uvm_hdl_release(char *path) { s_vpi_vecval value; vhpiHandleT handle; int language; if(is_valid_path_slice(path)) return uvm_hdl_set_vlog_partsel(path, &value, vpiReleaseFlag); m_uvm_get_object_handle(path,&handle,&language); switch(language) { case vhpiVerilog: return uvm_hdl_set_vlog(path, &value, vpiReleaseFlag); case vhpiVHDL: return uvm_hdl_set_vhdl(path, &value, vhpiReleaseKV); default:m_uvm_error("UVM/DPI/NOBJ5","name %s cannot be resolved to a hdl object (vlog,vhdl,vlog-slice)",path); return 0; } }