/* * count and list all acc world (prim terminal) drivers */ void mei_count_drivers(handle inst, handle net) { int count = 0; handle term; char s1[1024], s2[1024]; io_printf(" ... processing drivers for %s:\n", acc_fetch_fullname(net)); for (term = acc_next_driver(net, NULL); term != NULL; term = acc_next_driver(net, term)) { if (mei_isinside(inst, term) == 1) { strcpy(s1, "inside"); count++; } else strcpy(s1, "outside"); if (acc_fetch_type(term) == accTerminal) { sprintf(s2, "prim %s port %d", acc_fetch_fullname(acc_handle_parent(term)), acc_fetch_index(term)); } else strcpy(s2, acc_fetch_fullname(term)); io_printf(" +++ %s is %s driver of %s in %s.\n", s2, s1, acc_fetch_fullname(net), acc_fetch_fullname(inst)); } io_printf("net %s has %d inside drivers.\n", acc_fetch_name(net), count); }
/* * variable value change call back routine */ int var_prt_vclchg(p_vc_record vcp) { /* unsigned long long now, chgtim; */ int otyp, ltime, htime; handle net; char s1[1024], s2[1024], s3[1024]; /* current time */ ltime = tf_getlongsimtime(&htime); /* -- now = ((unsigned long long) ((unsigned long) htime)) << 32 | ((unsigned long long) ((unsigned long) ltime)); -* vc record time *- chgtim = ((unsigned long long) ((unsigned long) vcp->vc_hightime)) << 32 | ((unsigned long long) ((unsigned long) vcp->vc_lowtime)); -- */ /* net handle assigned to user data field */ net = (handle) vcp->user_data; otyp = acc_fetch_type(net); if (vcp->vc_reason != event_value_change) { /* these do not have value, i.e. get va8ue return NULL with error */ if (otyp == accPort || otyp == accPortBit || otyp == accTerminal) { sprintf(s1, "obj=%s", acc_fetch_type_str(otyp)); } else strcpy(s1, acc_fetch_value(net, "%b", NULL)); } switch (vcp->vc_reason) { case logic_value_change: sprintf(s2, "scalar=%u(%s)", (unsigned) vcp->out_value.logic_value, s1); break; case sregister_value_change: sprintf(s2, "sr-scalar=%u(%s)", (unsigned) vcp->out_value.logic_value, s1); break; case real_value_change: case realtime_value_change: sprintf(s2, "**error**"); break; case event_value_change: strcpy(s2, "**event**"); break; default: sprintf(s2, "vector=%s", s1); } /* -- io_printf("--> now %uL (chg time %uL): %s=%s\n", now, chgtim, -- */ if (otyp != accTerminal) strcpy(s3, acc_fetch_fullname(net)); else strcpy(s3, "**terminal**"); io_printf("--> now %d (chg time %d): %s=%s\n", ltime, vcp->vc_lowtime, s3, s2); return(0); }
/* * wire strength change value change call back routine */ int wire_prt_vclchg(p_vc_record vcp) { /* unsigned long long now, chgtim; */ int typ, ltime, htime; handle net; char s1[1024], s2[1024], s3[1024]; /* current time */ ltime = tf_getlongsimtime(&htime); /* --- now = ((unsigned long long) ((unsigned long) htime)) << 32 | ((unsigned long long) ((unsigned long) ltime)); -* vc record time *- chgtim = ((unsigned long long) ((unsigned long) vcp->vc_hightime)) << 32 | ((unsigned long long) ((unsigned long) vcp->vc_lowtime)); --- */ /* net handle assigned to user data field */ net = (handle) vcp->user_data; /* build strength value string */ sprintf(s1, "<%d, %d>=%d", (int) vcp->out_value.strengths_s.strength1, (int) vcp->out_value.strengths_s.strength2, (int) vcp->out_value.strengths_s.logic_value); /* also get value as internal strength %v string */ strcpy(s2, acc_fetch_value(net, "%v", NULL)); if (vcp->vc_reason != strength_value_change) { io_printf("*** ERROR: wire change reason %d - strength change expected\n", vcp->vc_reason); } /* --- io_printf("--> now %uL (chg time %uL): %s=%s(%s)\n", now, chgtim, -- */ /* terminals do not have names */ typ = acc_fetch_type(net); if (typ != accTerminal) strcpy(s3, acc_fetch_fullname(net)); else strcpy(s3, "**terminal**"); io_printf("--> now %d (chg time %d): %s=%s(%s)\n", ltime, vcp->vc_lowtime, s3, s2, s1); return(0); }
/** * @name Find the root handle * @brief Find the root handle using an optional name * * Get a handle to the root simulator object. This is usually the toplevel. * * If no name is provided, we return the first root instance. * * If name is provided, we check the name against the available objects until * we find a match. If no match is found we return NULL */ GpiObjHdl *FliImpl::get_root_handle(const char *name) { mtiRegionIdT root; char *rgn_name; char *rgn_fullname; std::string root_name; std::string root_fullname; PLI_INT32 accType; PLI_INT32 accFullType; for (root = mti_GetTopRegion(); root != NULL; root = mti_NextRegion(root)) { LOG_DEBUG("Iterating over: %s", mti_GetRegionName(root)); if (name == NULL || !strcmp(name, mti_GetRegionName(root))) break; } if (!root) { goto error; } rgn_name = mti_GetRegionName(root); rgn_fullname = mti_GetRegionFullName(root); root_name = rgn_name; root_fullname = rgn_fullname; mti_VsimFree(rgn_fullname); LOG_DEBUG("Found toplevel: %s, creating handle....", root_name.c_str()); accType = acc_fetch_type(root); accFullType = acc_fetch_fulltype(root); return create_gpi_obj_from_handle(root, root_name, root_fullname, accType, accFullType); error: LOG_ERROR("FLI: Couldn't find root handle %s", name); for (root = mti_GetTopRegion(); root != NULL; root = mti_NextRegion(root)) { if (name == NULL) break; LOG_ERROR("FLI: Toplevel instances: %s != %s...", name, mti_GetRegionName(root)); } return NULL; }
GpiObjHdl* FliImpl::native_check_create(void *raw_hdl, GpiObjHdl *parent) { LOG_DEBUG("Trying to convert a raw handle to an FLI Handle."); const char * c_name = acc_fetch_name(raw_hdl); const char * c_fullname = acc_fetch_fullname(raw_hdl); if (!c_name) { LOG_DEBUG("Unable to query the name of the raw handle."); return NULL; } std::string name = c_name; std::string fq_name = c_fullname; PLI_INT32 accType = acc_fetch_type(raw_hdl); PLI_INT32 accFullType = acc_fetch_fulltype(raw_hdl); return create_gpi_obj_from_handle(raw_hdl, name, fq_name, accType, accFullType); }
/* * routine to add vcl to one net/reg/var/event */ static void add_vcl(handle net) { int typ, fulltyp; char s1[1024]; /* DBG remove -- */ typ = acc_fetch_type(net); fulltyp = acc_fetch_fulltype(net); if (typ != accTerminal) strcpy(s1, acc_fetch_fullname(net)); else strcpy(s1, "**terminal**"); io_printf("Adding vcl for %s type %s (fulltype %s)\n", s1, acc_fetch_type_str(typ), acc_fetch_type_str(fulltyp)); /* --- */ if (typ == accNet) { acc_vcl_add(net, wire_prt_vclchg, (void *) net, vcl_verilog_strength); } else acc_vcl_add(net, var_prt_vclchg, (void *) net, vcl_verilog_logic); }
GpiIterator::Status FliIterator::next_handle(std::string &name, GpiObjHdl **hdl, void **raw_hdl) { HANDLE obj; GpiObjHdl *new_obj; if (!selected) return GpiIterator::END; gpi_objtype_t obj_type = m_parent->get_type(); std::string parent_name = m_parent->get_name(); /* We want the next object in the current mapping. * If the end of mapping is reached then we want to * try next one until a new object is found */ do { obj = NULL; if (m_iterator != m_currentHandles->end()) { obj = *m_iterator++; /* For GPI_GENARRAY, only allow the generate statements through that match the name * of the generate block. */ if (obj_type == GPI_GENARRAY) { if (acc_fetch_fulltype(obj) == accForGenerate) { std::string rgn_name = mti_GetRegionName(static_cast<mtiRegionIdT>(obj)); if (rgn_name.compare(0,parent_name.length(),parent_name) != 0) { obj = NULL; continue; } } else { obj = NULL; continue; } } break; } else { LOG_DEBUG("No more valid handles in the current OneToMany=%d iterator", *one2many); } if (++one2many >= selected->end()) { obj = NULL; break; } /* GPI_GENARRAY are pseudo-regions and all that should be searched for are the sub-regions */ if (obj_type == GPI_GENARRAY && *one2many != FliIterator::OTM_REGIONS) { LOG_DEBUG("fli_iterator OneToMany=%d skipped for GPI_GENARRAY type", *one2many); continue; } populate_handle_list(*one2many); switch (*one2many) { case FliIterator::OTM_CONSTANTS: case FliIterator::OTM_VARIABLE_SUB_ELEMENTS: m_currentHandles = &m_vars; m_iterator = m_vars.begin(); break; case FliIterator::OTM_SIGNALS: case FliIterator::OTM_SIGNAL_SUB_ELEMENTS: m_currentHandles = &m_sigs; m_iterator = m_sigs.begin(); break; case FliIterator::OTM_REGIONS: m_currentHandles = &m_regs; m_iterator = m_regs.begin(); break; default: LOG_WARN("Unhandled OneToMany Type (%d)", *one2many); } } while (!obj); if (NULL == obj) { LOG_DEBUG("No more children, all relationships tested"); return GpiIterator::END; } char *c_name; PLI_INT32 accType = 0; PLI_INT32 accFullType = 0; switch (*one2many) { case FliIterator::OTM_CONSTANTS: case FliIterator::OTM_VARIABLE_SUB_ELEMENTS: c_name = mti_GetVarName(static_cast<mtiVariableIdT>(obj)); accFullType = accType = mti_GetVarKind(static_cast<mtiVariableIdT>(obj)); break; case FliIterator::OTM_SIGNALS: c_name = mti_GetSignalName(static_cast<mtiSignalIdT>(obj)); accType = acc_fetch_type(obj); accFullType = acc_fetch_fulltype(obj); break; case FliIterator::OTM_SIGNAL_SUB_ELEMENTS: c_name = mti_GetSignalNameIndirect(static_cast<mtiSignalIdT>(obj), NULL, 0); accType = acc_fetch_type(obj); accFullType = acc_fetch_fulltype(obj); break; case FliIterator::OTM_REGIONS: c_name = mti_GetRegionName(static_cast<mtiRegionIdT>(obj)); accType = acc_fetch_type(obj); accFullType = acc_fetch_fulltype(obj); break; default: LOG_WARN("Unhandled OneToMany Type (%d)", *one2many); } if (!c_name) { if (!VS_TYPE_IS_VHDL(accFullType)) { *raw_hdl = (void *)obj; return GpiIterator::NOT_NATIVE_NO_NAME; } return GpiIterator::NATIVE_NO_NAME; } /* * If the parent is not a generate loop, then watch for generate handles and create * the pseudo-region. * * NOTE: Taking advantage of the "caching" to only create one pseudo-region object. * Otherwise a list would be required and checked while iterating */ if (*one2many == FliIterator::OTM_REGIONS && obj_type != GPI_GENARRAY && accFullType == accForGenerate) { std::string idx_str = c_name; std::size_t found = idx_str.find_last_of("("); if (found != std::string::npos && found != 0) { FliObj *fli_obj = dynamic_cast<FliObj *>(m_parent); name = idx_str.substr(0,found); obj = m_parent->get_handle<HANDLE>(); accType = fli_obj->get_acc_type(); accFullType = fli_obj->get_acc_full_type(); } else { LOG_WARN("Unhandled Generate Loop Format - %s", name.c_str()); name = c_name; } } else { name = c_name; } if (*one2many == FliIterator::OTM_SIGNAL_SUB_ELEMENTS) { mti_VsimFree(c_name); } std::string fq_name = m_parent->get_fullname(); if (fq_name == "/") { fq_name += name; } else if (*one2many == FliIterator::OTM_SIGNAL_SUB_ELEMENTS || *one2many == FliIterator::OTM_VARIABLE_SUB_ELEMENTS || obj_type == GPI_GENARRAY) { std::size_t found; if (obj_type == GPI_STRUCTURE) { found = name.find_last_of("."); } else { found = name.find_last_of("("); } if (found != std::string::npos) { fq_name += name.substr(found); if (obj_type != GPI_GENARRAY) { name = name.substr(found+1); } } else { LOG_WARN("Unhandled Sub-Element Format - %s", name.c_str()); fq_name += "/" + name; } } else { fq_name += "/" + name; } FliImpl *fli_impl = reinterpret_cast<FliImpl *>(m_impl); new_obj = fli_impl->create_gpi_obj_from_handle(obj, name, fq_name, accType, accFullType); if (new_obj) { *hdl = new_obj; return GpiIterator::NATIVE; } else { return GpiIterator::NOT_NATIVE; } }
/** * @name Native Check Create * @brief Determine whether a simulation object is native to FLI and create * a handle if it is */ GpiObjHdl* FliImpl::native_check_create(int32_t index, GpiObjHdl *parent) { gpi_objtype_t obj_type = parent->get_type(); HANDLE hdl; PLI_INT32 accType; PLI_INT32 accFullType; char buff[14]; if (obj_type == GPI_GENARRAY) { LOG_DEBUG("Looking for index %d from %s", index, parent->get_name_str()); snprintf(buff, 14, "(%d)", index); std::string idx = buff; std::string name = parent->get_name() + idx; std::string fq_name = parent->get_fullname() + idx; std::vector<char> writable(fq_name.begin(), fq_name.end()); writable.push_back('\0'); if ((hdl = mti_FindRegion(&writable[0])) != NULL) { accType = acc_fetch_type(hdl); accFullType = acc_fetch_fulltype(hdl); LOG_DEBUG("Found region %s -> %p", fq_name.c_str(), hdl); LOG_DEBUG(" Type: %d", accType); LOG_DEBUG(" Full Type: %d", accFullType); } else { LOG_DEBUG("Didn't find anything named %s", &writable[0]); return NULL; } return create_gpi_obj_from_handle(hdl, name, fq_name, accType, accFullType); } else if (obj_type == GPI_REGISTER || obj_type == GPI_ARRAY || obj_type == GPI_STRING) { FliValueObjHdl *fli_obj = reinterpret_cast<FliValueObjHdl *>(parent); LOG_DEBUG("Looking for index %u from %s", index, parent->get_name_str()); if ((hdl = fli_obj->get_sub_hdl(index)) == NULL) { LOG_DEBUG("Didn't find the index %d", index); return NULL; } snprintf(buff, 14, "(%d)", index); std::string idx = buff; std::string name = parent->get_name() + idx; std::string fq_name = parent->get_fullname() + idx; if (!(fli_obj->is_var())) { accType = acc_fetch_type(hdl); accFullType = acc_fetch_fulltype(hdl); LOG_DEBUG("Found a signal %s -> %p", fq_name.c_str(), hdl); LOG_DEBUG(" Type: %d", accType); LOG_DEBUG(" Full Type: %d", accFullType); } else { accFullType = accType = mti_GetVarKind(static_cast<mtiVariableIdT>(hdl)); LOG_DEBUG("Found a variable %s -> %p", fq_name.c_str(), hdl); LOG_DEBUG(" Type: %d", accType); LOG_DEBUG(" Full Type: %d", accFullType); } return create_gpi_obj_from_handle(hdl, name, fq_name, accType, accFullType); } else { LOG_ERROR("FLI: Parent of type %d must be of type GPI_GENARRAY, GPI_REGISTER, GPI_ARRAY, or GPI_STRING to have an index.", obj_type); return NULL; } }
/** * @name Native Check Create * @brief Determine whether a simulation object is native to FLI and create * a handle if it is */ GpiObjHdl* FliImpl::native_check_create(std::string &name, GpiObjHdl *parent) { bool search_rgn = false; bool search_sig = false; bool search_var = false; std::string fq_name = parent->get_fullname(); gpi_objtype_t obj_type = parent->get_type(); if (fq_name == "/") { fq_name += name; search_rgn = true; search_sig = true; search_var = true; } else if (obj_type == GPI_MODULE) { fq_name += "/" + name; search_rgn = true; search_sig = true; search_var = true; } else if (obj_type == GPI_STRUCTURE) { FliValueObjHdl *fli_obj = reinterpret_cast<FliValueObjHdl *>(parent); fq_name += "." + name; search_rgn = false; search_var = fli_obj->is_var(); search_sig = !search_var; } else { LOG_ERROR("FLI: Parent of type %d must be of type GPI_MODULE or GPI_STRUCTURE to have a child.", obj_type); return NULL; } LOG_DEBUG("Looking for child %s from %s", name.c_str(), parent->get_name_str()); std::vector<char> writable(fq_name.begin(), fq_name.end()); writable.push_back('\0'); HANDLE hdl = NULL; PLI_INT32 accType; PLI_INT32 accFullType; if (search_rgn && (hdl = mti_FindRegion(&writable[0])) != NULL) { accType = acc_fetch_type(hdl); accFullType = acc_fetch_fulltype(hdl); LOG_DEBUG("Found region %s -> %p", fq_name.c_str(), hdl); LOG_DEBUG(" Type: %d", accType); LOG_DEBUG(" Full Type: %d", accFullType); } else if (search_sig && (hdl = mti_FindSignal(&writable[0])) != NULL) { accType = acc_fetch_type(hdl); accFullType = acc_fetch_fulltype(hdl); LOG_DEBUG("Found a signal %s -> %p", fq_name.c_str(), hdl); LOG_DEBUG(" Type: %d", accType); LOG_DEBUG(" Full Type: %d", accFullType); } else if (search_var && (hdl = mti_FindVar(&writable[0])) != NULL) { accFullType = accType = mti_GetVarKind(static_cast<mtiVariableIdT>(hdl)); LOG_DEBUG("Found a variable %s -> %p", fq_name.c_str(), hdl); LOG_DEBUG(" Type: %d", accType); LOG_DEBUG(" Full Type: %d", accFullType); } else if (search_rgn){ mtiRegionIdT rgn; /* If not found, check to see if the name of a generate loop and create a pseudo-region */ for (rgn = mti_FirstLowerRegion(parent->get_handle<mtiRegionIdT>()); rgn != NULL; rgn = mti_NextRegion(rgn)) { if (acc_fetch_fulltype(rgn) == accForGenerate) { std::string rgn_name = mti_GetRegionName(static_cast<mtiRegionIdT>(rgn)); if (rgn_name.compare(0,name.length(),name) == 0) { FliObj *fli_obj = dynamic_cast<FliObj *>(parent); return create_gpi_obj_from_handle(parent->get_handle<HANDLE>(), name, fq_name, fli_obj->get_acc_type(), fli_obj->get_acc_full_type()); } } } } if (NULL == hdl) { LOG_DEBUG("Didn't find anything named %s", &writable[0]); return NULL; } /* Generate Loops have inconsistent behavior across fli. A "name" * without an index, i.e. dut.loop vs dut.loop(0), will attempt to map * to index 0, if index 0 exists. If it doesn't then it won't find anything. * * If this unique case is hit, we need to create the Pseudo-region, with the handle * being equivalent to the parent handle. */ if (accFullType == accForGenerate) { FliObj *fli_obj = dynamic_cast<FliObj *>(parent); return create_gpi_obj_from_handle(parent->get_handle<HANDLE>(), name, fq_name, fli_obj->get_acc_type(), fli_obj->get_acc_full_type()); } return create_gpi_obj_from_handle(hdl, name, fq_name, accType, accFullType); }
/************************************************* lxt2_add - add object to file ************************************************/ static void lxt2_add( handle object, int depth ) { int real = 0; int event = 0; int flags; int msb; int lsb; info_p info; handle block; handle term; static int filter[] = { accIntegerVar, accNamedEvent, accNet, accRealVar, accRegister, accTimeVar, 0 }; switch( acc_fetch_type(object) ) { case accNamedEvent: flags = LXT2_WR_SYM_F_BITS; event = 1; break; case accRealVar: flags = LXT2_WR_SYM_F_DOUBLE; real = 1; break; case accIntegerVar: case accNet: case accPort: case accReg: case accTimeVar: case accParameter: flags = LXT2_WR_SYM_F_BITS; break; case accStatement: case accTask: case accModule: term = null; while(1) { term = acc_next( filter, object, term ); if( term == null ) { break; } lxt2_add( term, depth ); } if( depth == 1 ) { return; } block = null; while(1) { block = acc_next_child( object, block ); if( block == null ) { break; } lxt2_add( block, (depth==0) ? 0 : depth-1 ); } return; default: return; } info = (info_p)malloc( sizeof(info_t) ); if( !info ) { tf_error( "cannot allocate memory" ); tf_dofinish(); return; } info->object = object; info->name = strdup( acc_fetch_fullname(object) ); info->next = lxt.objectList; lxt.objectList = info; info->sequence = lxt.sequence; info->event = event; info->real = real; info->updateNext = 0; if( real ) { info->symbol = lxt2_wr_symbol_add( lxt.t, info->name, 0, 0, 0, flags ); } else if( event ) { info->symbol = lxt2_wr_symbol_add( lxt.t, info->name, 0, 0, 0, flags ); } else { acc_fetch_range( object, &msb, &lsb ); #if DEBUG io_printf( "lxt2_add: %s [ %d : %d ]\n", info->name, msb, lsb ); #endif info->symbol = lxt2_wr_symbol_add( lxt.t, info->name, 0, msb, lsb, flags ); } acc_vcl_add( object, lxt2_changed, (char*)info, vcl_verilog_logic ); #if DEBUG io_printf( "lxt2_recordvars: adding %p %s\n", info->symbol, info->name ); #endif }