Support $past.
This commit is contained in:
parent
a8519a7a53
commit
0e37747d2c
2
Changes
2
Changes
|
|
@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
* Verilator 4.003 devel
|
* Verilator 4.003 devel
|
||||||
|
|
||||||
|
*** Support $past. [Dan Gisselquist]
|
||||||
|
|
||||||
*** Fix Mac OSX 10.13.6 / LLVM 9.1 compile issues, bug1348. [Kevin Kiningham]
|
*** Fix Mac OSX 10.13.6 / LLVM 9.1 compile issues, bug1348. [Kevin Kiningham]
|
||||||
|
|
||||||
*** Fix MinGW compile issues, msg2636. [HyungKi Jeong]
|
*** Fix MinGW compile issues, msg2636. [HyungKi Jeong]
|
||||||
|
|
|
||||||
|
|
@ -3731,6 +3731,17 @@ Change this to:
|
||||||
Verilator doesn't do this conversion for you, as some more complicated
|
Verilator doesn't do this conversion for you, as some more complicated
|
||||||
cases would result in simulator mismatches.
|
cases would result in simulator mismatches.
|
||||||
|
|
||||||
|
=item TICKCOUNT
|
||||||
|
|
||||||
|
Warns that the number of ticks to delay a $past variable is greater than
|
||||||
|
10. At present Verilator effectively creates a flop for each delayed
|
||||||
|
signals, and as such any large counts may lead to large design size
|
||||||
|
increases.
|
||||||
|
|
||||||
|
Ignoring this warning will only slow simulations, it will simulate
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
|
||||||
=item UNDRIVEN
|
=item UNDRIVEN
|
||||||
|
|
||||||
Warns that the specified signal is never sourced. Verilator is fairly
|
Warns that the specified signal is never sourced. Verilator is fairly
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ private:
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeModule* m_modp; // Last module
|
AstNodeModule* m_modp; // Last module
|
||||||
AstBegin* m_beginp; // Last begin
|
AstBegin* m_beginp; // Last begin
|
||||||
|
unsigned m_modPastNum; // Module past numbering
|
||||||
V3Double0 m_statAsCover; // Statistic tracking
|
V3Double0 m_statAsCover; // Statistic tracking
|
||||||
V3Double0 m_statAsPsl; // Statistic tracking
|
V3Double0 m_statAsPsl; // Statistic tracking
|
||||||
V3Double0 m_statAsFull; // Statistic tracking
|
V3Double0 m_statAsFull; // Statistic tracking
|
||||||
|
|
@ -185,6 +186,7 @@ private:
|
||||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
virtual void visit(AstIf* nodep) {
|
virtual void visit(AstIf* nodep) {
|
||||||
if (nodep->user1SetOnce()) return;
|
if (nodep->user1SetOnce()) return;
|
||||||
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||||
|
|
@ -244,7 +246,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Case assertions
|
//========== Case assertions
|
||||||
virtual void visit(AstCase* nodep) {
|
virtual void visit(AstCase* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
if (!nodep->user1SetOnce()) {
|
if (!nodep->user1SetOnce()) {
|
||||||
|
|
@ -302,7 +304,38 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
//========== Past
|
||||||
|
virtual void visit(AstPast* nodep) {
|
||||||
|
iterateChildren(nodep);
|
||||||
|
uint32_t ticks = 1;
|
||||||
|
if (nodep->ticksp()) {
|
||||||
|
if (!VN_IS(nodep->ticksp(), Const)) nodep->v3fatalSrc("Expected constant ticks, checked in V3Width");
|
||||||
|
ticks = VN_CAST(nodep->ticksp(), Const)->toUInt();
|
||||||
|
}
|
||||||
|
if (ticks<1) nodep->v3fatalSrc("0 tick should have been checked in V3Width");
|
||||||
|
AstNode* inp = nodep->exprp()->unlinkFrBack();
|
||||||
|
AstVar* invarp = NULL;
|
||||||
|
AstSenTree* sentreep = nodep->sentreep(); sentreep->unlinkFrBack();
|
||||||
|
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS,
|
||||||
|
sentreep, NULL);
|
||||||
|
m_modp->addStmtp(alwaysp);
|
||||||
|
for (uint32_t i=0; i<ticks; ++i) {
|
||||||
|
AstVar* outvarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP,
|
||||||
|
"_Vpast_"+cvtToStr(m_modPastNum++)+"_"+cvtToStr(i),
|
||||||
|
inp->dtypep());
|
||||||
|
m_modp->addStmtp(outvarp);
|
||||||
|
AstNode* assp = new AstAssignDly(nodep->fileline(),
|
||||||
|
new AstVarRef(nodep->fileline(), outvarp, true),
|
||||||
|
inp);
|
||||||
|
alwaysp->addStmtp(assp);
|
||||||
|
//if (debug()>-9) assp->dumpTree(cout, "-ass: ");
|
||||||
|
invarp = outvarp;
|
||||||
|
inp = new AstVarRef(nodep->fileline(), invarp, false);
|
||||||
|
}
|
||||||
|
nodep->replaceWith(inp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//========== Statements
|
||||||
virtual void visit(AstDisplay* nodep) {
|
virtual void visit(AstDisplay* nodep) {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Replace the special types with standard text
|
// Replace the special types with standard text
|
||||||
|
|
@ -330,6 +363,7 @@ private:
|
||||||
|
|
||||||
virtual void visit(AstNodeModule* nodep) {
|
virtual void visit(AstNodeModule* nodep) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
|
m_modPastNum = 0;
|
||||||
//
|
//
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Reset defaults
|
// Reset defaults
|
||||||
|
|
@ -354,6 +388,7 @@ public:
|
||||||
explicit AssertVisitor(AstNetlist* nodep) {
|
explicit AssertVisitor(AstNetlist* nodep) {
|
||||||
m_beginp = NULL;
|
m_beginp = NULL;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
m_modPastNum = 0;
|
||||||
// Process
|
// Process
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,11 @@ private:
|
||||||
// NODE STATE/TYPES
|
// NODE STATE/TYPES
|
||||||
// STATE
|
// STATE
|
||||||
// Reset each module:
|
// Reset each module:
|
||||||
AstNodeSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock)
|
AstNodeSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock)
|
||||||
// Reset each assertion:
|
// Reset each assertion:
|
||||||
AstNodeSenItem* m_senip; // Last sensitivity
|
AstNodeSenItem* m_senip; // Last sensitivity
|
||||||
|
// Reset each always:
|
||||||
|
AstNodeSenItem* m_seniAlwaysp; // Last sensitivity in always
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
VL_DEBUG_FUNC; // Declare debug()
|
VL_DEBUG_FUNC; // Declare debug()
|
||||||
|
|
@ -55,7 +57,9 @@ private:
|
||||||
// Create sentree based on clocked or default clock
|
// Create sentree based on clocked or default clock
|
||||||
// Return NULL for always
|
// Return NULL for always
|
||||||
AstSenTree* newp = NULL;
|
AstSenTree* newp = NULL;
|
||||||
AstNodeSenItem* senip = m_senip ? m_senip : m_seniDefaultp;
|
AstNodeSenItem* senip = m_senip;
|
||||||
|
if (!senip) senip = m_seniDefaultp;
|
||||||
|
if (!senip) senip = m_seniAlwaysp;
|
||||||
if (!senip) {
|
if (!senip) {
|
||||||
nodep->v3error("Unsupported: Unclocked assertion");
|
nodep->v3error("Unsupported: Unclocked assertion");
|
||||||
newp = new AstSenTree(nodep->fileline(), NULL);
|
newp = new AstSenTree(nodep->fileline(), NULL);
|
||||||
|
|
@ -68,7 +72,8 @@ private:
|
||||||
m_senip = NULL;
|
m_senip = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
// VISITORS
|
||||||
|
//========== Statements
|
||||||
virtual void visit(AstClocking* nodep) {
|
virtual void visit(AstClocking* nodep) {
|
||||||
UINFO(8," CLOCKING"<<nodep<<endl);
|
UINFO(8," CLOCKING"<<nodep<<endl);
|
||||||
// Store the new default clock, reset on new module
|
// Store the new default clock, reset on new module
|
||||||
|
|
@ -81,16 +86,31 @@ private:
|
||||||
}
|
}
|
||||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstAlways* nodep) {
|
||||||
|
iterateAndNextNull(nodep->sensesp());
|
||||||
|
if (nodep->sensesp()) {
|
||||||
|
m_seniAlwaysp = nodep->sensesp()->sensesp();
|
||||||
|
}
|
||||||
|
iterateAndNextNull(nodep->bodysp());
|
||||||
|
m_seniAlwaysp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstNodePslCoverOrAssert* nodep) {
|
virtual void visit(AstNodePslCoverOrAssert* nodep) {
|
||||||
if (nodep->sentreep()) return; // Already processed
|
if (nodep->sentreep()) return; // Already processed
|
||||||
clearAssertInfo();
|
clearAssertInfo();
|
||||||
|
// Find PslClocking's burried under nodep->exprsp
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
clearAssertInfo();
|
clearAssertInfo();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslClocked* nodep) {
|
virtual void visit(AstPast* nodep) {
|
||||||
|
if (nodep->sentreep()) return; // Already processed
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
nodep->sentreep(newSenTree(nodep));
|
||||||
|
}
|
||||||
|
virtual void visit(AstPslClocked* nodep) {
|
||||||
|
// No need to iterate the body, once replace will get iterated
|
||||||
|
iterateAndNextNull(nodep->sensesp());
|
||||||
if (m_senip) {
|
if (m_senip) {
|
||||||
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
|
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion");
|
||||||
}
|
}
|
||||||
|
|
@ -120,6 +140,7 @@ public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
explicit AssertPreVisitor(AstNetlist* nodep) {
|
explicit AssertPreVisitor(AstNetlist* nodep) {
|
||||||
m_seniDefaultp = NULL;
|
m_seniDefaultp = NULL;
|
||||||
|
m_seniAlwaysp = NULL;
|
||||||
clearAssertInfo();
|
clearAssertInfo();
|
||||||
// Process
|
// Process
|
||||||
iterate(nodep);
|
iterate(nodep);
|
||||||
|
|
|
||||||
|
|
@ -2155,7 +2155,7 @@ public:
|
||||||
//
|
//
|
||||||
virtual void dump(std::ostream& str);
|
virtual void dump(std::ostream& str);
|
||||||
AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list
|
AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list
|
||||||
AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate
|
AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate
|
||||||
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
|
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
|
||||||
VAlwaysKwd keyword() const { return m_keyword; }
|
VAlwaysKwd keyword() const { return m_keyword; }
|
||||||
// Special accessors
|
// Special accessors
|
||||||
|
|
@ -5193,6 +5193,30 @@ public:
|
||||||
virtual string emitC() { return "hypot(%li,%ri)"; }
|
virtual string emitC() { return "hypot(%li,%ri)"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AstPast : public AstNodeMath {
|
||||||
|
// Verilog $past
|
||||||
|
// Parents: math
|
||||||
|
// Children: expression
|
||||||
|
public:
|
||||||
|
AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp) : AstNodeMath(fl) {
|
||||||
|
addOp1p(exprp);
|
||||||
|
addNOp2p(ticksp);
|
||||||
|
}
|
||||||
|
ASTNODE_NODE_FUNCS(Past)
|
||||||
|
virtual string emitVerilog() { V3ERROR_NA; return ""; }
|
||||||
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { V3ERROR_NA; }
|
||||||
|
virtual string emitC() { V3ERROR_NA; return "";}
|
||||||
|
virtual string emitSimpleOperator() { V3ERROR_NA; return "";}
|
||||||
|
virtual bool cleanOut() { V3ERROR_NA; return "";}
|
||||||
|
virtual int instrCount() const { return widthInstrs(); }
|
||||||
|
AstNode* exprp() const { return op1p(); } // op1 = expression
|
||||||
|
AstNode* ticksp() const { return op2p(); } // op2 = ticks or NULL means 1
|
||||||
|
AstSenTree* sentreep() const { return VN_CAST(op4p(), SenTree); } // op4 = clock domain
|
||||||
|
void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain
|
||||||
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
|
virtual bool same(const AstNode* samep) const { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
class AstPattern : public AstNodeMath {
|
class AstPattern : public AstNodeMath {
|
||||||
// Verilog '{a,b,c,d...}
|
// Verilog '{a,b,c,d...}
|
||||||
// Parents: AstNodeAssign, AstPattern, ...
|
// Parents: AstNodeAssign, AstPattern, ...
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
putqs(nodep,"end\n");
|
putqs(nodep,"end\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstPast* nodep) {
|
||||||
|
putfs(nodep, "$past(");
|
||||||
|
iterateAndNextNull(nodep->exprp());
|
||||||
|
if (nodep->ticksp()) {
|
||||||
|
puts(",");
|
||||||
|
iterateAndNextNull(nodep->ticksp());
|
||||||
|
}
|
||||||
|
puts(")");
|
||||||
|
}
|
||||||
virtual void visit(AstReturn* nodep) {
|
virtual void visit(AstReturn* nodep) {
|
||||||
putfs(nodep,"return ");
|
putfs(nodep,"return ");
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ public:
|
||||||
STMTDLY, // Delayed statement
|
STMTDLY, // Delayed statement
|
||||||
SYMRSVDWORD, // Symbol is Reserved Word
|
SYMRSVDWORD, // Symbol is Reserved Word
|
||||||
SYNCASYNCNET, // Mixed sync + async reset
|
SYNCASYNCNET, // Mixed sync + async reset
|
||||||
|
TICKCOUNT, // Too large tick count
|
||||||
UNDRIVEN, // No drivers
|
UNDRIVEN, // No drivers
|
||||||
UNOPT, // Unoptimizable block
|
UNOPT, // Unoptimizable block
|
||||||
UNOPTFLAT, // Unoptimizable block after flattening
|
UNOPTFLAT, // Unoptimizable block after flattening
|
||||||
|
|
@ -140,6 +141,7 @@ public:
|
||||||
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY",
|
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY",
|
||||||
"REALCVT", "REDEFMACRO",
|
"REALCVT", "REDEFMACRO",
|
||||||
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
"SELRANGE", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||||
|
"TICKCOUNT",
|
||||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
||||||
"UNPACKED", "UNSIGNED", "UNUSED",
|
"UNPACKED", "UNSIGNED", "UNUSED",
|
||||||
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
|
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
|
||||||
|
|
|
||||||
|
|
@ -798,6 +798,26 @@ private:
|
||||||
// We don't size the constant until we commit the widths, as need parameters
|
// We don't size the constant until we commit the widths, as need parameters
|
||||||
// to remain unsized, and numbers to remain unsized to avoid backp() warnings
|
// to remain unsized, and numbers to remain unsized to avoid backp() warnings
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstPast* nodep) {
|
||||||
|
if (m_vup->prelim()) {
|
||||||
|
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
|
||||||
|
nodep->dtypeFrom(nodep->exprp());
|
||||||
|
if (nodep->ticksp()) {
|
||||||
|
iterateCheckSizedSelf(nodep, "Ticks", nodep->ticksp(), SELF, BOTH);
|
||||||
|
V3Const::constifyParamsEdit(nodep->ticksp()); // ticksp may change
|
||||||
|
const AstConst* constp = VN_CAST(nodep->ticksp(), Const);
|
||||||
|
if (!constp || constp->toSInt() < 1) {
|
||||||
|
nodep->v3error("$past tick value must be constant and >= 1 (IEEE 2017 16.9.3)");
|
||||||
|
nodep->ticksp()->unlinkFrBack()->deleteTree();
|
||||||
|
} else {
|
||||||
|
if (constp->toSInt() > 10) {
|
||||||
|
nodep->v3warn(TICKCOUNT, "$past tick value of "<<constp->toSInt()
|
||||||
|
<<" may have a large performance cost");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void visit(AstRand* nodep) {
|
virtual void visit(AstRand* nodep) {
|
||||||
if (m_vup->prelim()) {
|
if (m_vup->prelim()) {
|
||||||
nodep->dtypeSetSigned32(); // Says the spec
|
nodep->dtypeSetSigned32(); // Says the spec
|
||||||
|
|
|
||||||
|
|
@ -444,6 +444,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
||||||
"$low" { FL; return yD_LOW; }
|
"$low" { FL; return yD_LOW; }
|
||||||
"$onehot" { FL; return yD_ONEHOT; }
|
"$onehot" { FL; return yD_ONEHOT; }
|
||||||
"$onehot0" { FL; return yD_ONEHOT0; }
|
"$onehot0" { FL; return yD_ONEHOT0; }
|
||||||
|
"$past" { FL; return yD_PAST; }
|
||||||
"$right" { FL; return yD_RIGHT; }
|
"$right" { FL; return yD_RIGHT; }
|
||||||
"$size" { FL; return yD_SIZE; }
|
"$size" { FL; return yD_SIZE; }
|
||||||
"$unpacked_dimensions" { FL; return yD_UNPACKED_DIMENSIONS; }
|
"$unpacked_dimensions" { FL; return yD_UNPACKED_DIMENSIONS; }
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,7 @@ class AstSenTree;
|
||||||
%token<fl> yD_LOW "$low"
|
%token<fl> yD_LOW "$low"
|
||||||
%token<fl> yD_ONEHOT "$onehot"
|
%token<fl> yD_ONEHOT "$onehot"
|
||||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||||
|
%token<fl> yD_PAST "$past"
|
||||||
%token<fl> yD_POW "$pow"
|
%token<fl> yD_POW "$pow"
|
||||||
%token<fl> yD_RANDOM "$random"
|
%token<fl> yD_RANDOM "$random"
|
||||||
%token<fl> yD_READMEMB "$readmemb"
|
%token<fl> yD_READMEMB "$readmemb"
|
||||||
|
|
@ -2776,8 +2777,12 @@ system_f_call_or_t<nodep>: // IEEE: part of system_tf_call (can be task or func)
|
||||||
| yD_LOW '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,$5); }
|
| yD_LOW '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,$5); }
|
||||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
|
||||||
|
| yD_PAST '(' expr ')' { $$ = new AstPast($1,$3, NULL); }
|
||||||
|
| yD_PAST '(' expr ',' expr ')' { $$ = new AstPast($1,$3, $5); }
|
||||||
|
| yD_PAST '(' expr ',' expr ',' expr ')' { $1->v3error("Unsupported: $past expr2 and clock arguments"); $$ = $3; }
|
||||||
|
| yD_PAST '(' expr ',' expr ',' expr ',' expr')' { $1->v3error("Unsupported: $past expr2 and clock arguments"); $$ = $3; }
|
||||||
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
||||||
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
|
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); $$ = NULL; }
|
||||||
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
| yD_RANDOM parenE { $$ = new AstRand($1); }
|
||||||
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
|
||||||
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2018 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
reg [63:0] crc;
|
||||||
|
reg [63:0] sum;
|
||||||
|
|
||||||
|
// Take CRC data and apply to testblock inputs
|
||||||
|
wire [31:0] in = crc[31:0];
|
||||||
|
|
||||||
|
Test test (/*AUTOINST*/
|
||||||
|
// Inputs
|
||||||
|
.clk (clk),
|
||||||
|
.in (in[31:0]));
|
||||||
|
|
||||||
|
Test2 test2 (/*AUTOINST*/
|
||||||
|
// Inputs
|
||||||
|
.clk (clk),
|
||||||
|
.in (in[31:0]));
|
||||||
|
|
||||||
|
// Test loop
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
crc <= 64'h5aef0c8d_d70a4497;
|
||||||
|
end
|
||||||
|
else if (cyc<10) begin
|
||||||
|
end
|
||||||
|
else if (cyc<90) begin
|
||||||
|
end
|
||||||
|
else if (cyc==99) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Test (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk, in
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
input [31:0] in;
|
||||||
|
|
||||||
|
reg [31:0] dly0;
|
||||||
|
reg [31:0] dly1;
|
||||||
|
reg [31:0] dly2;
|
||||||
|
reg [31:0] dly3;
|
||||||
|
|
||||||
|
// If called in an assertion, sequence, or property, the appropriate clocking event.
|
||||||
|
// Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit.
|
||||||
|
// Otherwise, if called in an action block of an assertion, the leading clock of the assertion is used.
|
||||||
|
// Otherwise, if called in a procedure, the inferred clock
|
||||||
|
// Otherwise, default clocking
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
dly0 <= in;
|
||||||
|
dly1 <= dly0;
|
||||||
|
dly2 <= dly1;
|
||||||
|
dly3 <= dly2;
|
||||||
|
// $past(expression, ticks, expression, clocking)
|
||||||
|
// In clock expression
|
||||||
|
if (dly0 != $past(in)) $stop;
|
||||||
|
if (dly0 != $past(in,1)) $stop;
|
||||||
|
if (dly1 != $past(in,2)) $stop;
|
||||||
|
end
|
||||||
|
|
||||||
|
assert property (@(posedge clk) dly0 == $past(in));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module Test2 (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk, in
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
input [31:0] in;
|
||||||
|
|
||||||
|
reg [31:0] dly0;
|
||||||
|
reg [31:0] dly1;
|
||||||
|
|
||||||
|
default clocking @(posedge clk); endclocking
|
||||||
|
assert property (@(posedge clk) dly1 == $past(in, 2));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
scenarios(vlt_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
fails => 1,
|
||||||
|
expect =>
|
||||||
|
'%Error: t/t_past_bad.v:\d+:.* \$past tick value must be constant and >= 1 \(IEEE 2017 16.9.3\)
|
||||||
|
%Warning-TICKCOUNT: t/t_past_bad.v:\d+: \$past tick value of 10000 may have a large performance cost
|
||||||
|
.*%Error: Exiting due to.*',
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2018 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (d, clk);
|
||||||
|
input d;
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
if ($past(d, 0)) $stop; // IEEE 16.9.3 must be >- 0
|
||||||
|
if ($past(d, 10000)) $stop; // TICKCOUNT
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/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.
|
||||||
|
|
||||||
|
scenarios(vlt_all => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
fails => 1,
|
||||||
|
expect =>
|
||||||
|
'%Error: t/t_past_unsup_bad.v:12: Unsupported: \$past expr2 and clock arguments
|
||||||
|
%Error: Exiting due to.*',
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2018 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t (d, clk);
|
||||||
|
input d;
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
// Unsupported
|
||||||
|
if ($past(d, 0, 0, 0)) $stop;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue