forked from github/verilator
Fix force/release of real.
This commit is contained in:
parent
d33ded22f9
commit
2d89c458f6
@ -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}};
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user