diff --git a/src/V3DfgBreakCycles.cpp b/src/V3DfgBreakCycles.cpp index b4e2f1cdb..4c429fb6c 100644 --- a/src/V3DfgBreakCycles.cpp +++ b/src/V3DfgBreakCycles.cpp @@ -496,6 +496,41 @@ class TraceDriver final : public DfgVisitor { } } + void visit(DfgExtendS* vtxp) override { + DfgVertex* const srcp = vtxp->srcp(); + const uint32_t sWidth = srcp->width(); + // If the traced bits are wholly in the input + if (sWidth > m_msb) { + SET_RESULT(trace(srcp, m_msb, m_lsb)); + return; + } + // If there is a single traced bit, wholly in the extension + if (m_lsb >= sWidth && m_msb == m_lsb) { + if (DfgVertex* const sp = trace(srcp, sWidth - 1, sWidth - 1)) SET_RESULT(sp); + return; + } + + // The rest need a real ExtendS + if (!m_aggressive) return; + + // If the traced bits are wholly in the extension + if (m_lsb >= sWidth) { + if (DfgVertex* const sp = trace(srcp, sWidth - 1, sWidth - 1)) { + DfgExtendS* const resp = make(vtxp, m_msb - m_lsb + 1); + resp->srcp(sp); + SET_RESULT(resp); + } + return; + } + // The traced bits span both sides + if (DfgVertex* const sp = trace(srcp, sWidth - 1, m_lsb)) { + DfgExtendS* const resp = make(vtxp, m_msb - m_lsb + 1); + resp->srcp(sp); + SET_RESULT(resp); + return; + } + } + void visit(DfgSel* vtxp) override { const uint32_t lsb = vtxp->lsb(); SET_RESULT(trace(vtxp->srcp(), m_msb + lsb, m_lsb + lsb)); @@ -834,6 +869,15 @@ class IndependentBits final : public DfgVisitor { m.opSetRange(sWidth, vtxp->width() - sWidth, '0'); } + void visit(DfgExtendS* vtxp) override { + const DfgVertex* const srcp = vtxp->srcp(); + const uint32_t sWidth = srcp->width(); + V3Number& s = MASK(srcp); + V3Number& m = MASK(vtxp); + m.opSelInto(s, 0, sWidth); + m.opSetRange(sWidth, vtxp->width() - sWidth, s.bitIs0(sWidth - 1) ? '0' : '1'); + } + void visit(DfgNot* vtxp) override { // MASK(vtxp) = MASK(vtxp->srcp()); } diff --git a/test_regress/t/t_dfg_break_cycles.v b/test_regress/t/t_dfg_break_cycles.v index 9aed4d9c1..70d4fad4d 100644 --- a/test_regress/t/t_dfg_break_cycles.v +++ b/test_regress/t/t_dfg_break_cycles.v @@ -59,12 +59,24 @@ module t ( assign SEL[1] = SEL[0]; assign SEL[2] = SEL[1]; - `signal(EXTEND, 8); // UNOPTFLAT - assign EXTEND[0] = rand_a[3]; - assign EXTEND[3:1] = 3'(EXTEND[0]); - assign EXTEND[4] = EXTEND[1]; - assign EXTEND[6:5] = EXTEND[2:1]; - assign EXTEND[7] = EXTEND[3]; + `signal(ZX, 8); // UNOPTFLAT + assign ZX[0] = rand_a[3]; + assign ZX[3:1] = 3'(ZX[0]); + assign ZX[4] = ZX[1]; + assign ZX[6:5] = ZX[2:1]; + assign ZX[7] = ZX[3]; + + `signal(SX_0, 5); // UNOPTFLAT + assign SX_0[0] = rand_a[3]; + assign SX_0[3:1] = 3'(signed'(SX_0[0])); + `signal(SX_1, 5); // UNOPTFLAT + assign SX_1 = 5'(signed'({rand_a[0], SX_1[1]})); + `signal(SX_2, 5); // UNOPTFLAT + assign SX_2 = 5'(signed'({rand_a[0], SX_2[2]})); + `signal(SX_3, 5); // UNOPTFLAT + assign SX_3 = 5'(signed'({rand_a[0], SX_3[3:2]})); + `signal(SX_4, 5); // UNOPTFLAT + assign SX_4 = 5'(signed'({rand_a[0], SX_4[4:3]})); `signal(NOT, 3); // UNOPTFLAT assign NOT = ~(rand_a[2:0] ^ 3'(NOT[2:1]));