Avoid double traversal of maps
The typical find/if-not-exists-insert pattern can be achieved with 1 lookup instead of 2 using emplace with a sentinel value. Also maps value initialize their values when inserted with the [] operator, this is defined and so there is no need to explicitly insert zeroes for integer values.
This commit is contained in:
parent
30318a6654
commit
d60f180f43
|
|
@ -1178,13 +1178,10 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd,
|
|||
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
||||
const VBasicTypeKey key{nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(),
|
||||
nodep->nrange()};
|
||||
DetailedMap& mapr = m_detailedMap;
|
||||
const auto it = mapr.find(key);
|
||||
if (it != mapr.end()) return it->second;
|
||||
mapr.emplace(key, nodep);
|
||||
nodep->generic(true);
|
||||
auto pair = m_detailedMap.emplace(key, nodep);
|
||||
if (pair.second) nodep->generic(true);
|
||||
// No addTypesp; the upper function that called new() is responsible for adding
|
||||
return nodep;
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
AstConstPool::AstConstPool(FileLine* fl)
|
||||
|
|
@ -1641,13 +1638,13 @@ void AstInitArray::cloneRelink() {
|
|||
}
|
||||
}
|
||||
void AstInitArray::addIndexValuep(uint64_t index, AstNodeExpr* newp) {
|
||||
const auto it = m_map.find(index);
|
||||
if (it != m_map.end()) {
|
||||
it->second->valuep(newp);
|
||||
} else {
|
||||
const auto pair = m_map.emplace(index, nullptr);
|
||||
if (pair.second) {
|
||||
AstInitItem* const itemp = new AstInitItem{fileline(), newp};
|
||||
m_map.emplace(index, itemp);
|
||||
pair.first->second = itemp;
|
||||
addInitsp(itemp);
|
||||
} else {
|
||||
pair.first->second->valuep(newp);
|
||||
}
|
||||
}
|
||||
AstNodeExpr* AstInitArray::getIndexValuep(uint64_t index) const {
|
||||
|
|
|
|||
|
|
@ -400,12 +400,10 @@ public:
|
|||
|
||||
bool getEntryMatch(const V3ConfigScopeTraceEntry* entp, const string& scopepart) {
|
||||
// Return if a entry matches the scopepart, with memoization
|
||||
const auto& key = V3ConfigScopeTraceEntryMatch{entp, scopepart};
|
||||
const auto& it = m_matchCache.find(key);
|
||||
if (it != m_matchCache.end()) return it->second; // Cached
|
||||
const bool matched = VString::wildmatch(scopepart, entp->m_scope);
|
||||
m_matchCache.emplace(key, matched);
|
||||
return matched;
|
||||
const V3ConfigScopeTraceEntryMatch key{entp, scopepart};
|
||||
const auto pair = m_matchCache.emplace(key, false);
|
||||
if (pair.second) pair.first->second = VString::wildmatch(scopepart, entp->m_scope);
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
bool getScopeTraceOn(const string& scope) {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ private:
|
|||
CheckState m_state; // State save-restored on each new coverage scope/block
|
||||
AstNodeModule* m_modp = nullptr; // Current module to add statement to
|
||||
bool m_inToggleOff = false; // In function/task etc
|
||||
std::unordered_map<std::string, int> m_varnames; // Uniquification of inserted variable names
|
||||
// Uniquification of inserted variable names
|
||||
std::unordered_map<std::string, uint32_t> m_varnames;
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
std::unordered_map<int, LinenoSet>
|
||||
m_handleLines; // All line numbers for a given m_stateHandle
|
||||
|
|
@ -141,13 +142,7 @@ private:
|
|||
string traceNameForLine(AstNode* nodep, const string& type) {
|
||||
string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
|
||||
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type;
|
||||
const auto it = m_varnames.find(name);
|
||||
if (it == m_varnames.end()) {
|
||||
m_varnames.emplace(name, 1);
|
||||
} else {
|
||||
const int suffix = (it->second)++;
|
||||
name += "_" + cvtToStr(suffix);
|
||||
}
|
||||
if (const uint32_t suffix = m_varnames[name]++) name += "_" + cvtToStr(suffix);
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,30 +145,26 @@ private:
|
|||
int width /*0==fromoldvar*/, AstNodeDType* newdtypep) {
|
||||
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
|
||||
UASSERT_OBJ(oldvarscp->scopep(), oldvarscp, "Var unscoped");
|
||||
AstVar* varp;
|
||||
FileLine* const flp = oldvarscp->fileline();
|
||||
AstNodeModule* const addmodp = oldvarscp->scopep()->modp();
|
||||
// We need a new AstVar, but only one for all scopes, to match the new AstVarScope
|
||||
const auto it = m_modVarMap.find(std::make_pair(addmodp, name));
|
||||
if (it != m_modVarMap.end()) {
|
||||
// Created module's AstVar earlier under some other scope
|
||||
varp = it->second;
|
||||
} else {
|
||||
const auto pair = m_modVarMap.emplace(std::make_pair(addmodp, name), nullptr);
|
||||
if (pair.second) {
|
||||
AstVar* varp = nullptr;
|
||||
if (newdtypep) {
|
||||
varp = new AstVar{oldvarscp->fileline(), VVarType::BLOCKTEMP, name, newdtypep};
|
||||
varp = new AstVar{flp, VVarType::BLOCKTEMP, name, newdtypep};
|
||||
} else if (width == 0) {
|
||||
varp = new AstVar{oldvarscp->fileline(), VVarType::BLOCKTEMP, name,
|
||||
oldvarscp->varp()};
|
||||
varp = new AstVar{flp, VVarType::BLOCKTEMP, name, oldvarscp->varp()};
|
||||
varp->dtypeFrom(oldvarscp);
|
||||
} else { // Used for vset and dimensions, so can zero init
|
||||
varp = new AstVar{oldvarscp->fileline(), VVarType::BLOCKTEMP, name,
|
||||
VFlagBitPacked{}, width};
|
||||
varp = new AstVar{flp, VVarType::BLOCKTEMP, name, VFlagBitPacked{}, width};
|
||||
}
|
||||
addmodp->addStmtsp(varp);
|
||||
m_modVarMap.emplace(std::make_pair(addmodp, name), varp);
|
||||
pair.first->second = varp;
|
||||
}
|
||||
AstVar* const varp = pair.first->second;
|
||||
|
||||
AstVarScope* const varscp
|
||||
= new AstVarScope{oldvarscp->fileline(), oldvarscp->scopep(), varp};
|
||||
AstVarScope* const varscp = new AstVarScope{flp, oldvarscp->scopep(), varp};
|
||||
oldvarscp->scopep()->addVarsp(varscp);
|
||||
return varscp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,13 +63,7 @@ void V3DupFinder::dumpFile(const string& filename, bool tree) {
|
|||
for (auto it = cbegin(); true; ++it) {
|
||||
if (it == cend() || lasthash != it->first) {
|
||||
if (it != cend()) lasthash = it->first;
|
||||
if (num_in_bucket) {
|
||||
if (dist.find(num_in_bucket) == dist.end()) {
|
||||
dist.emplace(num_in_bucket, 1);
|
||||
} else {
|
||||
++dist[num_in_bucket];
|
||||
}
|
||||
}
|
||||
if (num_in_bucket) ++dist[num_in_bucket];
|
||||
num_in_bucket = 0;
|
||||
}
|
||||
if (it == cend()) break;
|
||||
|
|
|
|||
|
|
@ -187,12 +187,9 @@ class EmitCSyms final : EmitCBaseVisitorConst {
|
|||
const auto scpit = m_vpiScopeCandidates.find(scopeSymString(scp));
|
||||
if ((scpit != m_vpiScopeCandidates.end())
|
||||
&& (m_scopeNames.find(scp) == m_scopeNames.end())) {
|
||||
const auto scopeNameit = m_scopeNames.find(scpit->second.m_symName);
|
||||
if (scopeNameit == m_scopeNames.end()) {
|
||||
m_scopeNames.emplace(scpit->second.m_symName, scpit->second);
|
||||
} else {
|
||||
scopeNameit->second.m_type = scpit->second.m_type;
|
||||
}
|
||||
// If not in m_scopeNames, add it, otherwise just update m_type
|
||||
const auto pair = m_scopeNames.emplace(scpit->second.m_symName, scpit->second);
|
||||
if (!pair.second) pair.first->second.m_type = scpit->second.m_type;
|
||||
}
|
||||
string::size_type pos = scp.rfind("__DOT__");
|
||||
if (pos == string::npos) {
|
||||
|
|
|
|||
|
|
@ -991,10 +991,8 @@ public:
|
|||
string protectIf(const string& old, bool doIt) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old;
|
||||
const V3LockGuard lock{m_mutex};
|
||||
const auto it = m_nameMap.find(old);
|
||||
if (it != m_nameMap.end()) {
|
||||
return it->second;
|
||||
} else {
|
||||
const auto pair = m_nameMap.emplace(old, "");
|
||||
if (pair.second) {
|
||||
string out;
|
||||
if (v3Global.opt.debugProtect()) {
|
||||
// This lets us see the symbol being protected to debug cases
|
||||
|
|
@ -1009,16 +1007,15 @@ public:
|
|||
// See if we can shrink the digest symbol to something smaller
|
||||
for (size_t len = 6; len < out.size() - 3; len += 3) {
|
||||
const string tryout = out.substr(0, len);
|
||||
if (m_newIdSet.find(tryout) == m_newIdSet.end()) {
|
||||
if (m_newIdSet.insert(tryout).second) {
|
||||
out = tryout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_nameMap.emplace(old, out);
|
||||
m_newIdSet.insert(out);
|
||||
return out;
|
||||
pair.first->second = out;
|
||||
}
|
||||
return pair.first->second;
|
||||
}
|
||||
string protectWordsIf(const string& old, bool doIt) VL_MT_SAFE {
|
||||
// Split at " " (for traces), "." (for scopes), "->", "(", "&", ")" (for self pointers)
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool
|
|||
}
|
||||
|
||||
const std::string& V3Global::ptrToId(const void* p) {
|
||||
auto it = m_ptrToId.find(p);
|
||||
if (it == m_ptrToId.end()) {
|
||||
const auto pair = m_ptrToId.emplace(p, "");
|
||||
if (pair.second) {
|
||||
std::ostringstream os;
|
||||
if (p) {
|
||||
os << "(";
|
||||
|
|
@ -125,7 +125,7 @@ const std::string& V3Global::ptrToId(const void* p) {
|
|||
} else {
|
||||
os << "0";
|
||||
}
|
||||
it = m_ptrToId.emplace(p, os.str()).first;
|
||||
pair.first->second = os.str();
|
||||
}
|
||||
return it->second;
|
||||
return pair.first->second;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,12 +306,12 @@ public:
|
|||
//######################################################################
|
||||
|
||||
void V3HierBlockPlan::add(const AstNodeModule* modp, const std::vector<AstVar*>& gparams) {
|
||||
const iterator it = m_blocks.find(modp);
|
||||
if (it == m_blocks.end()) {
|
||||
const auto pair = m_blocks.emplace(modp, nullptr);
|
||||
if (pair.second) {
|
||||
V3HierBlock* hblockp = new V3HierBlock{modp, gparams};
|
||||
UINFO(3, "Add " << modp->prettyNameQ() << " with " << gparams.size() << " parameters"
|
||||
<< std::endl);
|
||||
m_blocks.emplace(modp, hblockp);
|
||||
pair.first->second = hblockp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,31 +157,27 @@ public:
|
|||
// Do we have a old assignment we can nuke?
|
||||
UINFO(4, " ASSIGNof: " << nodep << endl);
|
||||
UINFO(7, " new: " << assp << endl);
|
||||
const auto it = m_map.find(nodep);
|
||||
if (it != m_map.end()) {
|
||||
checkRemoveAssign(it);
|
||||
it->second.simpleAssign(assp);
|
||||
} else {
|
||||
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::SIMPLEASSIGN{}, assp});
|
||||
const auto pair = m_map.emplace(std::piecewise_construct, //
|
||||
std::forward_as_tuple(nodep),
|
||||
std::forward_as_tuple(LifeVarEntry::SIMPLEASSIGN{}, assp));
|
||||
if (!pair.second) {
|
||||
checkRemoveAssign(pair.first);
|
||||
pair.first->second.simpleAssign(assp);
|
||||
}
|
||||
// lifeDump();
|
||||
}
|
||||
void complexAssign(AstVarScope* nodep) {
|
||||
UINFO(4, " clearof: " << nodep << endl);
|
||||
const auto it = m_map.find(nodep);
|
||||
if (it != m_map.end()) {
|
||||
it->second.complexAssign();
|
||||
} else {
|
||||
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}});
|
||||
}
|
||||
const auto pair = m_map.emplace(nodep, LifeVarEntry::COMPLEXASSIGN{});
|
||||
if (!pair.second) pair.first->second.complexAssign();
|
||||
}
|
||||
void clearReplaced() { m_replacedVref = false; }
|
||||
bool replaced() const { return m_replacedVref; }
|
||||
void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) {
|
||||
// Variable rvalue. If it references a constant, we can replace it
|
||||
const auto it = m_map.find(nodep);
|
||||
if (it != m_map.end()) {
|
||||
if (AstConst* const constp = it->second.constNodep()) {
|
||||
const auto pair = m_map.emplace(nodep, LifeVarEntry::CONSUMED{});
|
||||
if (!pair.second) {
|
||||
if (AstConst* const constp = pair.first->second.constNodep()) {
|
||||
if (!varrefp->varp()->isSigPublic() && !varrefp->varp()->isUsedVirtIface()) {
|
||||
// Aha, variable is constant; substitute in.
|
||||
// We'll later constant propagate
|
||||
|
|
@ -194,27 +190,19 @@ public:
|
|||
}
|
||||
}
|
||||
UINFO(4, " usage: " << nodep << endl);
|
||||
it->second.consumed();
|
||||
} else {
|
||||
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::CONSUMED{}});
|
||||
pair.first->second.consumed();
|
||||
}
|
||||
}
|
||||
void complexAssignFind(AstVarScope* nodep) {
|
||||
const auto it = m_map.find(nodep);
|
||||
if (it != m_map.end()) {
|
||||
UINFO(4, " casfind: " << it->first << endl);
|
||||
it->second.complexAssign();
|
||||
} else {
|
||||
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}});
|
||||
const auto pair = m_map.emplace(nodep, LifeVarEntry::COMPLEXASSIGN{});
|
||||
if (!pair.second) {
|
||||
UINFO(4, " casfind: " << pair.first->first << endl);
|
||||
pair.first->second.complexAssign();
|
||||
}
|
||||
}
|
||||
void consumedFind(AstVarScope* nodep) {
|
||||
const auto it = m_map.find(nodep);
|
||||
if (it != m_map.end()) {
|
||||
it->second.consumed();
|
||||
} else {
|
||||
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::CONSUMED{}});
|
||||
}
|
||||
const auto pair = m_map.emplace(nodep, LifeVarEntry::CONSUMED{});
|
||||
if (!pair.second) pair.first->second.consumed();
|
||||
}
|
||||
void lifeToAbove() {
|
||||
// Any varrefs under a if/else branch affect statements outside and after the if/else
|
||||
|
|
|
|||
|
|
@ -195,22 +195,18 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
|||
for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||
if (AstVar* const oldvarp = VN_CAST(subnodep, Var)) {
|
||||
if (oldvarp->isIO()) {
|
||||
if (ioNames.find(oldvarp->name()) != ioNames.end()) {
|
||||
if (!ioNames.insert(oldvarp->name()).second) {
|
||||
// UINFO(8, "Multitop dup I/O found: " << oldvarp << endl);
|
||||
dupNames.insert(oldvarp->name());
|
||||
} else {
|
||||
ioNames.insert(oldvarp->name());
|
||||
}
|
||||
} else if (v3Global.opt.topIfacesSupported() && oldvarp->isIfaceRef()) {
|
||||
const AstNodeDType* const subtypep = oldvarp->subDTypep();
|
||||
if (VN_IS(subtypep, IfaceRefDType)) {
|
||||
const AstIfaceRefDType* const ifacerefp = VN_AS(subtypep, IfaceRefDType);
|
||||
if (!ifacerefp->cellp()) {
|
||||
if (ioNames.find(oldvarp->name()) != ioNames.end()) {
|
||||
if (!ioNames.insert(oldvarp->name()).second) {
|
||||
// UINFO(8, "Multitop dup interface found: " << oldvarp << endl);
|
||||
dupNames.insert(oldvarp->name());
|
||||
} else {
|
||||
ioNames.insert(oldvarp->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -221,12 +217,10 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
|
|||
const AstIfaceRefDType* const ifacerefp
|
||||
= VN_AS(arrsubtypep, IfaceRefDType);
|
||||
if (!ifacerefp->cellp()) {
|
||||
if (ioNames.find(oldvarp->name()) != ioNames.end()) {
|
||||
if (!ioNames.insert(oldvarp->name()).second) {
|
||||
// UINFO(8, "Multitop dup interface array found: " << oldvarp
|
||||
// << endl);
|
||||
dupNames.insert(oldvarp->name());
|
||||
} else {
|
||||
ioNames.insert(oldvarp->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -495,14 +495,9 @@ public:
|
|||
V3List<OrderMoveVertex*>& readyVertices() { return m_readyVertices; }
|
||||
static OrderMoveDomScope* findCreate(const AstSenTree* domainp, const AstScope* scopep) {
|
||||
const DomScopeKey key = std::make_pair(domainp, scopep);
|
||||
const auto iter = s_dsMap.find(key);
|
||||
if (iter != s_dsMap.end()) {
|
||||
return iter->second;
|
||||
} else {
|
||||
OrderMoveDomScope* domScopep = new OrderMoveDomScope{domainp, scopep};
|
||||
s_dsMap.emplace(key, domScopep);
|
||||
return domScopep;
|
||||
}
|
||||
const auto pair = s_dsMap.emplace(key, nullptr);
|
||||
if (pair.second) pair.first->second = new OrderMoveDomScope{domainp, scopep};
|
||||
return pair.first->second;
|
||||
}
|
||||
string name() const {
|
||||
return string{"MDS:"} + " d=" + cvtToHex(domainp()) + " s=" + cvtToHex(scopep());
|
||||
|
|
|
|||
|
|
@ -356,27 +356,22 @@ class ParamProcessor final {
|
|||
// cppcheck-has-bug-suppress unreadVariable
|
||||
if (VL_UNLIKELY(v3Global.opt.debugCollision())) hash = V3Hash{paramStr};
|
||||
int num;
|
||||
const auto it = m_valueMap.find(hash);
|
||||
if (it != m_valueMap.end()) {
|
||||
num = it->second;
|
||||
} else {
|
||||
num = m_nextValue++;
|
||||
m_valueMap[hash] = num;
|
||||
}
|
||||
const auto pair = m_valueMap.emplace(hash, 0);
|
||||
if (pair.second) pair.first->second = m_nextValue++;
|
||||
num = pair.first->second;
|
||||
return std::string{"z"} + cvtToStr(num);
|
||||
}
|
||||
string moduleCalcName(const AstNodeModule* srcModp, const string& longname) {
|
||||
string newname = longname;
|
||||
if (longname.length() > 30) {
|
||||
const auto iter = m_longMap.find(longname);
|
||||
if (iter != m_longMap.end()) {
|
||||
newname = iter->second;
|
||||
} else {
|
||||
const auto pair = m_longMap.emplace(longname, "");
|
||||
if (pair.second) {
|
||||
newname = srcModp->name();
|
||||
// We use all upper case above, so lower here can't conflict
|
||||
newname += "__pi" + cvtToStr(++m_longId);
|
||||
m_longMap.emplace(longname, newname);
|
||||
pair.first->second = newname;
|
||||
}
|
||||
newname = pair.first->second;
|
||||
}
|
||||
UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl);
|
||||
return newname;
|
||||
|
|
@ -496,8 +491,9 @@ class ParamProcessor final {
|
|||
}
|
||||
}
|
||||
|
||||
auto paramsIt = m_defaultParameterValues.find(modp);
|
||||
if (paramsIt == m_defaultParameterValues.end()) { // Not cached yet, so check parameters
|
||||
const auto pair = m_defaultParameterValues.emplace(
|
||||
std::piecewise_construct, std::forward_as_tuple(modp), std::forward_as_tuple());
|
||||
if (pair.second) { // Not cached yet, so check parameters
|
||||
// Using map with key=string so that we can scan it in deterministic order
|
||||
DefaultValueMap params;
|
||||
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
|
|
@ -511,8 +507,9 @@ class ParamProcessor final {
|
|||
}
|
||||
}
|
||||
}
|
||||
paramsIt = m_defaultParameterValues.emplace(modp, std::move(params)).first;
|
||||
pair.first->second = std::move(params);
|
||||
}
|
||||
const auto paramsIt = pair.first;
|
||||
if (paramsIt->second.empty()) return modp->name(); // modp has no parameter
|
||||
|
||||
string longname = modp->name();
|
||||
|
|
|
|||
|
|
@ -93,10 +93,9 @@ public:
|
|||
PartPtrIdMap() = default;
|
||||
// METHODS
|
||||
uint64_t findId(const void* ptrp) const {
|
||||
const auto it = m_id.find(ptrp);
|
||||
if (it != m_id.end()) return it->second;
|
||||
m_id[ptrp] = m_nextId;
|
||||
return m_nextId++;
|
||||
const auto pair = m_id.emplace(ptrp, m_nextId);
|
||||
if (pair.second) ++m_nextId;
|
||||
return pair.first->second;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -178,12 +178,13 @@ private:
|
|||
const std::string type = AstCDType::typeToHold(items);
|
||||
const std::string name = "VlRandC<" + type + ", " + cvtToStr(items) + "ULL>";
|
||||
// Create or reuse (to avoid duplicates) randomization object dtype
|
||||
auto it = m_randcDtypes.find(name);
|
||||
if (it != m_randcDtypes.end()) return it->second;
|
||||
AstCDType* newp = new AstCDType{fl, name};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(newp);
|
||||
m_randcDtypes.emplace(name, newp);
|
||||
return newp;
|
||||
const auto pair = m_randcDtypes.emplace(name, nullptr);
|
||||
if (pair.second) {
|
||||
AstCDType* newp = new AstCDType{fl, name};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(newp);
|
||||
pair.first->second = newp;
|
||||
}
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
AstVar* newRandcVarsp(AstVar* varp) {
|
||||
|
|
|
|||
|
|
@ -155,10 +155,9 @@ class SchedGraphBuilder final : public VNVisitor {
|
|||
// rst), so we use a hash map to get the unique SchedSenVertex. (Note: This creates
|
||||
// separate vertices for ET_CHANGED and ET_HYBRID over the same expression, but that is
|
||||
// OK for now).
|
||||
auto it = m_senVertices.find(*senItemp);
|
||||
|
||||
const auto pair = m_senVertices.emplace(*senItemp, nullptr);
|
||||
// If it does not exist, create it
|
||||
if (it == m_senVertices.end()) {
|
||||
if (pair.second) {
|
||||
// Create the vertex
|
||||
SchedSenVertex* const vtxp = new SchedSenVertex{m_graphp, senItemp};
|
||||
|
||||
|
|
@ -168,11 +167,11 @@ class SchedGraphBuilder final : public VNVisitor {
|
|||
});
|
||||
|
||||
// Store back to hash map so we can find it next time
|
||||
it = m_senVertices.emplace(*senItemp, vtxp).first;
|
||||
pair.first->second = vtxp;
|
||||
}
|
||||
|
||||
// Cache sensitivity vertex
|
||||
senItemp->user1p(it->second);
|
||||
senItemp->user1p(pair.first->second);
|
||||
}
|
||||
return senItemp->user1u().to<SchedSenVertex*>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ class SenExprBuilder final {
|
|||
AstNode* scopeExprp = exprp;
|
||||
if (AstVarRef* const refp = VN_CAST(exprp, VarRef)) scopeExprp = refp->varScopep();
|
||||
// Create the 'previous value' variable
|
||||
auto it = m_prev.find(*scopeExprp);
|
||||
if (it == m_prev.end()) {
|
||||
const auto pair = m_prev.emplace(*scopeExprp, nullptr);
|
||||
if (pair.second) {
|
||||
AstVarScope* prevp;
|
||||
if (m_scopep->isTop()) {
|
||||
// For readability, use the scoped signal name if the trigger is a simple AstVarRef
|
||||
|
|
@ -118,7 +118,7 @@ class SenExprBuilder final {
|
|||
prevp = new AstVarScope{flp, m_scopep, varp};
|
||||
m_scopep->addVarsp(prevp);
|
||||
}
|
||||
it = m_prev.emplace(*scopeExprp, prevp).first;
|
||||
pair.first->second = prevp;
|
||||
|
||||
// Add the initializer init
|
||||
AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE},
|
||||
|
|
@ -126,7 +126,7 @@ class SenExprBuilder final {
|
|||
m_inits.push_back(initp);
|
||||
}
|
||||
|
||||
AstVarScope* const prevp = it->second;
|
||||
AstVarScope* const prevp = pair.first->second;
|
||||
|
||||
const auto wrPrev = [=]() { return new AstVarRef{flp, prevp, VAccess::WRITE}; };
|
||||
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ private:
|
|||
UASSERT_OBJ(varp->attrSplitVar(), varp, " no split_var metacomment");
|
||||
const MapIt it = m_map.find(varp);
|
||||
if (it == m_map.end()) return false; // Not registered
|
||||
const bool ok = m_map[varp].insert(ref).second;
|
||||
const bool ok = it->second.insert(ref).second;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,12 +71,10 @@ public:
|
|||
if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix;
|
||||
os << " n=" << nodep();
|
||||
os << '\n';
|
||||
if (VL_UNCOVERABLE(doneSymsr.find(this) != doneSymsr.end())) {
|
||||
if (VL_UNCOVERABLE(!doneSymsr.insert(this).second)) {
|
||||
os << indent << "| ^ duplicate, so no children printed\n"; // LCOV_EXCL_LINE
|
||||
} else {
|
||||
doneSymsr.insert(this);
|
||||
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end();
|
||||
++it) {
|
||||
for (auto it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||
if (numLevels >= 1) {
|
||||
it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1,
|
||||
it->first);
|
||||
|
|
|
|||
|
|
@ -85,10 +85,8 @@ public:
|
|||
|
||||
// METHODS
|
||||
void addVertex(const T_Key& key) {
|
||||
const auto itr = m_vertices.find(key);
|
||||
UASSERT(itr == m_vertices.end(), "Vertex already exists with same key");
|
||||
Vertex* v = new Vertex{this, key};
|
||||
m_vertices[key] = v;
|
||||
const bool newEntry = m_vertices.emplace(key, new Vertex{this, key}).second;
|
||||
UASSERT(newEntry, "Vertex already exists with same key");
|
||||
}
|
||||
|
||||
// For purposes of TSP, we are using non-directional graphs.
|
||||
|
|
|
|||
|
|
@ -971,19 +971,21 @@ private:
|
|||
// Only create one DPI Import prototype or DPI Export entry point for each unique cname as
|
||||
// it is illegal for the user to attach multiple tasks with different signatures to one DPI
|
||||
// cname.
|
||||
const auto it = m_dpiNames.find(nodep->cname());
|
||||
if (it == m_dpiNames.end()) {
|
||||
const auto pair = m_dpiNames.emplace(std::piecewise_construct, //
|
||||
std::forward_as_tuple(nodep->cname()),
|
||||
std::forward_as_tuple(nodep, signature, nullptr));
|
||||
if (pair.second) {
|
||||
// First time encountering this cname. Create Import prototype / Export entry point
|
||||
AstCFunc* const funcp = nodep->dpiExport() ? makeDpiExportDispatcher(nodep, rtnvarp)
|
||||
: makeDpiImportPrototype(nodep, rtnvarp);
|
||||
m_dpiNames.emplace(nodep->cname(), std::make_tuple(nodep, signature, funcp));
|
||||
std::get<2>(pair.first->second) = funcp;
|
||||
return funcp;
|
||||
} else {
|
||||
// Seen this cname import before. Check if it's the same prototype.
|
||||
const AstNodeFTask* firstNodep;
|
||||
string firstSignature;
|
||||
AstCFunc* firstFuncp;
|
||||
std::tie(firstNodep, firstSignature, firstFuncp) = it->second;
|
||||
std::tie(firstNodep, firstSignature, firstFuncp) = pair.first->second;
|
||||
if (signature != firstSignature) {
|
||||
// Different signature, so error.
|
||||
nodep->v3error("Duplicate declaration of DPI function with different signature: '"
|
||||
|
|
@ -1779,16 +1781,13 @@ void V3Task::taskConnectWrap(AstNodeFTaskRef* nodep, const V3TaskConnects& tconn
|
|||
// Make wrapper name such that is same iff same args are defaulted
|
||||
std::string newname = nodep->name() + "__Vtcwrap";
|
||||
for (const AstVar* varp : argWrap) newname += "_" + cvtToStr(varp->pinNum());
|
||||
const auto namekey = std::make_pair(nodep->taskp(), newname);
|
||||
auto& wrapMapr = statep->wrapMap();
|
||||
const auto it = wrapMapr.find(namekey);
|
||||
AstNodeFTask* newTaskp;
|
||||
if (it != wrapMapr.end()) {
|
||||
newTaskp = it->second;
|
||||
} else {
|
||||
newTaskp = taskConnectWrapNew(nodep->taskp(), newname, tconnects, argWrap);
|
||||
wrapMapr.emplace(namekey, newTaskp);
|
||||
const auto pair = statep->wrapMap().emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(nodep->taskp(), newname),
|
||||
std::forward_as_tuple(nullptr));
|
||||
if (pair.second) {
|
||||
pair.first->second = taskConnectWrapNew(nodep->taskp(), newname, tconnects, argWrap);
|
||||
}
|
||||
AstNodeFTask* const newTaskp = pair.first->second;
|
||||
|
||||
// Remove the defaulted arguments from original outside call
|
||||
for (const auto& tconnect : tconnects) {
|
||||
|
|
|
|||
|
|
@ -549,16 +549,11 @@ class TristateVisitor final : public TristateBaseVisitor {
|
|||
}
|
||||
|
||||
void mapInsertLhsVarRef(AstVarRef* nodep) {
|
||||
AstVar* const key = nodep->varp();
|
||||
const auto it = m_lhsmap.find(key);
|
||||
UINFO(9, " mapInsertLhsVarRef " << nodep << endl);
|
||||
if (it == m_lhsmap.end()) { // Not found
|
||||
RefStrengthVec* const refsp = new RefStrengthVec;
|
||||
refsp->push_back(RefStrength{nodep, m_currentStrength});
|
||||
m_lhsmap.emplace(key, refsp);
|
||||
} else {
|
||||
it->second->push_back(RefStrength{nodep, m_currentStrength});
|
||||
}
|
||||
AstVar* const key = nodep->varp();
|
||||
const auto pair = m_lhsmap.emplace(key, nullptr);
|
||||
if (pair.second) pair.first->second = new RefStrengthVec;
|
||||
pair.first->second->push_back(RefStrength{nodep, m_currentStrength});
|
||||
}
|
||||
|
||||
AstNodeExpr* newEnableDeposit(AstSel* selp, AstNodeExpr* enp) {
|
||||
|
|
|
|||
234
src/V3Width.cpp
234
src/V3Width.cpp
|
|
@ -2296,15 +2296,14 @@ private:
|
|||
}
|
||||
num.opAssign(constp->num());
|
||||
// Look for duplicates
|
||||
if (inits.find(num) != inits.end()) { // IEEE says illegal
|
||||
const AstNode* const otherp = inits.find(num)->second;
|
||||
const auto pair = inits.emplace(num, itemp);
|
||||
if (!pair.second) { // IEEE says illegal
|
||||
const AstNode* const otherp = pair.first->second;
|
||||
itemp->v3error("Overlapping enumeration value: "
|
||||
<< itemp->prettyNameQ() << '\n'
|
||||
<< itemp->warnContextPrimary() << '\n'
|
||||
<< otherp->warnOther() << "... Location of original declaration\n"
|
||||
<< otherp->warnContextSecondary());
|
||||
} else {
|
||||
inits.emplace(num, itemp);
|
||||
}
|
||||
num.opAdd(one, constp->num());
|
||||
}
|
||||
|
|
@ -3985,12 +3984,10 @@ private:
|
|||
= VN_CAST(patp->keyp(), NodeDType)) {
|
||||
// data_type: default_value
|
||||
const string dtype = nodedtypep->dtypep()->prettyDTypeName();
|
||||
auto it = dtypemap.find(dtype);
|
||||
if (it == dtypemap.end()) {
|
||||
dtypemap.emplace(dtype, patp);
|
||||
} else {
|
||||
const auto pair = dtypemap.emplace(dtype, patp);
|
||||
if (!pair.second) {
|
||||
// Override stored default_value
|
||||
it->second = patp->cloneTree(false);
|
||||
pair.first->second = patp->cloneTree(false);
|
||||
}
|
||||
} else {
|
||||
// Undefined pattern
|
||||
|
|
@ -7192,30 +7189,33 @@ private:
|
|||
}
|
||||
AstVar* dimensionVarp(AstNodeDType* nodep, VAttrType attrType, uint32_t msbdim) {
|
||||
// Return a variable table which has specified dimension properties for this variable
|
||||
const auto pos = m_tableMap.find(std::make_pair(nodep, attrType));
|
||||
if (pos != m_tableMap.end()) return pos->second;
|
||||
AstNodeArrayDType* const vardtypep
|
||||
= new AstUnpackArrayDType{nodep->fileline(), nodep->findSigned32DType(),
|
||||
new AstRange(nodep->fileline(), msbdim, 0)};
|
||||
AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
|
||||
"__Vdimtab_" + VString::downcase(attrType.ascii())
|
||||
+ cvtToStr(m_dtTables++),
|
||||
vardtypep};
|
||||
varp->isConst(true);
|
||||
varp->isStatic(true);
|
||||
varp->valuep(initp);
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
|
||||
// Element 0 is a non-index and has speced values
|
||||
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0));
|
||||
for (unsigned i = 1; i < msbdim + 1; ++i) {
|
||||
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, i));
|
||||
const auto pair = m_tableMap.emplace(std::piecewise_construct, //
|
||||
std::forward_as_tuple(nodep, attrType),
|
||||
std::forward_as_tuple(nullptr));
|
||||
if (pair.second) {
|
||||
AstNodeArrayDType* const vardtypep
|
||||
= new AstUnpackArrayDType{nodep->fileline(), nodep->findSigned32DType(),
|
||||
new AstRange(nodep->fileline(), msbdim, 0)};
|
||||
AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
|
||||
"__Vdimtab_" + VString::downcase(attrType.ascii())
|
||||
+ cvtToStr(m_dtTables++),
|
||||
vardtypep};
|
||||
varp->isConst(true);
|
||||
varp->isStatic(true);
|
||||
varp->valuep(initp);
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
|
||||
// Element 0 is a non-index and has speced values
|
||||
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0));
|
||||
for (unsigned i = 1; i < msbdim + 1; ++i) {
|
||||
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, i));
|
||||
}
|
||||
userIterate(varp, nullptr); // May have already done $unit so must do this var
|
||||
pair.first->second = varp;
|
||||
}
|
||||
userIterate(varp, nullptr); // May have already done $unit so must do this var
|
||||
m_tableMap.emplace(std::make_pair(nodep, attrType), varp);
|
||||
return varp;
|
||||
return pair.first->second;
|
||||
}
|
||||
uint64_t enumMaxValue(const AstNode* errNodep, const AstEnumDType* adtypep) {
|
||||
// Most enums unless overridden are 32 bits, so we size array
|
||||
|
|
@ -7237,94 +7237,97 @@ private:
|
|||
}
|
||||
return maxval;
|
||||
}
|
||||
AstVar* enumVarp(AstEnumDType* nodep, VAttrType attrType, bool assoc, uint32_t msbdim) {
|
||||
AstVar* enumVarp(AstEnumDType* const nodep, VAttrType attrType, bool assoc, uint32_t msbdim) {
|
||||
// Return a variable table which has specified dimension properties for this variable
|
||||
const auto& tableMapr = nodep->tableMap();
|
||||
const auto pos = tableMapr.find(attrType);
|
||||
if (pos != tableMapr.end()) return pos->second;
|
||||
UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " assoc=" << assoc
|
||||
<< " max=" << msbdim << " for " << nodep << endl);
|
||||
AstNodeDType* basep;
|
||||
if (attrType == VAttrType::ENUM_NAME) {
|
||||
basep = nodep->findStringDType();
|
||||
} else if (attrType == VAttrType::ENUM_VALID) {
|
||||
// TODO in theory we could bit-pack the bits in the table, but
|
||||
// would require additional operations to extract, so only
|
||||
// would be worth it for larger tables which perhaps could be
|
||||
// better handled with equation generation?
|
||||
basep = nodep->findBitDType();
|
||||
} else {
|
||||
basep = nodep->dtypep();
|
||||
}
|
||||
AstNodeDType* vardtypep;
|
||||
if (assoc) {
|
||||
vardtypep = new AstAssocArrayDType{nodep->fileline(), basep, nodep};
|
||||
} else {
|
||||
vardtypep = new AstUnpackArrayDType{nodep->fileline(), basep,
|
||||
new AstRange(nodep->fileline(), msbdim, 0)};
|
||||
}
|
||||
AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
|
||||
"__Venumtab_" + VString::downcase(attrType.ascii())
|
||||
+ cvtToStr(m_dtTables++),
|
||||
vardtypep};
|
||||
varp->lifetime(VLifetime::STATIC);
|
||||
varp->isConst(true);
|
||||
varp->isStatic(true);
|
||||
varp->valuep(initp);
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
|
||||
const auto pair = nodep->tableMap().emplace(attrType, nullptr);
|
||||
if (pair.second) {
|
||||
UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " assoc=" << assoc
|
||||
<< " max=" << msbdim << " for " << nodep << endl);
|
||||
AstNodeDType* basep;
|
||||
if (attrType == VAttrType::ENUM_NAME) {
|
||||
basep = nodep->findStringDType();
|
||||
} else if (attrType == VAttrType::ENUM_VALID) {
|
||||
// TODO in theory we could bit-pack the bits in the table, but
|
||||
// would require additional operations to extract, so only
|
||||
// would be worth it for larger tables which perhaps could be
|
||||
// better handled with equation generation?
|
||||
basep = nodep->findBitDType();
|
||||
} else {
|
||||
basep = nodep->dtypep();
|
||||
}
|
||||
AstNodeDType* vardtypep;
|
||||
if (assoc) {
|
||||
vardtypep = new AstAssocArrayDType{nodep->fileline(), basep, nodep};
|
||||
} else {
|
||||
vardtypep = new AstUnpackArrayDType{nodep->fileline(), basep,
|
||||
new AstRange(nodep->fileline(), msbdim, 0)};
|
||||
}
|
||||
AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr};
|
||||
v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
|
||||
"__Venumtab_" + VString::downcase(attrType.ascii())
|
||||
+ cvtToStr(m_dtTables++),
|
||||
vardtypep};
|
||||
varp->lifetime(VLifetime::STATIC);
|
||||
varp->isConst(true);
|
||||
varp->isStatic(true);
|
||||
varp->valuep(initp);
|
||||
// Add to root, as don't know module we are in, and aids later structure sharing
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
|
||||
|
||||
// Default for all unspecified values
|
||||
if (attrType == VAttrType::ENUM_NAME) {
|
||||
initp->defaultp(new AstConst{nodep->fileline(), AstConst::String{}, ""});
|
||||
} else if (attrType == VAttrType::ENUM_NEXT || attrType == VAttrType::ENUM_PREV) {
|
||||
initp->defaultp(new AstConst{nodep->fileline(), V3Number{nodep, nodep->width(), 0}});
|
||||
} else if (attrType == VAttrType::ENUM_VALID) {
|
||||
initp->defaultp(new AstConst{nodep->fileline(), AstConst::BitFalse{}});
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
// Default for all unspecified values
|
||||
if (attrType == VAttrType::ENUM_NAME) {
|
||||
initp->defaultp(new AstConst{nodep->fileline(), AstConst::String{}, ""});
|
||||
} else if (attrType == VAttrType::ENUM_NEXT || attrType == VAttrType::ENUM_PREV) {
|
||||
initp->defaultp(
|
||||
new AstConst{nodep->fileline(), V3Number{nodep, nodep->width(), 0}});
|
||||
} else if (attrType == VAttrType::ENUM_VALID) {
|
||||
initp->defaultp(new AstConst{nodep->fileline(), AstConst::BitFalse{}});
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
|
||||
// Find valid values and populate
|
||||
UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items");
|
||||
std::map<uint64_t, AstNodeExpr*> values;
|
||||
{
|
||||
AstEnumItem* const firstp = nodep->itemsp();
|
||||
const AstEnumItem* prevp = firstp; // Prev must start with last item
|
||||
while (prevp->nextp()) prevp = VN_AS(prevp->nextp(), EnumItem);
|
||||
for (AstEnumItem* itemp = firstp; itemp;) {
|
||||
AstEnumItem* const nextp = VN_AS(itemp->nextp(), EnumItem);
|
||||
const AstConst* const vconstp = VN_AS(itemp->valuep(), Const);
|
||||
UASSERT_OBJ(vconstp, nodep, "Enum item without constified value");
|
||||
const uint64_t i = vconstp->toUQuad();
|
||||
if (attrType == VAttrType::ENUM_NAME) {
|
||||
values[i] = new AstConst{nodep->fileline(), AstConst::String{}, itemp->name()};
|
||||
} else if (attrType == VAttrType::ENUM_NEXT) {
|
||||
values[i] = (nextp ? nextp : firstp)->valuep()->cloneTree(false); // A const
|
||||
} else if (attrType == VAttrType::ENUM_PREV) {
|
||||
values[i] = prevp->valuep()->cloneTree(false); // A const
|
||||
} else if (attrType == VAttrType::ENUM_VALID) {
|
||||
values[i] = new AstConst{nodep->fileline(), AstConst::BitTrue{}};
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
// Find valid values and populate
|
||||
UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items");
|
||||
std::map<uint64_t, AstNodeExpr*> values;
|
||||
{
|
||||
AstEnumItem* const firstp = nodep->itemsp();
|
||||
const AstEnumItem* prevp = firstp; // Prev must start with last item
|
||||
while (prevp->nextp()) prevp = VN_AS(prevp->nextp(), EnumItem);
|
||||
for (AstEnumItem* itemp = firstp; itemp;) {
|
||||
AstEnumItem* const nextp = VN_AS(itemp->nextp(), EnumItem);
|
||||
const AstConst* const vconstp = VN_AS(itemp->valuep(), Const);
|
||||
UASSERT_OBJ(vconstp, nodep, "Enum item without constified value");
|
||||
const uint64_t i = vconstp->toUQuad();
|
||||
if (attrType == VAttrType::ENUM_NAME) {
|
||||
values[i]
|
||||
= new AstConst{nodep->fileline(), AstConst::String{}, itemp->name()};
|
||||
} else if (attrType == VAttrType::ENUM_NEXT) {
|
||||
values[i]
|
||||
= (nextp ? nextp : firstp)->valuep()->cloneTree(false); // A const
|
||||
} else if (attrType == VAttrType::ENUM_PREV) {
|
||||
values[i] = prevp->valuep()->cloneTree(false); // A const
|
||||
} else if (attrType == VAttrType::ENUM_VALID) {
|
||||
values[i] = new AstConst{nodep->fileline(), AstConst::BitTrue{}};
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
prevp = itemp;
|
||||
itemp = nextp;
|
||||
}
|
||||
prevp = itemp;
|
||||
itemp = nextp;
|
||||
}
|
||||
}
|
||||
// Add all specified values to table
|
||||
if (assoc) {
|
||||
for (const auto& itr : values) initp->addIndexValuep(itr.first, itr.second);
|
||||
} else {
|
||||
for (uint64_t i = 0; i < (msbdim + 1); ++i) {
|
||||
if (values[i]) initp->addIndexValuep(i, values[i]);
|
||||
// Add all specified values to table
|
||||
if (assoc) {
|
||||
for (const auto& itr : values) initp->addIndexValuep(itr.first, itr.second);
|
||||
} else {
|
||||
for (uint64_t i = 0; i < (msbdim + 1); ++i) {
|
||||
if (values[i]) initp->addIndexValuep(i, values[i]);
|
||||
}
|
||||
}
|
||||
userIterate(varp, nullptr); // May have already done $unit so must do this var
|
||||
pair.first->second = varp;
|
||||
}
|
||||
userIterate(varp, nullptr); // May have already done $unit so must do this var
|
||||
nodep->tableMap().emplace(attrType, varp);
|
||||
return varp;
|
||||
return pair.first->second;
|
||||
}
|
||||
|
||||
PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) {
|
||||
|
|
@ -7340,10 +7343,9 @@ private:
|
|||
<< patp->keyp()->prettyTypeName());
|
||||
}
|
||||
}
|
||||
if (patmap.find(element) != patmap.end()) {
|
||||
const bool newEntry = patmap.emplace(element, patp).second;
|
||||
if (!newEntry) {
|
||||
patp->v3error("Assignment pattern key used multiple times: " << element);
|
||||
} else {
|
||||
patmap.emplace(element, patp);
|
||||
}
|
||||
element += range.leftToRightInc();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,18 +139,10 @@ public:
|
|||
}
|
||||
VlcPoint& pointNumber(uint64_t num) { return m_points[num]; }
|
||||
uint64_t findAddPoint(const string& name, uint64_t count) {
|
||||
uint64_t pointnum;
|
||||
const auto iter = m_nameMap.find(name);
|
||||
if (iter != m_nameMap.end()) {
|
||||
pointnum = iter->second;
|
||||
m_points[pointnum].countInc(count);
|
||||
} else {
|
||||
pointnum = m_numPoints++;
|
||||
VlcPoint point{name, pointnum};
|
||||
point.countInc(count);
|
||||
m_points.push_back(point);
|
||||
m_nameMap.emplace(point.name(), point.pointNum());
|
||||
}
|
||||
const auto pair = m_nameMap.emplace(name, m_numPoints);
|
||||
if (pair.second) m_points.emplace_back(name, m_numPoints++);
|
||||
const uint64_t pointnum = pair.first->second;
|
||||
m_points[pointnum].countInc(count);
|
||||
return pointnum;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ private:
|
|||
using PointsSet = std::set<const VlcPoint*>;
|
||||
|
||||
// MEMBERS
|
||||
int m_lineno; ///< Line number
|
||||
const int m_lineno; ///< Line number
|
||||
uint64_t m_count = 0; ///< Count
|
||||
bool m_ok = false; ///< Coverage is above threshold
|
||||
PointsSet m_points; // Points on this line
|
||||
|
|
@ -94,9 +94,7 @@ public:
|
|||
|
||||
// METHODS
|
||||
void lineIncCount(int lineno, uint64_t count, bool ok, const VlcPoint* pointp) {
|
||||
auto lit = m_lines.find(lineno);
|
||||
if (lit == m_lines.end()) lit = m_lines.emplace(lineno, VlcSourceCount{lineno}).first;
|
||||
VlcSourceCount& sc = lit->second;
|
||||
VlcSourceCount& sc = m_lines.emplace(lineno, lineno).first->second;
|
||||
sc.incCount(count, ok);
|
||||
sc.insertPoint(pointp);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue