// this function registers callback for vhpiCbAfterDelay reason // arguments: callback routine name, delay in simulation resolution units vhpiHandleT registerCbAfterDelay( PLI_VOID(*cb_rtn_name) (const struct vhpiCbDataS *), vhpiTimeT _tTime, PLI_VOID* _hUserData ) { vhpiCbDataT cbData; vhpiHandleT cbData_Hdl; vhpiErrorInfoT errInf; cbData.reason = vhpiCbAfterDelay; cbData.cb_rtn = cb_rtn_name; cbData.obj = NULL; cbData.time = &_tTime; cbData.value = NULL; cbData.user_data = _hUserData; if ( ( cbData_Hdl = vhpi_register_cb( &cbData, vhpiReturnCb ) ) ) return cbData_Hdl; else { // check error message and print failure info vhpi_printf( "isRegisteredCbAfterDelay(): Callback on vhpiCbAfterDelay reason NOT registered \n" ); if ( vhpi_check_error( &errInf ) ) vhpi_printf( errInf.message ); else vhpi_printf( "isRegisteredCbAfterDelay(): No vhpi_check_error() message...\n" ); return NULL; } }
// Should be run after every VPI call to check error status static int __check_vhpi_error(const char *func, long line) { int level=0; #if VHPI_CHECKING vhpiErrorInfoT info; int loglevel; level = vhpi_check_error(&info); if (level == 0) return; switch (level) { case vhpiNote: loglevel = GPIInfo; break; case vhpiWarning: loglevel = GPIWarning; break; case vhpiError: loglevel = GPIError; break; case vhpiFailure: case vhpiSystem: case vhpiInternal: loglevel = GPICritical; break; } gpi_log("cocotb.gpi", loglevel, __FILE__, func, line, "VPI Error level %d: %s\nFILE %s:%d", info.severity, info.message, info.file, info.line); #endif return level; }
// this function registers callback for vhpiCbEndOfSimulation reason // arguments: callback routine name bool isRegisteredCbEndOfSimulation( PLI_VOID(*cb_rtn_name) (const struct vhpiCbDataS *), PLI_VOID* _hUserData ) { vhpiCbDataT cbData; vhpiHandleT cbData_Hdl; vhpiErrorInfoT errInf; cbData.reason = vhpiCbEndOfSimulation ; cbData.cb_rtn = cb_rtn_name; cbData.obj = NULL; cbData.time = NULL; cbData.value = NULL; cbData.user_data = _hUserData; if ( ( cbData_Hdl = vhpi_register_cb( &cbData, vhpiReturnCb ) ) ) return true; else { // check error message and print failure info vhpi_printf( "isRegisteredCbEndOfSimulation(): Callback on vhpiCbEndOfSimulation reason NOT registered \n" ); if ( vhpi_check_error( &errInf ) ) vhpi_printf( errInf.message ); else vhpi_printf( "isRegisteredCbEndOfSimulation(): No vhpi_check_error() message...\n" ); return false; } }
// this function registers callback for vhpiCbValueChange reason // arguments: handles to signal and to user data bool isRegisteredCbValueChange( PLI_VOID( *cb_rtn_name ) (const struct vhpiCbDataS *), vhpiHandleT _hSigHdl, PLI_VOID* _hUserData ) { vhpiCbDataT cbData; vhpiHandleT cbData_Hdl; vhpiErrorInfoT errInf; cbData.cb_rtn = cb_rtn_name; cbData.reason = vhpiCbValueChange; cbData.obj = _hSigHdl; cbData.value = getFieldValue( cbData.obj ); cbData.time = NULL; cbData.user_data = _hUserData; // pass user data handle to callback vhpi_register_cb( &cbData, vhpiReturnCb ); if ( ( cbData_Hdl = vhpi_register_cb( &cbData, vhpiReturnCb ) ) ) return true; else { // check error message and print failure info vhpi_printf( "isRegisteredCbValueChange(): Callback on vhpiCbValueChange reason for signal: %s NOT registered \n", vhpi_get_str( vhpiFullNameP, _hSigHdl ) ); if ( vhpi_check_error( &errInf ) ) vhpi_printf( errInf.message ); else vhpi_printf( "isRegisteredCbValueChange(): No vhpi_check_error() message...\n" ); return false; } }
// 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; } }
// this function updates object's value of index in in information table bool objUpdateMain( int i , TValObjPtrs* _pValObjs, void* _pVar, int _bVarType) { if ( ( (_pValObjs[i].vValue)->format == vhpiEnumVal ) && ( ( _bVarType == typeIntVar ) || ( ( _pValObjs[i].nType == 0 ) && ( _bVarType == typeDefaultVar ) ) ) ) { // if scalar enum object and int variable (default for scalar objects of non-logic enum type) if (( _pVar )) // if user variable specified, copies it to port structure *(_pValObjs[i].pIntVar) = *(int*)_pVar; // updates value structure with variable value (_pValObjs[i].vValue)->value.enumv = *(_pValObjs[i].pIntVar); if ( ( *(_pValObjs[i].pIntVar) > _pValObjs[i].enumMax ) || ( *(_pValObjs[i].pIntVar) < _pValObjs[i].enumMin ) ) vhpi_printf( "objUpdate(): Variable value %d exceeds %s type's range.\n", *(_pValObjs[i].pIntVar), _pValObjs[i].szName ); } else if ( ( (_pValObjs[i].vValue)->format == vhpiEnumVal ) && ( ( _bVarType == typeBoolVar ) || ( ( _pValObjs[i].nType == 1 ) && ( _bVarType == typeDefaultVar ) ) ) ) { // if scalar enum object and bool variable (default for scalar objects of logic enum type) if (( _pVar )) // if user variable specified, copies it to port structure *(_pValObjs[i].pBoolVar) = *(bool*)_pVar; // updates value structure with variable value if ( _pValObjs[i].nType == 0 ) // if non-logic enum type (_pValObjs[i].vValue)->value.enumv = *(_pValObjs[i].pBoolVar) ? 1 : 0; if ( _pValObjs[i].nType == 1 ) // if logic enum type (_pValObjs[i].vValue)->value.enumv = *(_pValObjs[i].pBoolVar) ? _pValObjs[i].enumOnes[0] : _pValObjs[i].enumZeros[0]; } else if ( ( (_pValObjs[i].vValue)->format == vhpiEnumVecVal ) && ( ( _bVarType == typeIntVecVar ) || ( ( _pValObjs[i].nType == 0 ) && ( _bVarType == typeDefaultVar ) ) ) ) { // if vector of enum object and int[n] variable (default for vector objects of non-logic enum type) if (( _pVar )) // if user variable specified, copies it to port structure memcpy( _pValObjs[i].pIntVecVar, _pVar, _pValObjs[i].vValue->bufSize ); // updates value structure with variable value for ( int j = 0; j < _pValObjs[i].vValue->numElems; j++ ) { // check if integer value fits the object type range if ( ( _pValObjs[i].pIntVecVar[j] <= _pValObjs[i].enumMax ) && ( _pValObjs[i].pIntVecVar[j] >= _pValObjs[i].enumMin ) ) (_pValObjs[i].vValue)->value.enumvs[j] = _pValObjs[i].pIntVecVar[j]; else { // if integer value exceeds the object type range vhpi_printf( "objUpdate(): Variable value %d exceeds %s type range. Object value set to the leftmost value in type\n", _pValObjs[i].pIntVecVar[j], _pValObjs[i].szName ); (_pValObjs[i].vValue)->value.enumvs[j] = _pValObjs[i].enumMin; } } } else if ( ( (_pValObjs[i].vValue)->format == vhpiEnumVecVal ) && ( _bVarType == typeBoolVecVar ) ) { // if vector of enum object and bool[n] variable if (( _pVar )) // if user variable specified, copies it to port structure memcpy( _pValObjs[i].pBoolVecVar, _pVar, _pValObjs[i].vValue->bufSize ); // updates value structure with variable value if ( _pValObjs[i].nType == 0 ) // if non-logic type for ( int j = 0; j < _pValObjs[i].vValue->numElems; j++ ) (_pValObjs[i].vValue)->value.enumvs[j] = _pValObjs[i].pBoolVecVar[j] ? _pValObjs[i].enumMin + 1 : _pValObjs[i].enumMin; if ( _pValObjs[i].nType == 1 ) // if logic type for ( int j = 0; j < _pValObjs[i].vValue->numElems; j++ ) (_pValObjs[i].vValue)->value.enumvs[j] = _pValObjs[i].pBoolVecVar[j] ? _pValObjs[i].enumOnes[0] : _pValObjs[i].enumZeros[0]; } else if ( ( (_pValObjs[i].vValue)->format == vhpiEnumVecVal ) && ( _pValObjs[i].nType == 1 ) && ( ( _bVarType == typeIntVar ) || ( _bVarType == typeDefaultVar ) ) ) { // if vector of enum object and int variable (default for vector objects of logic enum type) if (( _pVar )) // if user variable specified, copies it to port structure memcpy( _pValObjs[i].pIntVar, _pVar, _pValObjs[i].vValue->bufSize ); // updates value structure with variable value int2logicv( _pValObjs[i] ); } else if ( ( (_pValObjs[i].vValue)->format == vhpiIntVal ) && ( ( _bVarType == typeIntVar ) || ( _bVarType == typeDefaultVar ) ) ) { // if integer port and int variable (default for integer ports) if (( _pVar )) // if user variable specified, copies it to port structure *(_pValObjs[i].pIntVar) = *(int*)_pVar; // updates value structure with variable value (_pValObjs[i].vValue)->value.intg = *(_pValObjs[i].pIntVar); } else if ( ( (_pValObjs[i].vValue)->format == vhpiIntVecVal ) && ( ( _bVarType == typeIntVecVar ) || ( _bVarType == typeDefaultVar ) ) ) { // if array of integer port and int[n] variable (default for array of integer port) if (( _pVar )) // if user variable specified, copies it to port structure memcpy( _pValObjs[i].pIntVecVar, _pVar, _pValObjs[i].vValue->bufSize ); // updates value structure with variable value for ( int j = 0; j < _pValObjs[i].vValue->numElems; j++ ) (_pValObjs[i].vValue)->value.intgs[j] = _pValObjs[i].pIntVecVar[j]; } else if ( ( (_pValObjs[i].vValue)->format == vhpiRealVal ) && ( ( _bVarType == typeRealVar ) || ( _bVarType == typeDefaultVar ) ) ) { // if real port and double variable (default for real port) if (( _pVar )) // if user variable specified, copies it to port structure *(_pValObjs[i].pRealVar) = *(double*)_pVar; // updates value structure with variable value (_pValObjs[i].vValue)->value.real = *(_pValObjs[i].pRealVar); } else if ( ( (_pValObjs[i].vValue)->format == vhpiRealVecVal ) && ( ( _bVarType == typeRealVecVar ) || ( _bVarType == typeDefaultVar ) ) ) { // if array of real port and double[n] variable (default for array of real port) if (( _pVar )) // if user variable specified, copies it to port structure memcpy( _pValObjs[i].pRealVecVar, _pVar, _pValObjs[i].vValue->bufSize ); // updates value structure with variable value for ( int j = 0; j < _pValObjs[i].vValue->numElems; j++ ) (_pValObjs[i].vValue)->value.reals[j] = _pValObjs[i].pRealVecVar[j]; } else { vhpi_printf( "objUpdate(): Object %s type is not supported\n", _pValObjs[i].szName ); return false; } vhpiErrorInfoT errInf; if ( ( vhpi_put_value( _pValObjs[i].hHdl, _pValObjs[i].vValue, vhpiDepositPropagate ) ) == 0 ) { // vhpi_printf("Signal value update succeeded\n"); return true; } else { vhpi_printf( "objUpdate(): Object %s value update failed\n", _pValObjs[i].szName ); // check error info from vhpi_put_value() if ( vhpi_check_error( &errInf ) ) vhpi_printf( "objUpdate(): vhpi_check_error() message: \n", errInf.message ); else vhpi_printf( "objUpdate(): No vhpi_check_error() message...\n" ); return false; } }
static void check_error(void) { vhpiErrorInfoT info; if (vhpi_check_error(&info)) vhpi_assert(vhpiFailure, "unexpected error '%s'", info.message); }