Fix driver tracing of partially assigned variable (#6364) (#6378)

Fixes #6364
This commit is contained in:
Geza Lore 2025-09-04 15:02:33 +01:00 committed by GitHub
parent 7d3c58d21c
commit 63993436c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 15 deletions

View File

@ -131,12 +131,27 @@ class TraceDriver final : public DfgVisitor {
}
}
// Create temporary capable of holding the result of 'vtxp'
DfgVertexVar* createTmp(const char* prefix, DfgVertex* vtxp) {
AstNode* nodep = m_dfg.modulep();
if (!nodep) nodep = v3Global.rootp();
const std::string name = m_dfg.makeUniqueName(prefix, nodep->user2Inc());
FileLine* const flp = vtxp->fileline();
AstNodeDType* const dtypep = vtxp->dtypep();
DfgVertex::ScopeCache scopeCache;
AstScope* const scopep = m_dfg.modulep() ? nullptr : vtxp->scopep(scopeCache);
DfgVertexVar* const varp = m_dfg.makeNewVar(flp, name, dtypep, scopep);
varp->varp()->isInternal(true);
varp->tmpForp(varp->nodep());
return varp;
}
// Continue tracing drivers of the given vertex, at the given LSB. Every
// visitor should call this to continue the traversal, then immediately
// return after the call. 'visit' methods should not call 'iterate', call
// this method instead, which checks for cycles.
DfgVertex* trace(DfgVertex* const vtxp, const uint32_t msb, const uint32_t lsb) {
UASSERT_OBJ(!vtxp->is<DfgVarArray>(), vtxp, "Cannot trace array variables");
UASSERT_OBJ(!vtxp->isArray(), vtxp, "Cannot trace array type vertices");
UASSERT_OBJ(vtxp->width() > msb, vtxp, "Traced Vertex too narrow");
// Push to stack
@ -163,22 +178,24 @@ class TraceDriver final : public DfgVisitor {
// Trace the vertex
onStackr = true;
// If the currently traced vertex is in a different component, then we
// found what we were looking for. However, keep going past a splice,
// or a unit as they cannot be use directly (they must always feed into
// a variable, so we can't make them drive arbitrary logic)
if (m_vtx2Scc[vtxp] != m_component //
&& !vtxp->is<DfgVertexSplice>() //
&& !vtxp->is<DfgUnitArray>()) {
if (msb != vtxp->width() - 1 || lsb != 0) {
// Apply a Sel to extract the relevant bits if only a part is needed
DfgSel* const selp = make<DfgSel>(vtxp, msb - lsb + 1);
selp->fromp(vtxp);
// If the currently traced vertex is in a different component,
// then we found what we were looking for.
if (m_vtx2Scc[vtxp] != m_component) {
m_resp = 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 = m_resp->cast<DfgVertexSplice>()) {
DfgVertexVar* const tmpp = createTmp("TraceDriver", splicep);
splicep->replaceWith(tmpp);
tmpp->srcp(splicep);
m_resp = tmpp;
}
// Apply a Sel to extract the relevant bits if only a part is needed
if (msb != m_resp->width() - 1 || lsb != 0) {
DfgSel* const selp = make<DfgSel>(m_resp, msb - lsb + 1);
selp->fromp(m_resp);
selp->lsb(lsb);
m_resp = selp;
} else {
// Otherwise just return the vertex
m_resp = vtxp;
}
} else {
// Otherwise visit the vertex
@ -1290,6 +1307,9 @@ V3DfgPasses::breakCycles(const DfgGraph& dfg, V3DfgContext& ctx) {
return {nullptr, false};
}
// AstNetlist/AstNodeModule user2 used as sequence numbers for temporaries
const VNUser2InUse user2InUse;
// Show input for debugging
dump(7, dfg, "input");

View File

@ -227,4 +227,26 @@ module t (
`signal(ALWAYS_2, 4); // UNOPTFLAT
assign ALWAYS_2 = always_2;
// verilator lint_on ALWCOMBORDER
logic [31:0] array_4[3]; // UNOPTFLAT
// Input
assign array_4[0] = rand_a[31:0];
// Sums 1
assign array_4[1][ 0 +: 3] = array_4[0][ 2 +: 2] + array_4[0][ 0 +: 2];
assign array_4[1][ 3 +: 3] = array_4[0][ 6 +: 2] + array_4[0][ 4 +: 2];
assign array_4[1][ 6 +: 3] = array_4[0][10 +: 2] + array_4[0][ 8 +: 2];
assign array_4[1][ 9 +: 3] = array_4[0][14 +: 2] + array_4[0][12 +: 2];
assign array_4[1][12 +: 3] = array_4[0][18 +: 2] + array_4[0][16 +: 2];
assign array_4[1][15 +: 3] = array_4[0][22 +: 2] + array_4[0][20 +: 2];
assign array_4[1][18 +: 3] = array_4[0][26 +: 2] + array_4[0][24 +: 2];
assign array_4[1][21 +: 3] = array_4[0][30 +: 2] + array_4[0][28 +: 2];
// Sums 2
assign array_4[2][ 0 +: 4] = array_4[1][ 3 +: 3] + array_4[1][ 0 +: 3];
assign array_4[2][ 4 +: 4] = array_4[1][ 9 +: 3] + array_4[1][ 6 +: 3];
assign array_4[2][ 8 +: 4] = array_4[1][15 +: 3] + array_4[1][12 +: 3];
assign array_4[2][12 +: 4] = array_4[1][21 +: 3] + array_4[1][18 +: 3];
// Outupt
`signal(ARRAY_4, 32);
assign ARRAY_4 = array_4[2];
endmodule