forked from github/verilator
Support $monitor and $strobe.
This commit is contained in:
parent
67103d346b
commit
665e8edaff
2
Changes
2
Changes
@ -11,6 +11,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
*** Support $random and $urandom seeds.
|
||||
|
||||
*** Support $monitor and $strobe.
|
||||
|
||||
*** Support complex function arguments.
|
||||
|
||||
*** Support 'super'.
|
||||
|
@ -4107,11 +4107,6 @@ $setup, $setuphold, $skew, $timeskew, $width
|
||||
|
||||
All specify blocks and timing checks are ignored.
|
||||
|
||||
=item $monitor, $strobe
|
||||
|
||||
Monitor and strobe are not supported, convert to always_comb $display or
|
||||
similar.
|
||||
|
||||
=item $random, $urandom, $urandom_range
|
||||
|
||||
Use +verilator+seed argument to set the seed if there is no $random or
|
||||
|
@ -364,6 +364,14 @@ private:
|
||||
}
|
||||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||
}
|
||||
virtual void visit(AstAlwaysPostponed* nodep) override {
|
||||
UINFO(4, " ALW " << nodep << endl);
|
||||
if (!nodep->bodysp()) {
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS);
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4, " ALWPub " << nodep << endl);
|
||||
|
@ -36,7 +36,11 @@ private:
|
||||
// STATE
|
||||
AstNodeModule* m_modp = nullptr; // Last module
|
||||
AstBegin* m_beginp = nullptr; // Last begin
|
||||
unsigned m_monitorNum = 0; // Global $monitor numbering (not per module)
|
||||
AstVar* m_monitorNumVarp = nullptr; // $monitor number variable
|
||||
AstVar* m_monitorOffVarp = nullptr; // $monitoroff variable
|
||||
unsigned m_modPastNum = 0; // Module past numbering
|
||||
unsigned m_modStrobeNum = 0; // Module $strobe numbering
|
||||
VDouble0 m_statCover; // Statistic tracking
|
||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||
VDouble0 m_statAsImm; // Statistic tracking
|
||||
@ -62,7 +66,26 @@ private:
|
||||
nodep->fmtp()->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||
}
|
||||
}
|
||||
|
||||
AstVarRef* newMonitorNumVarRefp(AstNode* nodep, VAccess access) {
|
||||
if (!m_monitorNumVarp) {
|
||||
m_monitorNumVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP,
|
||||
"__VmonitorNum", nodep->findUInt64DType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access);
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
AstVarRef* newMonitorOffVarRefp(AstNode* nodep, VAccess access) {
|
||||
if (!m_monitorOffVarp) {
|
||||
m_monitorOffVarp = new AstVar{nodep->fileline(), AstVarType::MODULETEMP,
|
||||
"__VmonitorOff", nodep->findBitDType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access);
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
return varrefp;
|
||||
}
|
||||
AstNode* newIfAssertOn(AstNode* nodep) {
|
||||
// Add a internal if to check assertions are on.
|
||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||
@ -342,9 +365,54 @@ private:
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_ERROR
|
||||
|| nodep->displayType() == AstDisplayType::DT_FATAL) {
|
||||
replaceDisplay(nodep, "%%Error");
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_MONITOR) {
|
||||
nodep->displayType(AstDisplayType::DT_DISPLAY);
|
||||
const auto fl = nodep->fileline();
|
||||
const auto monNum = ++m_monitorNum;
|
||||
// Where $monitor was we do "__VmonitorNum = N;"
|
||||
const auto newsetp = new AstAssign{fl, newMonitorNumVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst{fl, monNum}};
|
||||
nodep->replaceWith(newsetp);
|
||||
// Add "always_comb if (__VmonitorOn && __VmonitorNum==N) $display(...);"
|
||||
AstNode* stmtsp = nodep;
|
||||
AstIf* ifp = new AstIf{
|
||||
fl,
|
||||
new AstLogAnd{fl, new AstLogNot{fl, newMonitorOffVarRefp(nodep, VAccess::READ)},
|
||||
new AstEq{fl, new AstConst{fl, monNum},
|
||||
newMonitorNumVarRefp(nodep, VAccess::READ)}},
|
||||
stmtsp, nullptr};
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
AstNode* newp = new AstAlwaysPostponed{fl, ifp};
|
||||
m_modp->addStmtp(newp);
|
||||
} else if (nodep->displayType() == AstDisplayType::DT_STROBE) {
|
||||
nodep->displayType(AstDisplayType::DT_DISPLAY);
|
||||
// Need one-shot
|
||||
const auto fl = nodep->fileline();
|
||||
const auto varp
|
||||
= new AstVar{fl, AstVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
|
||||
nodep->findBitDType()};
|
||||
m_modp->addStmtp(varp);
|
||||
// Where $strobe was we do "__Vstrobe = '1;"
|
||||
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitTrue{}}};
|
||||
nodep->replaceWith(newsetp);
|
||||
// Add "always_comb if (__Vstrobe) begin $display(...); __Vstrobe = '0; end"
|
||||
AstNode* stmtsp = nodep;
|
||||
AstIf* ifp = new AstIf{fl, new AstVarRef{fl, varp, VAccess::READ}, stmtsp, nullptr};
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
AstNode* newp = new AstAlwaysPostponed{fl, ifp};
|
||||
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitFalse{}}});
|
||||
m_modp->addStmtp(newp);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstMonitorOff* nodep) override {
|
||||
const auto newp
|
||||
= new AstAssign(nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst(nodep->fileline(), AstConst::BitTrue{}, nodep->off()));
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstAssert* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nodep->failsp());
|
||||
@ -362,9 +430,11 @@ private:
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_modPastNum);
|
||||
VL_RESTORER(m_modStrobeNum);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_modPastNum = 0;
|
||||
m_modStrobeNum = 0;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
17
src/V3Ast.h
17
src/V3Ast.h
@ -879,12 +879,21 @@ inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs ==
|
||||
|
||||
class AstDisplayType final {
|
||||
public:
|
||||
enum en : uint8_t { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL };
|
||||
enum en : uint8_t {
|
||||
DT_DISPLAY,
|
||||
DT_WRITE,
|
||||
DT_MONITOR,
|
||||
DT_STROBE,
|
||||
DT_INFO,
|
||||
DT_ERROR,
|
||||
DT_WARNING,
|
||||
DT_FATAL
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstDisplayType()
|
||||
AstDisplayType()
|
||||
: m_e{DT_DISPLAY} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline AstDisplayType(en _e)
|
||||
AstDisplayType(en _e)
|
||||
: m_e{_e} {}
|
||||
explicit inline AstDisplayType(int _e)
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
@ -893,7 +902,7 @@ public:
|
||||
bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; }
|
||||
const char* ascii() const {
|
||||
static const char* const names[]
|
||||
= {"display", "write", "info", "error", "warning", "fatal"};
|
||||
= {"display", "write", "monitor", "strobe", "info", "error", "warning", "fatal"};
|
||||
return names[m_e];
|
||||
}
|
||||
};
|
||||
|
@ -146,16 +146,11 @@ public:
|
||||
, m_num(this, 1, 0) {
|
||||
dtypeSetBit();
|
||||
}
|
||||
// Shorthand const 1 (or with argument 0/1), dtype should be a logic of size 1
|
||||
class BitTrue {};
|
||||
AstConst(FileLine* fl, BitTrue) // Shorthand const 1, dtype should be a logic of size 1
|
||||
AstConst(FileLine* fl, BitTrue, bool on = true)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_num(this, 1, 1) {
|
||||
dtypeSetBit();
|
||||
}
|
||||
class BitTrueFalse {};
|
||||
AstConst(FileLine* fl, BitTrueFalse, bool on)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_num(this, 1, on ? 1 : 0) {
|
||||
, m_num(this, 1, on) {
|
||||
dtypeSetBit();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Const)
|
||||
@ -3296,6 +3291,14 @@ public:
|
||||
void sensesp(AstSenTree* nodep) { setOp1p(nodep); }
|
||||
VAlwaysKwd keyword() const { return m_keyword; }
|
||||
};
|
||||
class AstAlwaysPostponed final : public AstNodeProcedure {
|
||||
// Like always but postponement scheduling region
|
||||
|
||||
public:
|
||||
AstAlwaysPostponed(FileLine* fl, AstNode* bodysp)
|
||||
: ASTGEN_SUPER(fl, bodysp) {}
|
||||
ASTNODE_NODE_FUNCS(AlwaysPostponed)
|
||||
};
|
||||
|
||||
class AstAlwaysPublic final : public AstNodeStmt {
|
||||
// "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/
|
||||
@ -4282,6 +4285,29 @@ public:
|
||||
virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; }
|
||||
};
|
||||
|
||||
class AstMonitorOff final : public AstNodeStmt {
|
||||
bool m_off; // Monitor off. Using 0=on allows faster init and comparison
|
||||
|
||||
public:
|
||||
AstMonitorOff(FileLine* fl, bool off)
|
||||
: ASTGEN_SUPER(fl)
|
||||
, m_off{off} {}
|
||||
ASTNODE_NODE_FUNCS(MonitorOff)
|
||||
virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; }
|
||||
virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt
|
||||
virtual bool isPredictOptimizable() const override {
|
||||
return false;
|
||||
} // Though deleted before opt
|
||||
virtual bool isPure() const override { return false; } // Though deleted before opt
|
||||
virtual bool isOutputter() const override { return true; } // Though deleted before opt
|
||||
virtual int instrCount() const override { return instrCountPli(); }
|
||||
virtual V3Hash sameHash() const override { return V3Hash(m_off); }
|
||||
virtual bool same(const AstNode* samep) const override {
|
||||
return m_off == static_cast<const AstMonitorOff*>(samep)->m_off;
|
||||
}
|
||||
bool off() const { return m_off; }
|
||||
};
|
||||
|
||||
class AstSystemT final : public AstNodeStmt {
|
||||
// $system used as task
|
||||
public:
|
||||
|
@ -311,6 +311,15 @@ private:
|
||||
}
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstAlwaysPostponed* nodep) override {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
// nodep->dumpTree(cout, "ct:");
|
||||
// COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||
|
@ -170,7 +170,7 @@ private:
|
||||
// of the RHS is expected to be deleted by the caller.
|
||||
AstNode* foldAndUnlink(AstNode* rhsp, bool condTrue) {
|
||||
if (rhsp->sameTree(m_mgCondp)) {
|
||||
return new AstConst(rhsp->fileline(), AstConst::BitTrueFalse(), condTrue);
|
||||
return new AstConst(rhsp->fileline(), AstConst::BitTrue{}, condTrue);
|
||||
} else if (AstNodeCond* const condp = extractCond(rhsp)) {
|
||||
AstNode* const resp
|
||||
= condTrue ? condp->expr1p()->unlinkFrBack() : condp->expr2p()->unlinkFrBack();
|
||||
|
@ -673,6 +673,7 @@ private:
|
||||
bool m_inClkAss = false; // Underneath AstAssign
|
||||
bool m_inPre = false; // Underneath AstAssignPre
|
||||
bool m_inPost = false; // Underneath AstAssignPost
|
||||
bool m_inPostponed = false; // Underneath AstAssignPostponed
|
||||
OrderLogicVertex* m_activeSenVxp = nullptr; // Sensitivity vertex
|
||||
std::deque<OrderUser*> m_orderUserps; // All created OrderUser's for later deletion.
|
||||
// STATE... for inside process
|
||||
@ -1044,7 +1045,8 @@ private:
|
||||
// We don't want to add extra edges if the logic block has many usages of same var
|
||||
bool gen = false;
|
||||
bool con = false;
|
||||
if (nodep->access().isWriteOrRW()) gen = !(varscp->user4() & VU_GEN);
|
||||
if (nodep->access().isWriteOrRW() && !m_inPostponed)
|
||||
gen = !(varscp->user4() & VU_GEN);
|
||||
if (nodep->access().isReadOrRW()) {
|
||||
con = !(varscp->user4() & VU_CON);
|
||||
if ((varscp->user4() & VU_GEN) && !m_inClocked) {
|
||||
@ -1174,6 +1176,11 @@ private:
|
||||
iterateNewStmt(nodep);
|
||||
m_inPost = false;
|
||||
}
|
||||
virtual void visit(AstAlwaysPostponed* nodep) override {
|
||||
VL_RESTORER(m_inPostponed);
|
||||
m_inPostponed = true;
|
||||
iterateNewStmt(nodep);
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAlwaysPublic* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); }
|
||||
|
@ -205,11 +205,19 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"$fgets" { FL; return yD_FGETS; }
|
||||
"$finish" { FL; return yD_FINISH; }
|
||||
"$floor" { FL; return yD_FLOOR; }
|
||||
"$fmonitor" { FL; return yD_FMONITOR; }
|
||||
"$fmonitorb" { FL; return yD_FMONITORB; }
|
||||
"$fmonitorh" { FL; return yD_FMONITORH; }
|
||||
"$fmonitoro" { FL; return yD_FMONITORO; }
|
||||
"$fopen" { FL; return yD_FOPEN; }
|
||||
"$fread" { FL; return yD_FREAD; }
|
||||
"$frewind" { FL; return yD_FREWIND; }
|
||||
"$fscanf" { FL; return yD_FSCANF; }
|
||||
"$fseek" { FL; return yD_FSEEK; }
|
||||
"$fstrobe" { FL; return yD_FSTROBE; }
|
||||
"$fstrobeb" { FL; return yD_FSTROBEB; }
|
||||
"$fstrobeh" { FL; return yD_FSTROBEH; }
|
||||
"$fstrobeo" { FL; return yD_FSTROBEO; }
|
||||
"$ftell" { FL; return yD_FTELL; }
|
||||
"$fullskew" { FL; return yaTIMINGSPEC; }
|
||||
"$fwrite" { FL; return yD_FWRITE; }
|
||||
@ -221,6 +229,12 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"$itor" { FL; return yD_ITOR; }
|
||||
"$ln" { FL; return yD_LN; }
|
||||
"$log10" { FL; return yD_LOG10; }
|
||||
"$monitor" { FL; return yD_MONITOR; }
|
||||
"$monitorb" { FL; return yD_MONITORB; }
|
||||
"$monitorh" { FL; return yD_MONITORH; }
|
||||
"$monitoro" { FL; return yD_MONITORO; }
|
||||
"$monitoroff" { FL; return yD_MONITOROFF; }
|
||||
"$monitoron" { FL; return yD_MONITORON; }
|
||||
"$nochange" { FL; return yaTIMINGSPEC; }
|
||||
"$period" { FL; return yaTIMINGSPEC; }
|
||||
"$pow" { FL; return yD_POW; }
|
||||
@ -248,6 +262,10 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"$sscanf" { FL; return yD_SSCANF; }
|
||||
"$stime" { FL; return yD_STIME; }
|
||||
"$stop" { FL; return yD_STOP; }
|
||||
"$strobe" { FL; return yD_STROBE; }
|
||||
"$strobeb" { FL; return yD_STROBEB; }
|
||||
"$strobeh" { FL; return yD_STROBEH; }
|
||||
"$strobeo" { FL; return yD_STROBEO; }
|
||||
"$swrite" { FL; return yD_SWRITE; }
|
||||
"$swriteb" { FL; return yD_SWRITEB; }
|
||||
"$swriteh" { FL; return yD_SWRITEH; }
|
||||
@ -268,9 +286,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||
"$write" { FL; return yD_WRITE; }
|
||||
"$writeb" { FL; return yD_WRITEB; }
|
||||
"$writeh" { FL; return yD_WRITEH; }
|
||||
"$writeo" { FL; return yD_WRITEO; }
|
||||
"$writememb" { FL; return yD_WRITEMEMB; }
|
||||
"$writememh" { FL; return yD_WRITEMEMH; }
|
||||
"$writeo" { FL; return yD_WRITEO; }
|
||||
/* Keywords */
|
||||
"always" { FL; return yALWAYS; }
|
||||
"and" { FL; return yAND; }
|
||||
|
@ -740,11 +740,19 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
||||
%token<fl> yD_FGETS "$fgets"
|
||||
%token<fl> yD_FINISH "$finish"
|
||||
%token<fl> yD_FLOOR "$floor"
|
||||
%token<fl> yD_FMONITOR "$fmonitor"
|
||||
%token<fl> yD_FMONITORB "$fmonitorb"
|
||||
%token<fl> yD_FMONITORH "$fmonitorh"
|
||||
%token<fl> yD_FMONITORO "$fmonitoro"
|
||||
%token<fl> yD_FOPEN "$fopen"
|
||||
%token<fl> yD_FREAD "$fread"
|
||||
%token<fl> yD_FREWIND "$frewind"
|
||||
%token<fl> yD_FSCANF "$fscanf"
|
||||
%token<fl> yD_FSEEK "$fseek"
|
||||
%token<fl> yD_FSTROBE "$fstrobe"
|
||||
%token<fl> yD_FSTROBEB "$fstrobeb"
|
||||
%token<fl> yD_FSTROBEH "$fstrobeh"
|
||||
%token<fl> yD_FSTROBEO "$fstrobeo"
|
||||
%token<fl> yD_FTELL "$ftell"
|
||||
%token<fl> yD_FWRITE "$fwrite"
|
||||
%token<fl> yD_FWRITEB "$fwriteb"
|
||||
@ -761,6 +769,12 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
||||
%token<fl> yD_LN "$ln"
|
||||
%token<fl> yD_LOG10 "$log10"
|
||||
%token<fl> yD_LOW "$low"
|
||||
%token<fl> yD_MONITOR "$monitor"
|
||||
%token<fl> yD_MONITORB "$monitorb"
|
||||
%token<fl> yD_MONITORH "$monitorh"
|
||||
%token<fl> yD_MONITORO "$monitoro"
|
||||
%token<fl> yD_MONITOROFF "$monitoroff"
|
||||
%token<fl> yD_MONITORON "$monitoron"
|
||||
%token<fl> yD_ONEHOT "$onehot"
|
||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||
%token<fl> yD_PAST "$past"
|
||||
@ -789,6 +803,10 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
||||
%token<fl> yD_STABLE "$stable"
|
||||
%token<fl> yD_STIME "$stime"
|
||||
%token<fl> yD_STOP "$stop"
|
||||
%token<fl> yD_STROBE "$strobe"
|
||||
%token<fl> yD_STROBEB "$strobeb"
|
||||
%token<fl> yD_STROBEH "$strobeh"
|
||||
%token<fl> yD_STROBEO "$strobeo"
|
||||
%token<fl> yD_SWRITE "$swrite"
|
||||
%token<fl> yD_SWRITEB "$swriteb"
|
||||
%token<fl> yD_SWRITEH "$swriteh"
|
||||
@ -3580,6 +3598,14 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
| yD_DISPLAYH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'h'); }
|
||||
| yD_DISPLAYO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'o'); }
|
||||
| yD_DISPLAYO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'o'); }
|
||||
| yD_MONITOR '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3); }
|
||||
| yD_MONITORB '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'b'); }
|
||||
| yD_MONITORH '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'h'); }
|
||||
| yD_MONITORO '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, nullptr, $3, 'o'); }
|
||||
| yD_STROBE '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3); }
|
||||
| yD_STROBEB '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'b'); }
|
||||
| yD_STROBEH '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'h'); }
|
||||
| yD_STROBEO '(' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, nullptr, $3, 'o'); }
|
||||
| yD_WRITE parenE { $$ = nullptr; } // NOP
|
||||
| yD_WRITE '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3); }
|
||||
| yD_WRITEB parenE { $$ = nullptr; } // NOP
|
||||
@ -3596,6 +3622,14 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
| yD_FDISPLAYH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'h'); }
|
||||
| yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'o'); }
|
||||
| yD_FDISPLAYO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'o'); }
|
||||
| yD_FMONITOR '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5); }
|
||||
| yD_FMONITORB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'b'); }
|
||||
| yD_FMONITORH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'h'); }
|
||||
| yD_FMONITORO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_MONITOR, $3, $5, 'o'); }
|
||||
| yD_FSTROBE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5); }
|
||||
| yD_FSTROBEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'b'); }
|
||||
| yD_FSTROBEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'h'); }
|
||||
| yD_FSTROBEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_STROBE, $3, $5, 'o'); }
|
||||
| yD_FWRITE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5); }
|
||||
| yD_FWRITEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'b'); }
|
||||
| yD_FWRITEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1, AstDisplayType::DT_WRITE, $3, $5, 'h'); }
|
||||
@ -3610,6 +3644,9 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
| yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, nullptr); $$->addNext(new AstStop($1, false)); DEL($3); }
|
||||
| yD_FATAL '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, $5); $$->addNext(new AstStop($1, false)); DEL($3); }
|
||||
//
|
||||
| yD_MONITOROFF parenE { $$ = new AstMonitorOff($1, true); }
|
||||
| yD_MONITORON parenE { $$ = new AstMonitorOff($1, false); }
|
||||
//
|
||||
| yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale($1); }
|
||||
| yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale($1); }
|
||||
| yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale($1); DEL($3); }
|
||||
|
15
test_regress/t/t_sys_fmonitor.out
Normal file
15
test_regress/t/t_sys_fmonitor.out
Normal file
@ -0,0 +1,15 @@
|
||||
[110] cyc=11 also
|
||||
[120] cyc=12 also
|
||||
[130] cyc=13 also
|
||||
[140] cyc=14 also
|
||||
[150] cyc=15 also
|
||||
[160] cyc=16 also
|
||||
[170] cyc=17 also
|
||||
00000000000000000000000000010010b
|
||||
00000013h
|
||||
00000000024o
|
||||
00000000025o
|
||||
00000000026o
|
||||
[230] cyc=23 new-monitor
|
||||
[240] cyc=24 new-monitor
|
||||
[270] cyc=27 new-monitor
|
24
test_regress/t/t_sys_fmonitor.pl
Executable file
24
test_regress/t/t_sys_fmonitor.pl
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
files_identical("$Self->{obj_dir}/open.log", $Self->{golden_filename});
|
||||
|
||||
ok(1);
|
||||
|
||||
1;
|
57
test_regress/t/t_sys_fmonitor.v
Normal file
57
test_regress/t/t_sys_fmonitor.v
Normal file
@ -0,0 +1,57 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
int cyc = 0;
|
||||
int fd;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 5) begin
|
||||
fd = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/open.log"}, "w");
|
||||
end
|
||||
else if (cyc == 10) begin
|
||||
$fmonitor(fd, "[%0t] cyc=%0d", $time, cyc);
|
||||
$fmonitor(fd, "[%0t] cyc=%0d also", $time, cyc);
|
||||
end
|
||||
else if (cyc == 17) begin
|
||||
$fmonitorb(fd, cyc, "b");
|
||||
end
|
||||
else if (cyc == 18) begin
|
||||
$fmonitorh(fd, cyc, "h");
|
||||
end
|
||||
else if (cyc == 19) begin
|
||||
$fmonitoro(fd, cyc, "o");
|
||||
end
|
||||
else if (cyc == 22) begin
|
||||
$fmonitor(fd, "[%0t] cyc=%0d new-monitor", $time, cyc);
|
||||
end
|
||||
else if (cyc == 24) begin
|
||||
// IEEE suggests $monitoroff doesn't affect $fmonitor, but
|
||||
// other simulators believe it does
|
||||
$monitoroff;
|
||||
end
|
||||
else if (cyc == 26) begin
|
||||
$monitoron;
|
||||
end
|
||||
else if (cyc == 27) begin
|
||||
$fclose(fd);
|
||||
end
|
||||
else if (cyc == 30) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
6
test_regress/t/t_sys_fstrobe.out
Normal file
6
test_regress/t/t_sys_fstrobe.out
Normal file
@ -0,0 +1,6 @@
|
||||
[110] cyc=11
|
||||
[110] cyc=11 also
|
||||
00000000000000000000000000010010b
|
||||
00000013h
|
||||
00000000024o
|
||||
[230] cyc=23 new-strobe
|
24
test_regress/t/t_sys_fstrobe.pl
Executable file
24
test_regress/t/t_sys_fstrobe.pl
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
files_identical("$Self->{obj_dir}/open.log", $Self->{golden_filename});
|
||||
|
||||
ok(1);
|
||||
|
||||
1;
|
55
test_regress/t/t_sys_fstrobe.v
Normal file
55
test_regress/t/t_sys_fstrobe.v
Normal file
@ -0,0 +1,55 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define STRINGIFY(x) `"x`"
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
int cyc = 0;
|
||||
int fd;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 5) begin
|
||||
fd = $fopen({`STRINGIFY(`TEST_OBJ_DIR),"/open.log"}, "w");
|
||||
end
|
||||
else if (cyc == 10) begin
|
||||
$fstrobe(fd, "[%0t] cyc=%0d", $time, cyc);
|
||||
$fstrobe(fd, "[%0t] cyc=%0d also", $time, cyc);
|
||||
end
|
||||
else if (cyc == 17) begin
|
||||
$fstrobeb(fd, cyc, "b");
|
||||
end
|
||||
else if (cyc == 18) begin
|
||||
$fstrobeh(fd, cyc, "h");
|
||||
end
|
||||
else if (cyc == 19) begin
|
||||
$fstrobeo(fd, cyc, "o");
|
||||
end
|
||||
else if (cyc == 22) begin
|
||||
$fstrobe(fd, "[%0t] cyc=%0d new-strobe", $time, cyc);
|
||||
end
|
||||
else if (cyc == 24) begin
|
||||
$monitoroff;
|
||||
end
|
||||
else if (cyc == 26) begin
|
||||
$monitoron;
|
||||
end
|
||||
else if (cyc == 27) begin
|
||||
$fclose(fd);
|
||||
end
|
||||
else if (cyc == 30) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
20
test_regress/t/t_sys_monitor.out
Normal file
20
test_regress/t/t_sys_monitor.out
Normal file
@ -0,0 +1,20 @@
|
||||
[110] cyc=11
|
||||
[120] cyc=12
|
||||
[130] cyc=13
|
||||
[140] cyc=14
|
||||
[150] cyc=15
|
||||
[160] cyc=16
|
||||
[170] cyc=17
|
||||
00000000000000000000000000010010b
|
||||
00000013h
|
||||
00000000024o
|
||||
00000000025o
|
||||
00000000026o
|
||||
[230] cyc=23 new-monitor
|
||||
[240] cyc=24 new-monitor
|
||||
[270] cyc=27 new-monitor
|
||||
[280] cyc=28 new-monitor
|
||||
[290] cyc=29 new-monitor
|
||||
[300] cyc=30 new-monitor
|
||||
*-* All Finished *-*
|
||||
[310] cyc=31 new-monitor
|
23
test_regress/t/t_sys_monitor.pl
Executable file
23
test_regress/t/t_sys_monitor.pl
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
1;
|
45
test_regress/t/t_sys_monitor.v
Normal file
45
test_regress/t/t_sys_monitor.v
Normal file
@ -0,0 +1,45 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
int cyc = 0;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 10) begin
|
||||
$monitor("[%0t] cyc=%0d", $time, cyc);
|
||||
end
|
||||
else if (cyc == 17) begin
|
||||
$monitorb(cyc, "b");
|
||||
end
|
||||
else if (cyc == 18) begin
|
||||
$monitorh(cyc, "h");
|
||||
end
|
||||
else if (cyc == 19) begin
|
||||
$monitoro(cyc, "o");
|
||||
end
|
||||
else if (cyc == 22) begin
|
||||
$monitor("[%0t] cyc=%0d new-monitor", $time, cyc);
|
||||
end
|
||||
else if (cyc == 24) begin
|
||||
$monitoroff;
|
||||
end
|
||||
else if (cyc == 26) begin
|
||||
$monitoron;
|
||||
end
|
||||
else if (cyc == 30) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
7
test_regress/t/t_sys_strobe.out
Normal file
7
test_regress/t/t_sys_strobe.out
Normal file
@ -0,0 +1,7 @@
|
||||
[110] cyc=11
|
||||
[110] cyc=11 also
|
||||
00000000000000000000000000010010b
|
||||
00000013h
|
||||
00000000024o
|
||||
[230] cyc=23 new-strobe
|
||||
*-* All Finished *-*
|
23
test_regress/t/t_sys_strobe.pl
Executable file
23
test_regress/t/t_sys_strobe.pl
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
|
||||
1;
|
46
test_regress/t/t_sys_strobe.v
Normal file
46
test_regress/t/t_sys_strobe.v
Normal file
@ -0,0 +1,46 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
int cyc = 0;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 10) begin
|
||||
$strobe("[%0t] cyc=%0d", $time, cyc);
|
||||
$strobe("[%0t] cyc=%0d also", $time, cyc);
|
||||
end
|
||||
else if (cyc == 17) begin
|
||||
$strobeb(cyc, "b");
|
||||
end
|
||||
else if (cyc == 18) begin
|
||||
$strobeh(cyc, "h");
|
||||
end
|
||||
else if (cyc == 19) begin
|
||||
$strobeo(cyc, "o");
|
||||
end
|
||||
else if (cyc == 22) begin
|
||||
$strobe("[%0t] cyc=%0d new-strobe", $time, cyc);
|
||||
end
|
||||
else if (cyc == 24) begin
|
||||
$monitoroff;
|
||||
end
|
||||
else if (cyc == 26) begin
|
||||
$monitoron;
|
||||
end
|
||||
else if (cyc == 30) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user