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
|
// TYPES
|
||||||
struct ForceComponentsVar {
|
struct ForceComponentsVar {
|
||||||
AstVar* const m_rdVarp; // New variable to replace read references with
|
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_valVarp; // Forced value
|
||||||
|
AstVar* const m_enVarp; // Force enabled signal
|
||||||
explicit ForceComponentsVar(AstVar* varp)
|
explicit ForceComponentsVar(AstVar* varp)
|
||||||
: m_rdVarp{new AstVar{varp->fileline(), VVarType::WIRE, varp->name() + "__VforceRd",
|
: m_rdVarp{new AstVar{varp->fileline(), VVarType::WIRE, varp->name() + "__VforceRd",
|
||||||
varp->dtypep()}}
|
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",
|
, 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_enVarp);
|
||||||
m_rdVarp->addNext(m_valVarp);
|
m_rdVarp->addNext(m_valVarp);
|
||||||
varp->addNextHere(m_rdVarp);
|
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 lhsp = new AstVarRef{flp, m_rdVscp, VAccess::WRITE};
|
||||||
AstVarRef* const origp = new AstVarRef{flp, vscp, VAccess::READ};
|
AstVarRef* const origp = new AstVarRef{flp, vscp, VAccess::READ};
|
||||||
origp->user2(1); // Don't replace this read ref with the read signal
|
origp->user2(1); // Don't replace this read ref with the read signal
|
||||||
AstOr* const rhsp = new AstOr{
|
AstNodeExpr* rhsp;
|
||||||
flp,
|
if (isRangedDType(vscp)) {
|
||||||
new AstAnd{flp, new AstVarRef{flp, m_enVscp, VAccess::READ},
|
rhsp = new AstOr{
|
||||||
new AstVarRef{flp, m_valVscp, VAccess::READ}},
|
flp,
|
||||||
new AstAnd{flp, new AstNot{flp, new AstVarRef{flp, m_enVscp, VAccess::READ}},
|
new AstAnd{flp, new AstVarRef{flp, m_enVscp, VAccess::READ},
|
||||||
origp}};
|
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
|
AstActive* const activep
|
||||||
= new AstActive{flp, "force-comb",
|
= new AstActive{flp, "force-comb",
|
||||||
new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}}};
|
new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}}};
|
||||||
@ -137,6 +145,12 @@ class ForceConvertVisitor final : public VNVisitor {
|
|||||||
AstUser1Allocator<AstVarScope, ForceComponentsVarScope> m_forceComponentsVarScope;
|
AstUser1Allocator<AstVarScope, ForceComponentsVarScope> m_forceComponentsVarScope;
|
||||||
|
|
||||||
// METHODS
|
// 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) {
|
const ForceComponentsVarScope& getForceComponents(AstVarScope* vscp) {
|
||||||
AstVar* const varp = vscp->varp();
|
AstVar* const varp = vscp->varp();
|
||||||
return m_forceComponentsVarScope(vscp, vscp, m_forceComponentsVar(varp, 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
|
AstNodeExpr* const rhsp = nodep->rhsp(); // The value we are forcing it to
|
||||||
|
|
||||||
// Set corresponding enable signals to ones
|
// Set corresponding enable signals to ones
|
||||||
V3Number ones{lhsp, lhsp->width()};
|
V3Number ones{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1};
|
||||||
ones.setAllBits1();
|
ones.setAllBits1();
|
||||||
AstAssign* const setEnp
|
AstAssign* const setEnp
|
||||||
= new AstAssign{flp, lhsp->cloneTree(false), new AstConst{rhsp->fileline(), ones}};
|
= 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
|
AstNodeExpr* const lhsp = nodep->lhsp(); // The LValue we are releasing
|
||||||
|
|
||||||
// Set corresponding enable signals to zero
|
// Set corresponding enable signals to zero
|
||||||
V3Number zero{lhsp, lhsp->width()};
|
V3Number zero{lhsp, isRangedDType(lhsp) ? lhsp->width() : 1};
|
||||||
zero.setAllBits0();
|
zero.setAllBits0();
|
||||||
AstAssign* const resetEnp
|
AstAssign* const resetEnp
|
||||||
= new AstAssign{flp, lhsp->cloneTree(false), new AstConst{lhsp->fileline(), zero}};
|
= new AstAssign{flp, lhsp->cloneTree(false), new AstConst{lhsp->fileline(), zero}};
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
`define stop $stop
|
`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 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*/
|
module t(/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
@ -21,6 +22,8 @@ module t(/*AUTOARG*/
|
|||||||
int never_driven;
|
int never_driven;
|
||||||
int never_forced;
|
int never_forced;
|
||||||
|
|
||||||
|
real r;
|
||||||
|
|
||||||
task force_bus;
|
task force_bus;
|
||||||
force bus[1:0] = 2'b10;
|
force bus[1:0] = 2'b10;
|
||||||
endtask
|
endtask
|
||||||
@ -95,6 +98,25 @@ module t(/*AUTOARG*/
|
|||||||
`checkh(bus, 4'b0101);
|
`checkh(bus, 4'b0101);
|
||||||
end
|
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
|
else if (cyc == 99) begin
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
Loading…
Reference in New Issue
Block a user