| //---------------------------------------------------------------------- |
| // Copyright 2007-2011 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. |
| //---------------------------------------------------------------------- |
| |
| #include "vpi_user.h" |
| #include "veriuser.h" |
| #include "svdpi.h" |
| #include <malloc.h> |
| #include <string.h> |
| #include <stdio.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 QUESTA |
| static 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) |
| { |
| vpi_printf((PLI_BYTE8*) "UVM_ERROR: set: unable to locate hdl path (%s)\n",path); |
| vpi_printf((PLI_BYTE8*) " Either the name is incorrect, or you may not have PLI/ACC visibility to that name\n"); |
| 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;i<chunks-1; ++i) { |
| value[i].aval = 0; |
| value[i].bval = 0; |
| } |
| } |
| int result = 0; |
| result = uvm_hdl_get_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) |
| { |
| vpi_printf((PLI_BYTE8*) "UVM_ERROR: get: unable to locate hdl path %s\n", path); |
| vpi_printf((PLI_BYTE8*) " Either the name is incorrect, or you may not have PLI/ACC visibility to that name\n"); |
| // 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) |
| { |
| vpi_printf((PLI_BYTE8*) "UVM_ERROR: uvm_reg : hdl path '%s' is %0d bits,\n",path,size); |
| vpi_printf((PLI_BYTE8*) " but the maximum size is %0d. You can increase the maximum\n",maxsize); |
| vpi_printf((PLI_BYTE8*) " via a compile-time flag: +define+UVM_HDL_MAX_WIDTH=<value>\n"); |
| //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<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); |
| #ifndef VCS |
| vpi_release_handle(r); |
| #endif |
| 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) |
| { |
| vpiHandle r; |
| |
| #ifdef QUESTA |
| 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) |
| return 0; |
| else |
| return 1; |
| } |
| |
| |
| /* |
| * 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) |
| { |
| return uvm_hdl_get_vlog(path, value, vpiNoDelay); |
| } |
| |
| /* |
| * 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) |
| { |
| return uvm_hdl_set_vlog(path, value, vpiNoDelay); |
| } |
| |
| |
| /* |
| * 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) |
| { |
| return uvm_hdl_set_vlog(path, value, vpiForceFlag); |
| } |
| |
| |
| /* |
| * 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) |
| { |
| return uvm_hdl_set_vlog(path, value, vpiReleaseFlag); |
| } |
| |
| /* |
| * 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; |
| p_vpi_vecval valuep = &value; |
| return uvm_hdl_set_vlog(path, valuep, vpiReleaseFlag); |
| } |
| |