Fix force/release of real.

This commit is contained in:
Wilson Snyder 2023-02-04 20:37:36 -05:00
parent d33ded22f9
commit 2d89c458f6
2 changed files with 48 additions and 12 deletions

View File

@ -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<AstVarScope, ForceComponentsVarScope> 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}};

View File

@ -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;