Support $monitor and $strobe.

This commit is contained in:
Wilson Snyder 2020-11-29 11:31:38 -05:00
parent 67103d346b
commit 665e8edaff
23 changed files with 548 additions and 22 deletions

View File

@ -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'.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

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

View 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

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

View 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

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

View 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

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

View 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