From 2d89c458f602f578755dbe1d9694629d33d7afca Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 4 Feb 2023 20:37:36 -0500 Subject: [PATCH] Fix force/release of real. --- src/V3Force.cpp | 38 ++++++++++++++++++++++++++------------ test_regress/t/t_force.v | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/V3Force.cpp b/src/V3Force.cpp index b909d04e4..1073f1c8c 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -55,15 +55,15 @@ class ForceConvertVisitor final : public VNVisitor { // TYPES struct ForceComponentsVar { AstVar* const m_rdVarp; // New variable to replace read references with - AstVar* const m_enVarp; // Force enabled signal AstVar* const m_valVarp; // Forced value + AstVar* const m_enVarp; // Force enabled signal explicit ForceComponentsVar(AstVar* varp) : m_rdVarp{new AstVar{varp->fileline(), VVarType::WIRE, varp->name() + "__VforceRd", varp->dtypep()}} - , m_enVarp{new AstVar{varp->fileline(), VVarType::VAR, varp->name() + "__VforceEn", - varp->dtypep()}} , m_valVarp{new AstVar{varp->fileline(), VVarType::VAR, varp->name() + "__VforceVal", - varp->dtypep()}} { + varp->dtypep()}} + , m_enVarp{new AstVar{varp->fileline(), VVarType::VAR, varp->name() + "__VforceEn", + (isRangedDType(varp) ? varp->dtypep() : varp->findBitDType())}} { m_rdVarp->addNext(m_enVarp); m_rdVarp->addNext(m_valVarp); varp->addNextHere(m_rdVarp); @@ -111,12 +111,20 @@ class ForceConvertVisitor final : public VNVisitor { AstVarRef* const lhsp = new AstVarRef{flp, m_rdVscp, VAccess::WRITE}; AstVarRef* const origp = new AstVarRef{flp, vscp, VAccess::READ}; origp->user2(1); // Don't replace this read ref with the read signal - AstOr* const rhsp = new AstOr{ - flp, - new AstAnd{flp, new AstVarRef{flp, m_enVscp, VAccess::READ}, - new AstVarRef{flp, m_valVscp, VAccess::READ}}, - new AstAnd{flp, new AstNot{flp, new AstVarRef{flp, m_enVscp, VAccess::READ}}, - origp}}; + AstNodeExpr* rhsp; + if (isRangedDType(vscp)) { + rhsp = new AstOr{ + flp, + new AstAnd{flp, new AstVarRef{flp, m_enVscp, VAccess::READ}, + new AstVarRef{flp, m_valVscp, VAccess::READ}}, + new AstAnd{flp, + new AstNot{flp, new AstVarRef{flp, m_enVscp, VAccess::READ}}, + origp}}; + } else { + rhsp = new AstCond{flp, new AstVarRef{flp, m_enVscp, VAccess::READ}, + new AstVarRef{flp, m_valVscp, VAccess::READ}, origp}; + } + AstActive* const activep = new AstActive{flp, "force-comb", new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}}}; @@ -137,6 +145,12 @@ class ForceConvertVisitor final : public VNVisitor { AstUser1Allocator m_forceComponentsVarScope; // METHODS + static bool isRangedDType(AstNode* nodep) { + // If ranged we need a multibit enable to support bit-by-bit part-select forces, + // otherwise forcing a real or other opaque dtype and need a single bit enable. + const AstBasicDType* const basicp = nodep->dtypep()->skipRefp()->basicp(); + return basicp && basicp->isRanged(); + } const ForceComponentsVarScope& getForceComponents(AstVarScope* vscp) { AstVar* const varp = vscp->varp(); return m_forceComponentsVarScope(vscp, vscp, m_forceComponentsVar(varp, varp)); @@ -171,7 +185,7 @@ class ForceConvertVisitor final : public VNVisitor { AstNodeExpr* const rhsp = nodep->rhsp(); // The value we are forcing it to // Set corresponding enable signals to ones - V3Number ones{lhsp, lhsp->width()}; + V3Number ones{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1}; ones.setAllBits1(); AstAssign* const setEnp = new AstAssign{flp, lhsp->cloneTree(false), new AstConst{rhsp->fileline(), ones}}; @@ -206,7 +220,7 @@ class ForceConvertVisitor final : public VNVisitor { AstNodeExpr* const lhsp = nodep->lhsp(); // The LValue we are releasing // Set corresponding enable signals to zero - V3Number zero{lhsp, lhsp->width()}; + V3Number zero{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1}; zero.setAllBits0(); AstAssign* const resetEnp = new AstAssign{flp, lhsp->cloneTree(false), new AstConst{lhsp->fileline(), zero}}; diff --git a/test_regress/t/t_force.v b/test_regress/t/t_force.v index d669a8d74..ec076fe3d 100644 --- a/test_regress/t/t_force.v +++ b/test_regress/t/t_force.v @@ -6,6 +6,7 @@ `define stop $stop `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) +`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0); module t(/*AUTOARG*/ // Inputs @@ -21,6 +22,8 @@ module t(/*AUTOARG*/ int never_driven; int never_forced; + real r; + task force_bus; force bus[1:0] = 2'b10; endtask @@ -95,6 +98,25 @@ module t(/*AUTOARG*/ `checkh(bus, 4'b0101); end // + else if (cyc == 40) begin + r <= 1.25; + end + else if (cyc == 41) begin + `checkr(r, 1.25); + end + else if (cyc == 42) begin + force r = 2.5; + end + else if (cyc == 43) begin + `checkr(r, 2.5); + end + else if (cyc == 44) begin + release r; + end + else if (cyc == 45) begin + `checkr(r, 1.25); + end + // else if (cyc == 99) begin $write("*-* All Finished *-*\n"); $finish;