mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Fix cache of boundary vertices in Dfg cycle breaking (#8308)
This commit is contained in:
@@ -300,6 +300,7 @@ Seth Pellegrino
|
||||
Shashvat Prabhu
|
||||
Shogo Yamazaki
|
||||
Shou-Li Hsu
|
||||
Shriyans Sahoo
|
||||
spomatasmd
|
||||
Srinivasan Venkataramanan
|
||||
Stefan Wallentowitz
|
||||
|
||||
+36
-24
@@ -199,6 +199,8 @@ class TraceDriver final : public DfgVisitor {
|
||||
DfgVertex* m_splicep = nullptr; // The splice vertex being traced, just for assertions
|
||||
// Result cache for reusing already traced vertices
|
||||
std::unordered_map<CacheKey, DfgVertex*, CacheKey::Hash, CacheKey::Equal> m_cache;
|
||||
// Cache for boundary vertices (where m_sccInfo.get(*vtxp) != m_component)
|
||||
std::unordered_map<CacheKey, DfgVertex*, CacheKey::Hash, CacheKey::Equal> m_boundaryCache;
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
std::ofstream m_lineCoverageFile; // Line coverage file, just for testing
|
||||
@@ -269,8 +271,40 @@ class TraceDriver final : public DfgVisitor {
|
||||
UASSERT_OBJ(vtxp->size() > msb, vtxp, "Traced Vertex too narrow");
|
||||
UASSERT_OBJ(!m_defaultp || vtxp == m_splicep, vtxp, "Tracing wrong vertex");
|
||||
|
||||
// Get the cache entry, which is the resulting driver that is not part of
|
||||
// the same component as vtxp
|
||||
// If the currently traced vertex is in a different component,
|
||||
// then we found what we were looking for. But if it's a splice
|
||||
// with a corresponding default, we need to keep going as the
|
||||
// splice does not fully define the value we are seeking.
|
||||
if (m_sccInfo.get(*vtxp) != m_component && !m_defaultp) {
|
||||
DfgVertex*& respr
|
||||
= m_boundaryCache
|
||||
.emplace(std::piecewise_construct, std::forward_as_tuple(vtxp, msb, lsb),
|
||||
std::forward_as_tuple(nullptr))
|
||||
.first->second;
|
||||
if (!respr) {
|
||||
respr = vtxp;
|
||||
// If the result is a splice, we need to insert a temporary for it
|
||||
// as a splice cannot be fed into arbitray logic
|
||||
if (DfgVertexSplice* const splicep = respr->cast<DfgVertexSplice>()) {
|
||||
DfgVertexVar* const tmpp = createTmp("TraceDriver", splicep);
|
||||
// Note: we can't do 'splicep->replaceWith(tmpp)', as other
|
||||
// variable sinks of the splice might have a defaultp driver.
|
||||
tmpp->srcp(splicep);
|
||||
respr = tmpp;
|
||||
}
|
||||
// Apply a Sel to extract the relevant bits if only a part is needed
|
||||
if (msb != respr->width() - 1 || lsb != 0) {
|
||||
DfgSel* const selp = make<DfgSel>(respr, msb - lsb + 1);
|
||||
selp->fromp(respr);
|
||||
selp->lsb(lsb);
|
||||
respr = selp;
|
||||
}
|
||||
}
|
||||
resp = respr;
|
||||
break;
|
||||
}
|
||||
|
||||
// Normal cache for intra-component traces
|
||||
DfgVertex*& respr = m_cache
|
||||
.emplace(std::piecewise_construct, //
|
||||
std::forward_as_tuple(vtxp, msb, lsb), //
|
||||
@@ -282,28 +316,6 @@ class TraceDriver final : public DfgVisitor {
|
||||
// If already traced this vtxp/msb/lsb, just use the result.
|
||||
// This is important to avoid combinatorial explosion when the
|
||||
// same sub-expression is needed multiple times.
|
||||
} else if (m_sccInfo.get(*vtxp) != m_component && !m_defaultp) {
|
||||
// If the currently traced vertex is in a different component,
|
||||
// then we found what we were looking for. But if it's a splice
|
||||
// with a corresponding default, we need to keep going as the
|
||||
// splice does not fully define the value we are seeking.
|
||||
respr = vtxp;
|
||||
// If the result is a splice, we need to insert a temporary for it
|
||||
// as a splice cannot be fed into arbitray logic
|
||||
if (DfgVertexSplice* const splicep = respr->cast<DfgVertexSplice>()) {
|
||||
DfgVertexVar* const tmpp = createTmp("TraceDriver", splicep);
|
||||
// Note: we can't do 'splicep->replaceWith(tmpp)', as other
|
||||
// variable sinks of the splice might have a defaultp driver.
|
||||
tmpp->srcp(splicep);
|
||||
respr = tmpp;
|
||||
}
|
||||
// Apply a Sel to extract the relevant bits if only a part is needed
|
||||
if (msb != respr->width() - 1 || lsb != 0) {
|
||||
DfgSel* const selp = make<DfgSel>(respr, msb - lsb + 1);
|
||||
selp->fromp(respr);
|
||||
selp->lsb(lsb);
|
||||
respr = selp;
|
||||
}
|
||||
} else {
|
||||
// Otherwise visit the vertex to trace it
|
||||
VL_RESTORER(m_msb);
|
||||
|
||||
Reference in New Issue
Block a user