static void start_of_sim(const vhpiCbDataT *cb_data) { vhpi_printf("start of sim callback! user data is '%s'", (char *)cb_data->user_data); long cycles; vhpiTimeT now; vhpi_get_time(&now, &cycles); fail_unless(now.low == 0); fail_unless(now.high == 0); fail_unless(cycles == 0); vhpiValueT value = { .format = vhpiObjTypeVal }; vhpi_get_value(handle_x, &value); check_error(); fail_unless(value.format == vhpiIntVal); fail_unless(value.value.intg == 0); value.value.intg = 5; vhpi_put_value(handle_x, &value, vhpiForcePropagate); check_error(); vhpiTimeT time_5ns = { .low = 5000000 }; vhpiCbDataT cb_data2 = { .reason = vhpiCbAfterDelay, .cb_rtn = after_5ns, .time = &time_5ns }; vhpi_register_cb(&cb_data2, 0); check_error(); } static void end_of_sim(const vhpiCbDataT *cb_data) { vhpi_printf("end of sim callback"); vhpiValueT value = { .format = vhpiObjTypeVal }; vhpi_get_value(handle_y, &value); check_error(); fail_unless(value.format == vhpiIntVal); fail_unless(value.value.intg == 75); vhpi_release_handle(handle_x); vhpi_release_handle(handle_y); vhpi_release_handle(handle_sos); }
int VhpiSignalObjHdl::initialise(std::string &name) { // Determine the type of object, either scalar or vector m_value.format = vhpiObjTypeVal; m_value.bufSize = 0; m_value.value.str = NULL; vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &m_value); check_vhpi_error(); switch (m_value.format) { case vhpiEnumVal: case vhpiLogicVal: { m_value.value.enumv = vhpi0; break; } case vhpiEnumVecVal: case vhpiLogicVecVal: { m_size = vhpi_get(vhpiSizeP, GpiObjHdl::get_handle<vhpiHandleT>()); m_value.bufSize = m_size*sizeof(vhpiEnumT); m_value.value.enumvs = (vhpiEnumT *)malloc(m_value.bufSize); if (!m_value.value.enumvs) { LOG_CRITICAL("Unable to alloc mem for write buffer: ABORTING"); } break; } default: { LOG_ERROR("Unable to determine property for %s (%d) format object", ((VhpiImpl*)GpiObjHdl::m_impl)->format_to_string(m_value.format), m_value.format); } } /* We also alloc a second value member for use with read string operations */ m_binvalue.format = vhpiBinStrVal; m_binvalue.bufSize = 0; m_binvalue.value.str = NULL; int new_size = vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &m_binvalue); m_binvalue.bufSize = new_size*sizeof(vhpiCharT) + 1; m_binvalue.value.str = (vhpiCharT *)calloc(m_binvalue.bufSize, m_binvalue.bufSize); if (!m_value.value.str) { LOG_CRITICAL("Unable to alloc mem for read buffer: ABORTING"); } GpiObjHdl::initialise(name); return 0; }
const char* VhpiSignalObjHdl::get_signal_value_binstr(void) { vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &m_binvalue); check_vhpi_error(); return m_binvalue.value.str; }
double VhpiSignalObjHdl::get_signal_value_real(void) { m_value.format = vhpiRealVal; m_value.numElems = 1; m_value.bufSize = sizeof(double); if (vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &m_value)) { check_vhpi_error(); LOG_ERROR("failed to get real value"); } return m_value.value.real; }
long VhpiSignalObjHdl::get_signal_value_long(void) { vhpiValueT value; value.format = vhpiIntVal; value.numElems = 0; if (vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &value)) { check_vhpi_error(); LOG_ERROR("failed to get long value"); } return value.value.intg; }
const char* VhpiSignalObjHdl::get_signal_value_str(void) { switch (m_value.format) { case vhpiStrVal: { int ret = vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &m_value); if (ret) { check_vhpi_error(); LOG_ERROR("Size of m_value.value.str was not large enough req=%d have=%d for type %s", ret, m_value.bufSize, ((VhpiImpl*)GpiObjHdl::m_impl)->format_to_string(m_value.format)); } break; } default: { LOG_ERROR("Reading strings not valid for this handle"); return ""; } } return m_value.value.str; }
const char* VhpiSignalObjHdl::get_signal_value_binstr(void) { switch (m_value.format) { case vhpiRealVal: LOG_INFO("get_signal_value_binstr not supported for %s", ((VhpiImpl*)GpiObjHdl::m_impl)->format_to_string(m_value.format)); return ""; default: { /* Some simulators do not support BinaryValues so we fake up here for them */ int ret = vhpi_get_value(GpiObjHdl::get_handle<vhpiHandleT>(), &m_binvalue); if (ret) { check_vhpi_error(); LOG_ERROR("Size of m_binvalue.value.str was not large enough req=%d have=%d for type %s", ret, m_binvalue.bufSize, ((VhpiImpl*)GpiObjHdl::m_impl)->format_to_string(m_value.format)); } return m_binvalue.value.str; } } }
// this function creates and allocates proper object for value of passed signal vhpiValueT* getFieldValue( vhpiHandleT _hSigHdl ) { vhpiValueT* vValue = NULL; if ( _hSigHdl ) { // allocates memory for vhpiValueT structure // vValue = (vhpiValueT*) malloc( sizeof( vhpiValueT ) ); vValue = new vhpiValueT; memset( vValue, '\x0', sizeof(vhpiValueT) ); // reads format from object (e.g. enum or int etc.) vValue->format = vhpiObjTypeVal; // if object size is greater than allocated value structure // i.e. object has more than one element e.g. is a vector // then allocate additional memory according to number of elements if ( vhpi_get_value( _hSigHdl, vValue ) > 0) { switch ( vValue->format ) { case vhpiEnumVecVal: // read number of elements read by vhpi_get_value vValue->bufSize = vValue->numElems * sizeof( vhpiEnumT ); // allocate memory vValue->value.enumvs = new vhpiEnumT [vValue->bufSize]; break; case vhpiIntVecVal: vValue->bufSize = vValue->numElems * sizeof( vhpiIntT ); vValue->value.intgs = new vhpiIntT [vValue->bufSize]; break; case vhpiRealVecVal: vValue->bufSize = vValue->numElems * sizeof( vhpiRealT ); vValue->value.reals = new vhpiRealT [vValue->bufSize]; break; } } } return vValue; }
int VhpiSignalObjHdl::initialise(std::string &name, std::string &fq_name) { // Determine the type of object, either scalar or vector m_value.format = vhpiObjTypeVal; m_value.bufSize = 0; m_value.value.str = NULL; m_value.numElems = 0; /* We also alloc a second value member for use with read string operations */ m_binvalue.format = vhpiBinStrVal; m_binvalue.bufSize = 0; m_binvalue.numElems = 0; m_binvalue.value.str = NULL; vhpiHandleT handle = GpiObjHdl::get_handle<vhpiHandleT>(); if (0 > vhpi_get_value(get_handle<vhpiHandleT>(), &m_value)) { if (vhpiSliceNameK == vhpi_get(vhpiKindP, handle)) { m_value.format = vhpiEnumVecVal; } else { LOG_DEBUG("vhpi_get_value failed and not a vhpiSliceNameK setting to vhpiRawDataVal"); m_value.format = vhpiRawDataVal; } } LOG_DEBUG("Found %s of format type %s (%d) format object with %d elems buffsize %d size %d", name.c_str(), ((VhpiImpl*)GpiObjHdl::m_impl)->format_to_string(m_value.format), m_value.format, m_value.numElems, m_value.bufSize, vhpi_get(vhpiSizeP, handle)); // Default - overridden below in certain special cases m_num_elems = m_value.numElems; switch (m_value.format) { case vhpiIntVal: case vhpiEnumVal: case vhpiLogicVal: case vhpiRealVal: case vhpiCharVal: { break; } case vhpiIntVecVal: case vhpiEnumVecVal: case vhpiLogicVecVal: { m_num_elems = vhpi_get(vhpiSizeP, handle); m_value.bufSize = m_num_elems*sizeof(vhpiEnumT); m_value.value.enumvs = (vhpiEnumT *)malloc(m_value.bufSize + 1); if (!m_value.value.enumvs) { LOG_CRITICAL("Unable to alloc mem for write buffer: ABORTING"); } LOG_DEBUG("Overriding num_elems to %d", m_num_elems); break; } case vhpiStrVal: { m_num_elems = vhpi_get(vhpiSizeP, handle); m_value.bufSize = (m_num_elems)*sizeof(vhpiCharT) + 1; m_value.value.str = (vhpiCharT *)malloc(m_value.bufSize); m_value.numElems = m_num_elems; if (!m_value.value.str) { LOG_CRITICAL("Unable to alloc mem for write buffer"); } LOG_DEBUG("Overriding num_elems to %d", m_num_elems); break; } case vhpiRawDataVal: { // This is an internal representation - the only way to determine // the size is to iterate over the members and count sub-elements m_num_elems = 0; vhpiHandleT result = NULL; vhpiHandleT iterator = vhpi_iterator(vhpiIndexedNames, handle); while (true) { result = vhpi_scan(iterator); if (NULL == result) break; m_num_elems++; } LOG_DEBUG("Found vhpiRawDataVal with %d elements", m_num_elems); goto gpi_init; } default: { LOG_ERROR("Unable to determine property for %s (%d) format object", ((VhpiImpl*)GpiObjHdl::m_impl)->format_to_string(m_value.format), m_value.format); } } if (m_num_elems) { m_binvalue.bufSize = m_num_elems*sizeof(vhpiCharT) + 1; m_binvalue.value.str = (vhpiCharT *)calloc(m_binvalue.bufSize, sizeof(vhpiCharT)); if (!m_binvalue.value.str) { LOG_CRITICAL("Unable to alloc mem for read buffer of signal %s", name.c_str()); } } gpi_init: return GpiObjHdl::initialise(name, fq_name); }
// this function updates user's variable value bool varUpdateMain( int i, TValObjPtrs* _pValObjs, void* _pVar, int _bVarType ) { if ( vhpi_get_value( _pValObjs[i].hHdl, _pValObjs[i].vValue ) == 0 ) // check port type switch ( _pValObjs[i].vValue->format ) { case vhpiEnumVal: // scalar enum object // copies port value to boolean variable in port map if ( _pValObjs[i].nType == 1 ) { // if logic object (i.e. representing numerical value in binary logic) *(_pValObjs[i].pBoolVar) = logic2bool( _pValObjs[i], _pValObjs[i].vValue->value.enumv ); } else if ( _pValObjs[i].nType == 0 ) // if non-logic object if ( ( (_pValObjs[i].vValue)->value.enumv != 0 ) ) *(_pValObjs[i].pBoolVar) = true; else *(_pValObjs[i].pBoolVar) = false; else { vhpi_printf( "varUpdate(): Object type is not supported\n" ); return false; } // copies port value to integer variable in port structure *(_pValObjs[i].pIntVar) = (_pValObjs[i].vValue)->value.enumv ; if ( _pVar ) // if user variable specified, copies value from port structure if ( ( _bVarType == typeBoolVar ) || ( ( _bVarType == typeDefaultVar ) && ( _pValObjs[i].nType == 1 ) ) ) // boolean variable *(bool*)_pVar = *(_pValObjs[i].pBoolVar); else if ( ( _bVarType == typeIntVar ) || ( ( _bVarType == typeDefaultVar ) && ( _pValObjs[i].nType == 0 ) ) ) // integer variable *(int*)_pVar = *(_pValObjs[i].pIntVar); else vhpi_printf( "varUpdate(): Variable type not supported\n" ); return true; break; case vhpiEnumVecVal: // vector port // copies port value to integer variable in port map if ( _pValObjs[i].nType == 1 ) logicv2int( _pValObjs[i] ); // copies port value to integer[n] variable in port map for ( int j = 0; j < (_pValObjs[i].vValue)->numElems; j++ ) _pValObjs[i].pIntVecVar[j] = (_pValObjs[i].vValue)->value.enumvs[j]; // copies port value to boolean[n] variable in port map for ( int j = 0; j < (_pValObjs[i].vValue)->numElems; j++ ) { if ( _pValObjs[i].nType == 1 ) // if logic object (i.e. representing numerical value in binary logic) _pValObjs[i].pBoolVecVar[j] = logic2bool( _pValObjs[i], (_pValObjs[i].vValue)->value.enumvs[j] ); if ( _pValObjs[i].nType == 0 ) // if non-logic object _pValObjs[i].pBoolVecVar[j] = ( (_pValObjs[i].vValue)->value.enumvs[j] == 0 ) ? false : true ; } if ( _pVar ) // if user variable specified, copies value from port structure if ( ( _pValObjs[i].nType == 1 ) && ( ( _bVarType == typeIntVar ) || ( _bVarType == typeDefaultVar ) ) ) // integer variable *(int*)_pVar = *(_pValObjs[i].pIntVar); else if ( _bVarType == typeBoolVecVar ) // boolean[n] variable memcpy( _pVar, _pValObjs[i].pBoolVecVar, _pValObjs[i].vValue->bufSize ); else if ( ( _bVarType == typeIntVecVar ) || ( ( _bVarType == typeDefaultVar ) && ( _pValObjs[i].nType == 0 ) ) ) // integer[n] variable memcpy( _pVar, _pValObjs[i].pIntVecVar, _pValObjs[i].vValue->bufSize ); else vhpi_printf( "varUpdate(): Variable type not supported\n" ); return true; break; case vhpiRealVal: // real port // copies port value to real variable in port map *(_pValObjs[i].pRealVar) = (_pValObjs[i].vValue)->value.real; if ( _pVar ) // if user variable specified, copies value from port structure *(double*)_pVar = *(_pValObjs[i].pRealVar); return true; break; case vhpiRealVecVal: // real port // copies port value to real[n] variable in port map for ( int j = 0; j < (_pValObjs[i].vValue)->numElems; j++ ) _pValObjs[i].pRealVecVar[j] = (_pValObjs[i].vValue)->value.reals[j]; if ( _pVar ) // if user variable specified, copies value from port structure memcpy( _pVar, _pValObjs[i].pRealVecVar, _pValObjs[i].vValue->bufSize ); return true; break; case vhpiIntVal: // integer port // copies port value to integer variable in port map *(_pValObjs[i].pIntVar) = (_pValObjs[i].vValue)->value.intg; if ( _pVar ) // if user variable specified, copies value from port structure *(int*)_pVar = *(_pValObjs[i].pIntVar); return true; break; case vhpiIntVecVal: // integer[n] port // copies port value to integer[n] variable in port map for ( int j = 0; j < (_pValObjs[i].vValue)->numElems; j++ ) _pValObjs[i].pIntVecVar[j] = (_pValObjs[i].vValue)->value.intgs[j]; if ( _pVar ) // if user variable specified, copies value from port structure memcpy( _pVar, _pValObjs[i].pIntVecVar, _pValObjs[i].vValue->bufSize ); return true; break; default: vhpi_printf( "varUpdate(): Object type is not supported yet\n" ); return false; break; } else { vhpiErrorInfoT errInf; vhpi_printf( "varUpdate(): Call to vhpi_get_value() failed\n" ); // check error info from vhpi_get_value() if ( vhpi_check_error( &errInf ) ) vhpi_printf( "varUpdate(): vhpi_check_error() message: \n", errInf.message ); else vhpi_printf( "varUpdate(): No vhpi_check_error() message...\n" ); return false; } }
static void test_bin_str(void) { vhpiHandleT root = vhpi_handle(vhpiRootInst, NULL); check_error(); vhpiHandleT hb = vhpi_handle_by_name("b", root); check_error(); vhpiHandleT hv = vhpi_handle_by_name("v", root); check_error(); char b_str[2] = { 0xff, 0xff }; vhpiValueT b_value = { .format = vhpiBinStrVal, .bufSize = sizeof(b_str), .value.str = (vhpiCharT *)b_str }; vhpi_get_value(hb, &b_value); check_error(); vhpi_printf("b bit string '%s' %x", b_str); fail_unless(strcmp(b_str, "0") == 0); vhpiValueT v_value = { .format = vhpiBinStrVal, .bufSize = 0, .value.str = NULL }; const int need = vhpi_get_value(hv, &v_value); check_error(); vhpi_printf("need %d bytes for v string", need); v_value.value.str = malloc(need); v_value.bufSize = need; fail_if(v_value.value.str == NULL); fail_unless(vhpi_get_value(hv, &v_value) == 0); check_error(); vhpi_printf("v bit string '%s'", v_value.value.str); fail_unless(strcmp((char *)v_value.value.str, "0011") == 0); free(v_value.value.str); vhpi_release_handle(root); vhpi_release_handle(hb); vhpi_release_handle(hv); } static void y_value_change(const vhpiCbDataT *cb_data) { vhpiValueT value = { .format = vhpiObjTypeVal }; vhpi_get_value(handle_y, &value); check_error(); fail_unless(value.format == vhpiIntVal); vhpi_printf("y value changed to %d", value.value.intg); if (value.value.intg == 75) { test_bin_str(); vhpi_control(vhpiFinish); check_error(); } else { value.value.intg++; vhpi_put_value(handle_x, &value, vhpiForcePropagate); check_error(); } } static void after_5ns(const vhpiCbDataT *cb_data) { vhpi_printf("after_5ns callback!"); long cycles; vhpiTimeT now; vhpi_get_time(&now, &cycles); fail_unless(now.low == 5000000); fail_unless(now.high == 0); fail_unless(cycles == 0); vhpiValueT value = { .format = vhpiObjTypeVal }; vhpi_get_value(handle_y, &value); check_error(); fail_unless(value.format == vhpiIntVal); fail_unless(value.value.intg == 6); value.value.intg = 70; vhpi_put_value(handle_x, &value, vhpiForcePropagate); check_error(); vhpiCbDataT cb_data2 = { .reason = vhpiCbValueChange, .cb_rtn = y_value_change, .obj = handle_y }; vhpi_register_cb(&cb_data2, 0); check_error(); }