blob: 7f46b1e46863ccd96927b2a32ba4cab9e94f77bd [file] [log] [blame]
//----------------------------------------------------------------------
// 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 "uvm_dpi.h"
#include <math.h>
#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=<value>";
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<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);
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;
r = vpi_handle_by_name(path, 0);
if(r == 0)
return 0;
else
return 1;
}
/*
* convert binary to integer
*/
long int uvm_hdl_btoi(char *binVal) {
long int remainder, dec=0, j = 0;
unsigned long long int bin;
int i;
char tmp[2];
tmp[1] = '\0';
for(i= strlen(binVal) -1 ; 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 VCSMX
int 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 VCSMX
int 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
}