This commit is contained in:
parent
53c59e7ac7
commit
c90f9e53b7
1
Changes
1
Changes
|
|
@ -20,6 +20,7 @@ Verilator 5.039 devel
|
|||
* Add enum base data type, wire data type, and I/O versus data declaration checking per IEEE.
|
||||
* Add PROTOTYPEMIS error on missing and mismatching prototypes (#6206) (#6207). [Alex Solomatnikov]
|
||||
* Add error when trying to assign class object to variable of non-class types (#6237). [Igor Zaworski, Antmicro Ltd.]
|
||||
* Add ALWNEVER warning, for `always @*` that never execute (#6291).
|
||||
* Add error on class 'function static'.
|
||||
* Add `-DVERILATOR=1` definition to compiler flags when using verilated.mk.
|
||||
* Support member-level triggers for virtual interfaces (#5166) (#6148). [Yilou Wang]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
.. comment: generated by t_event_control_star_never_bad
|
||||
.. code-block:: sv
|
||||
|
||||
always @* a = 100;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
.. comment: generated by t_event_control_star_never_bad
|
||||
.. code-block::
|
||||
|
||||
%Warning-ALWNEVER: example.v:1:3 'always @*' will never execute as expression list is empty (no variables read)
|
||||
|
|
@ -111,6 +111,27 @@ List Of Warnings
|
|||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: ALWNEVER
|
||||
|
||||
Warning that an `always @*` statement has no variables being read,
|
||||
therefore the event list is empty, and as there are no events to wake
|
||||
the process up, the always will never execute.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. include:: ../../docs/gen/ex_ALWNEVER_faulty.rst
|
||||
|
||||
Results in:
|
||||
|
||||
.. include:: ../../docs/gen/ex_ALWNEVER_msg.rst
|
||||
|
||||
To repair, assuming the intent was to execute the statements at e.g.
|
||||
time zero, instead use an `always_comb` statement.
|
||||
|
||||
Ignoring this warning will only suppress the lint check; it will
|
||||
simulate correctly.
|
||||
|
||||
|
||||
.. option:: ASCRANGE
|
||||
|
||||
.. TODO better example
|
||||
|
|
|
|||
|
|
@ -406,6 +406,7 @@ public:
|
|||
ET_TRUE,
|
||||
//
|
||||
ET_COMBO, // Sensitive to all combo inputs to this block
|
||||
ET_COMBO_STAR, // Sensitive to all combo inputs to this block (from .*)
|
||||
ET_HYBRID, // This is like ET_COMB, but with explicit sensitivity to an expression
|
||||
ET_STATIC, // static variable initializers (runs before 'initial')
|
||||
ET_INITIAL, // 'initial' statements
|
||||
|
|
@ -423,6 +424,7 @@ public:
|
|||
true, // ET_TRUE
|
||||
|
||||
false, // ET_COMBO
|
||||
false, // ET_COMBO_STAR
|
||||
false, // ET_HYBRID
|
||||
false, // ET_STATIC
|
||||
false, // ET_INITIAL
|
||||
|
|
@ -443,13 +445,13 @@ public:
|
|||
}
|
||||
const char* ascii() const {
|
||||
static const char* const names[]
|
||||
= {"CHANGED", "BOTH", "POS", "NEG", "EVENT", "TRUE",
|
||||
"COMBO", "HYBRID", "STATIC", "INITIAL", "FINAL", "NEVER"};
|
||||
= {"CHANGED", "BOTH", "POS", "NEG", "EVENT", "TRUE", "COMBO",
|
||||
"COMBO_STAR", "HYBRID", "STATIC", "INITIAL", "FINAL", "NEVER"};
|
||||
return names[m_e];
|
||||
}
|
||||
const char* verilogKwd() const {
|
||||
static const char* const names[]
|
||||
= {"[changed]", "edge", "posedge", "negedge", "[event]", "[true]",
|
||||
= {"[changed]", "edge", "posedge", "negedge", "[event]", "[true]", "*",
|
||||
"*", "[hybrid]", "[static]", "[initial]", "[final]", "[never]"};
|
||||
return names[m_e];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1533,7 +1533,10 @@ public:
|
|||
AstNodeVarRef* varrefp() const { return VN_CAST(sensp(), NodeVarRef); }
|
||||
//
|
||||
bool isClocked() const { return edgeType().clockedStmt(); }
|
||||
bool isCombo() const { return edgeType() == VEdgeType::ET_COMBO; }
|
||||
bool isComboOrStar() const {
|
||||
return edgeType() == VEdgeType::ET_COMBO || edgeType() == VEdgeType::ET_COMBO_STAR;
|
||||
}
|
||||
bool isComboStar() const { return edgeType() == VEdgeType::ET_COMBO_STAR; }
|
||||
bool isHybrid() const { return edgeType() == VEdgeType::ET_HYBRID; }
|
||||
bool isStatic() const { return edgeType() == VEdgeType::ET_STATIC; }
|
||||
bool isInitial() const { return edgeType() == VEdgeType::ET_INITIAL; }
|
||||
|
|
@ -1550,6 +1553,10 @@ public:
|
|||
addSensesp(sensesp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstSenTree;
|
||||
bool sameNode(const AstNode* samep) const override {
|
||||
const AstSenTree* const asamep = VN_DBG_AS(samep, SenTree);
|
||||
return m_multi == asamep->m_multi;
|
||||
}
|
||||
void dump(std::ostream& str) const override;
|
||||
void dumpJson(std::ostream& str) const override;
|
||||
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
||||
|
|
|
|||
|
|
@ -1254,7 +1254,7 @@ bool AstSenTree::hasFinal() const {
|
|||
bool AstSenTree::hasCombo() const {
|
||||
UASSERT_OBJ(sensesp(), this, "SENTREE without any SENITEMs under it");
|
||||
for (AstSenItem* senp = sensesp(); senp; senp = VN_AS(senp->nextp(), SenItem)) {
|
||||
if (senp->isCombo()) return true;
|
||||
if (senp->isComboOrStar()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,8 +80,10 @@ class ClockVisitor final : public VNVisitor {
|
|||
AstNodeExpr* senEqnp = nullptr;
|
||||
for (AstSenItem* senp = nodesp; senp; senp = VN_AS(senp->nextp(), SenItem)) {
|
||||
UASSERT_OBJ(senp->edgeType() == VEdgeType::ET_TRUE, senp, "Should have been lowered");
|
||||
AstNodeExpr* const senOnep = senp->sensp()->cloneTree(false);
|
||||
senEqnp = senEqnp ? new AstOr{senp->fileline(), senEqnp, senOnep} : senOnep;
|
||||
if (senp->sensp()) {
|
||||
AstNodeExpr* const senOnep = senp->sensp()->cloneTree(false);
|
||||
senEqnp = senEqnp ? new AstOr{senp->fileline(), senEqnp, senOnep} : senOnep;
|
||||
}
|
||||
}
|
||||
return senEqnp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1119,7 +1119,8 @@ class DelayedVisitor final : public VNVisitor {
|
|||
// First gather all senItems
|
||||
AstSenItem* senItemp = nullptr;
|
||||
for (AstSenTree* const domainp : m_timingDomains) {
|
||||
senItemp = AstNode::addNext(senItemp, domainp->sensesp()->cloneTree(true));
|
||||
if (domainp->sensesp())
|
||||
senItemp = AstNode::addNext(senItemp, domainp->sensesp()->cloneTree(true));
|
||||
}
|
||||
m_timingDomains.clear();
|
||||
// Add them to all nba targets we gathered in this process
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
EC_FIRST_WARN, // Just a code so the program knows where to start warnings
|
||||
//
|
||||
ALWCOMBORDER, // Always_comb with unordered statements
|
||||
ALWNEVER, // always will never execute
|
||||
ASCRANGE, // Ascending bit range vector
|
||||
ASSIGNDLY, // Assignment delays
|
||||
ASSIGNIN, // Assigning to input
|
||||
|
|
@ -203,18 +204,18 @@ public:
|
|||
// Errors
|
||||
"LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR", "UNSUPPORTED",
|
||||
// Warnings
|
||||
" EC_FIRST_WARN", "ALWCOMBORDER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN", "BADSTDPRAGMA",
|
||||
"BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE", "CASEINCOMPLETE",
|
||||
"CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA", "CMPCONST",
|
||||
"COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG", "COVERIGN", "DECLFILENAME",
|
||||
"DEFOVERRIDE", "DEFPARAM", "DEPRECATED", "ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH",
|
||||
"ENUMVALUE", "EOFNEWLINE", "GENCLK", "GENUNNAMED", "HIERBLOCK", "IFDEPTH",
|
||||
"IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE", "LATCH", "LITENDIAN",
|
||||
"MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING", "MULTIDRIVEN", "MULTITOP",
|
||||
"NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT", "PARAMNODEFAULT",
|
||||
"PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL",
|
||||
"PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
|
||||
" EC_FIRST_WARN", "ALWCOMBORDER", "ALWNEVER", "ASCRANGE", "ASSIGNDLY", "ASSIGNIN",
|
||||
"BADSTDPRAGMA", "BADVLTPRAGMA", "BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ", "BSSPACE",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC",
|
||||
"CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG",
|
||||
"COVERIGN", "DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED", "ENCAPSULATED",
|
||||
"ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "GENCLK", "GENUNNAMED",
|
||||
"HIERBLOCK", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC",
|
||||
"IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
||||
"LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING",
|
||||
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT",
|
||||
"PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND",
|
||||
"PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
|
||||
"PROTOTYPEMIS", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY", "SELRANGE",
|
||||
"SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", "STATICVAR", "STMTDLY",
|
||||
"SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT",
|
||||
|
|
|
|||
|
|
@ -835,7 +835,7 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
if (alwaysp && alwaysp->keyword() == VAlwaysKwd::ALWAYS_COMB) {
|
||||
alwaysp->v3error("Event control statements not legal under always_comb "
|
||||
"(IEEE 1800-2023 9.2.2.2.2)\n"
|
||||
<< nodep->warnMore() << "... Suggest use a normal 'always'");
|
||||
<< alwaysp->warnMore() << "... Suggest use a normal 'always'");
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
} else if (alwaysp && !alwaysp->sentreep()) {
|
||||
// If the event control is at the top, move the sentree to the always
|
||||
|
|
|
|||
|
|
@ -162,9 +162,11 @@ class SchedGraphBuilder final : public VNVisitor {
|
|||
SchedSenVertex* const vtxp = new SchedSenVertex{m_graphp, senItemp};
|
||||
|
||||
// Connect up the variable references
|
||||
senItemp->sensp()->foreach([&](AstVarRef* refp) {
|
||||
new V3GraphEdge{m_graphp, getVarVertex(refp->varScopep()), vtxp, 1};
|
||||
});
|
||||
if (senItemp->sensp()) {
|
||||
senItemp->sensp()->foreach([&](AstVarRef* refp) {
|
||||
new V3GraphEdge{m_graphp, getVarVertex(refp->varScopep()), vtxp, 1};
|
||||
});
|
||||
}
|
||||
|
||||
// Store back to hash map so we can find it next time
|
||||
pair.first->second = vtxp;
|
||||
|
|
|
|||
|
|
@ -905,8 +905,11 @@ class TimingControlVisitor final : public VNVisitor {
|
|||
void visit(AstEventControl* nodep) override {
|
||||
// Do not allow waiting on local named events, as they get enqueued for clearing, but can
|
||||
// go out of scope before that happens
|
||||
if (!nodep->sentreep())
|
||||
if (!nodep->sentreep()) {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: no sense equation (@*)");
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
return;
|
||||
}
|
||||
FileLine* const flp = nodep->fileline();
|
||||
// Relink child statements after the event control
|
||||
if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext());
|
||||
|
|
|
|||
|
|
@ -6556,6 +6556,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
userIterateChildren(nodep, nullptr);
|
||||
}
|
||||
void visit(AstSenItem* nodep) override {
|
||||
if (nodep->isComboStar()) return;
|
||||
UASSERT_OBJ(nodep->isClocked(), nodep, "Invalid edge");
|
||||
// Optimize concat/replicate senitems; this has to be done here at the latest, otherwise we
|
||||
// emit WIDTHCONCAT if there are unsized constants
|
||||
|
|
|
|||
|
|
@ -168,6 +168,36 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
void visit(AstAlways* nodep) override {
|
||||
// As have not optimized SenTrees yet, an 'always .*' will be on first and only SenItem
|
||||
if (nodep->sentreep() && nodep->sentreep()->sensesp()
|
||||
&& nodep->sentreep()->sensesp()->isComboStar()) {
|
||||
const bool noReads = nodep->forall(
|
||||
[&](const AstNodeVarRef* refp) { return !refp->access().isReadOrRW(); });
|
||||
if (noReads) {
|
||||
nodep->v3warn(ALWNEVER, "'always @*' will never execute as expression list is "
|
||||
"empty (no variables read)\n"
|
||||
<< nodep->warnMore()
|
||||
<< "... Suggest use 'always_comb'");
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Iterate will delete ComboStar sentrees, so after above
|
||||
iterateChildren(nodep);
|
||||
editDType(nodep);
|
||||
}
|
||||
void visit(AstSenTree* nodep) override {
|
||||
if (nodep->sensesp() && nodep->sensesp()->isComboStar()) {
|
||||
UASSERT_OBJ(!nodep->sensesp()->nextp(), nodep, "Shouldn't be senitems after .*");
|
||||
// Make look like standalone always
|
||||
// (Rest of code assumed this before .* existed)
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
return;
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
editDType(nodep);
|
||||
}
|
||||
void visit(AstAttrOf* nodep) override {
|
||||
switch (nodep->attrType()) {
|
||||
case VAttrType::FUNC_ARG_PROTO: // FALLTHRU
|
||||
|
|
|
|||
|
|
@ -160,14 +160,17 @@ public:
|
|||
return new AstGatePin{rangep->fileline(), exprp, rangep->cloneTree(true)};
|
||||
}
|
||||
}
|
||||
AstSenTree* createClockSenTree(FileLine* fl, AstNodeExpr* exprp) {
|
||||
AstSenTree* createSenTreeChanged(FileLine* fl, AstNodeExpr* exprp) {
|
||||
return new AstSenTree{fl, new AstSenItem{fl, VEdgeType::ET_CHANGED, exprp}};
|
||||
}
|
||||
AstSenTree* createSenTreeDotStar(FileLine* fl) {
|
||||
return new AstSenTree{fl, new AstSenItem{fl, VEdgeType::ET_COMBO_STAR, nullptr}};
|
||||
}
|
||||
AstNodeExpr* createGlobalClockParseRef(FileLine* fl) {
|
||||
return new AstParseRef{fl, VParseRefExp::PX_TEXT, "__024global_clock", nullptr, nullptr};
|
||||
}
|
||||
AstSenTree* createGlobalClockSenTree(FileLine* fl) {
|
||||
return createClockSenTree(fl, createGlobalClockParseRef(fl));
|
||||
return createSenTreeChanged(fl, createGlobalClockParseRef(fl));
|
||||
}
|
||||
AstNode* createNettype(FileLine* fl, const string& name) {
|
||||
// As nettypes are unsupported, we just alias to logic
|
||||
|
|
@ -2817,7 +2820,6 @@ module_common_item<nodep>: // ==IEEE: module_common_item
|
|||
;
|
||||
|
||||
always_construct<nodep>: // IEEE: == always_construct
|
||||
// // Verilator only - event_control attached to always
|
||||
yALWAYS stmtBlock { $$ = new AstAlways{$1, VAlwaysKwd::ALWAYS, nullptr, $2}; }
|
||||
| yALWAYS_FF stmtBlock { $$ = new AstAlways{$1, VAlwaysKwd::ALWAYS_FF, nullptr, $2}; }
|
||||
| yALWAYS_LATCH stmtBlock { $$ = new AstAlways{$1, VAlwaysKwd::ALWAYS_LATCH, nullptr, $2}; }
|
||||
|
|
@ -3492,14 +3494,14 @@ attr_event_controlE<senTreep>:
|
|||
|
||||
attr_event_control<senTreep>: // ==IEEE: event_control
|
||||
'@' '(' event_expression ')' { $$ = new AstSenTree{$1, $3}; }
|
||||
| '@' '(' '*' ')' { $$ = nullptr; }
|
||||
| '@' '*' { $$ = nullptr; }
|
||||
| '@' '(' '*' ')' { $$ = GRAMMARP->createSenTreeDotStar($1); }
|
||||
| '@' '*' { $$ = GRAMMARP->createSenTreeDotStar($1); }
|
||||
;
|
||||
|
||||
event_control<senTreep>: // ==IEEE: event_control
|
||||
// UNSUP: Needs alignment with IEEE event_control and clocking_event
|
||||
'@' '(' '*' ')' { $$ = nullptr; }
|
||||
| '@' '*' { $$ = nullptr; }
|
||||
'@' '(' '*' ')' { $$ = GRAMMARP->createSenTreeDotStar($1); }
|
||||
| '@' '*' { $$ = GRAMMARP->createSenTreeDotStar($1); }
|
||||
// // IEEE: clocking_event
|
||||
| '@' '(' event_expression ')' { $$ = new AstSenTree{$1, $3}; }
|
||||
// // IEEE: hierarchical_event_identifier
|
||||
|
|
@ -4464,7 +4466,7 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
|
|||
| yD_CEIL '(' expr ')' { $$ = new AstCeilD{$1, $3}; }
|
||||
| yD_CHANGED '(' expr ')' { $$ = new AstLogNot{$1, new AstStable{$1, $3, nullptr}}; }
|
||||
| yD_CHANGED '(' expr ',' expr ')'
|
||||
{ $$ = new AstLogNot{$1, new AstStable{$1, $3, GRAMMARP->createClockSenTree($1, $5)}}; }
|
||||
{ $$ = new AstLogNot{$1, new AstStable{$1, $3, GRAMMARP->createSenTreeChanged($1, $5)}}; }
|
||||
| yD_CHANGED_GCLK '(' expr ')'
|
||||
{ $$ = new AstLogNot{$1, new AstStable{$1, $3, GRAMMARP->createGlobalClockSenTree($1)}}; }
|
||||
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2{$1, $3}; }
|
||||
|
|
@ -4487,7 +4489,7 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
|
|||
| yD_DIST_UNIFORM '(' expr ',' expr ',' expr ')' { $$ = new AstDistUniform{$1, $3, $5, $7}; }
|
||||
| yD_EXP '(' expr ')' { $$ = new AstExpD{$1, $3}; }
|
||||
| yD_FELL '(' expr ')' { $$ = new AstFell{$1, $3, nullptr}; }
|
||||
| yD_FELL '(' expr ',' expr ')' { $$ = new AstFell{$1, $3, GRAMMARP->createClockSenTree($1, $5)}; }
|
||||
| yD_FELL '(' expr ',' expr ')' { $$ = new AstFell{$1, $3, GRAMMARP->createSenTreeChanged($1, $5)}; }
|
||||
| yD_FELL_GCLK '(' expr ')' { $$ = new AstFell{$1, $3, GRAMMARP->createGlobalClockSenTree($1)}; }
|
||||
| yD_FEOF '(' expr ')' { $$ = new AstFEof{$1, $3}; }
|
||||
| yD_FERROR '(' expr ',' idClassSel ')' { $$ = new AstFError{$1, $3, $5}; }
|
||||
|
|
@ -4539,7 +4541,7 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
|
|||
| yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_RIGHT, $3, nullptr}; }
|
||||
| yD_RIGHT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_RIGHT, $3, $5}; }
|
||||
| yD_ROSE '(' expr ')' { $$ = new AstRose{$1, $3, nullptr}; }
|
||||
| yD_ROSE '(' expr ',' expr ')' { $$ = new AstRose{$1, $3, GRAMMARP->createClockSenTree($1, $5)}; }
|
||||
| yD_ROSE '(' expr ',' expr ')' { $$ = new AstRose{$1, $3, GRAMMARP->createSenTreeChanged($1, $5)}; }
|
||||
| yD_ROSE_GCLK '(' expr ')' { $$ = new AstRose{$1, $3, GRAMMARP->createGlobalClockSenTree($1)}; }
|
||||
| yD_RTOI '(' expr ')' { $$ = new AstRToIS{$1, $3}; }
|
||||
| yD_SAMPLED '(' expr ')' { $$ = new AstSampled{$1, $3}; }
|
||||
|
|
@ -4555,7 +4557,7 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
|
|||
| yD_STIME parenE
|
||||
{ $$ = new AstSel{$1, new AstTime{$1, VTimescale{VTimescale::NONE}}, 0, 32}; }
|
||||
| yD_STABLE '(' expr ')' { $$ = new AstStable{$1, $3, nullptr}; }
|
||||
| yD_STABLE '(' expr ',' expr ')' { $$ = new AstStable{$1, $3, GRAMMARP->createClockSenTree($1, $5)}; }
|
||||
| yD_STABLE '(' expr ',' expr ')' { $$ = new AstStable{$1, $3, GRAMMARP->createSenTreeChanged($1, $5)}; }
|
||||
| yD_STABLE_GCLK '(' expr ')' { $$ = new AstStable{$1, $3, GRAMMARP->createGlobalClockSenTree($1)}; }
|
||||
| yD_TAN '(' expr ')' { $$ = new AstTanD{$1, $3}; }
|
||||
| yD_TANH '(' expr ')' { $$ = new AstTanhD{$1, $3}; }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
%Error-UNSUPPORTED: t/t_event_control_star.v:19:14: Unsupported: no sense equation (@*)
|
||||
%Error-UNSUPPORTED: t/t_event_control_star.v:19:6: Unsupported: no sense equation (@*)
|
||||
19 | @* a = c;
|
||||
| ^
|
||||
| ^
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error: Verilator internal fault, sorry. Suggest trying --debug --gdbbt
|
||||
%Error: Command Failed
|
||||
%Error: Exiting due to
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--binary', '-Wno-ALWNEVER'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
int a;
|
||||
always @* a = 100;
|
||||
initial begin
|
||||
#1;
|
||||
if (a != 0) $stop;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
%Warning-ALWNEVER: t/t_event_control_star_never.v:9:3: 'always @*' will never execute as expression list is empty (no variables read)
|
||||
: ... note: In instance 't'
|
||||
: ... Suggest use 'always_comb'
|
||||
9 | always @* a = 100;
|
||||
| ^~~~~~
|
||||
... For warning description see https://verilator.org/warn/ALWNEVER?v=latest
|
||||
... Use "/* verilator lint_off ALWNEVER */" and lint_on around source to disable this message.
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('linter')
|
||||
test.top_filename = 't/t_event_control_star_never.v'
|
||||
|
||||
root = ".."
|
||||
|
||||
if not os.path.exists(root + "/.git"):
|
||||
test.skip("Not in a git repository")
|
||||
|
||||
test.lint(verilator_flags2=['--timing'], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.extract(in_filename=test.top_filename,
|
||||
out_filename=root + "/docs/gen/ex_ALWNEVER_faulty.rst",
|
||||
lines="9-9")
|
||||
|
||||
test.extract(in_filename=test.golden_filename,
|
||||
out_filename=root + "/docs/gen/ex_ALWNEVER_msg.rst",
|
||||
lines="1-1")
|
||||
|
||||
test.passes()
|
||||
|
|
@ -26,7 +26,7 @@ module t (/*AUTOARG*/
|
|||
sync_nblk <= 1'b1;
|
||||
end
|
||||
|
||||
always @* begin
|
||||
always_comb begin
|
||||
combo_blk = 1'b1;
|
||||
combo_nblk <= 1'b1;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ module t (/*AUTOARG*/
|
|||
|
||||
reg signed [ 82:0] W0226 ; //=47A4301EE3FB4133EE3DA
|
||||
|
||||
always @* begin : Block144
|
||||
always_comb begin : Block144
|
||||
W0226 = 83'sh47A4301EE3FB4133EE3DA;
|
||||
if ((W0226 >>> 8'sh1a) != 83'sh7ffffff1e90c07b8fed04) if (check) $stop;
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue