diff --git a/src/V3Ast.h b/src/V3Ast.h index ca00b8040..47ae4dcc0 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2488,10 +2488,12 @@ public: class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt { protected: - AstNodeAssign(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) + AstNodeAssign(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, + AstNode* timingControlp = nullptr) : AstNodeStmt{t, fl} { setOp1p(rhsp); setOp2p(lhsp); + addNOp3p(timingControlp); dtypeFrom(lhsp); } @@ -2502,6 +2504,9 @@ public: // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 AstNode* rhsp() const { return op1p(); } // op1 = Assign from AstNode* lhsp() const { return op2p(); } // op2 = Assign to + // op3 = Timing controls (delays, event controls) + AstNode* timingControlp() const { return op3p(); } + void addTimingControlp(AstNode* const np) { addNOp3p(np); } void rhsp(AstNode* np) { setOp1p(np); } void lhsp(AstNode* np) { setOp2p(np); } virtual bool hasDType() const override { return true; } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 80ae000cc..404eff633 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2142,6 +2142,9 @@ public: virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + // op2 = Net delay + AstNode* delayp() const { return op2p(); } + void delayp(AstNode* const nodep) { setNOp2p(nodep); } AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) @@ -3481,8 +3484,8 @@ public: class AstAssign final : public AstNodeAssign { public: - AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Assign(fl, lhsp, rhsp) { + AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) + : ASTGEN_SUPER_Assign(fl, lhsp, rhsp, timingControlp) { dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Assign) @@ -3507,8 +3510,8 @@ public: class AstAssignDly final : public AstNodeAssign { public: - AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp) {} + AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) + : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp, timingControlp) {} ASTNODE_NODE_FUNCS(AssignDly) virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignDly(this->fileline(), lhsp, rhsp); @@ -3817,15 +3820,18 @@ public: class AstDelay final : public AstNodeStmt { // Delay statement public: - AstDelay(FileLine* fl, AstNode* lhsp) + AstDelay(FileLine* fl, AstNode* lhsp, AstNode* stmtsp) : ASTGEN_SUPER_Delay(fl) { setOp1p(lhsp); + setNOp2p(stmtsp); } ASTNODE_NODE_FUNCS(Delay) virtual bool same(const AstNode* samep) const override { return true; } // - AstNode* lhsp() const { return op1p(); } // op2 = Statements to evaluate + AstNode* lhsp() const { return op1p(); } // op1 = delay value void lhsp(AstNode* nodep) { setOp1p(nodep); } + void stmtsp(AstNode* nodep) { setOp2p(nodep); } // op2 = statements under delay + AstNode* stmtsp() const { return op2p(); } }; class AstGenCase final : public AstNodeCase { diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 3f3d06909..2cc65af6a 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -189,6 +189,8 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, nodep->ansi(m_pinAnsi); nodep->declTyped(m_varDeclTyped); nodep->lifetime(m_varLifetime); + nodep->delayp(m_netDelayp); + m_netDelayp = nullptr; if (GRAMMARP->m_varDecl != VVarType::UNKNOWN) nodep->combineType(GRAMMARP->m_varDecl); if (GRAMMARP->m_varIO != VDirection::NONE) { nodep->declDirection(GRAMMARP->m_varIO); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6118bcff4..69cee08f6 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -595,6 +595,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); return; } + if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBack()); nodep->v3warn(STMTDLY, "Unsupported: Ignoring delay on this delayed statement."); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } @@ -3984,6 +3985,11 @@ private: nodep->v3warn(E_UNSUPPORTED, "Unsupported: assignment of event data type"); } } + if (nodep->timingControlp()) { + nodep->timingControlp()->v3warn( + ASSIGNDLY, "Unsupported: Ignoring timing control on this assignment."); + nodep->timingControlp()->unlinkFrBackWithNext()->deleteTree(); + } if (VN_IS(nodep->rhsp(), EmptyQueue)) { UINFO(9, "= {} -> .delete(): " << nodep); if (!VN_IS(nodep->lhsp()->dtypep()->skipRefp(), QueueDType)) { diff --git a/src/verilog.y b/src/verilog.y index 3175ee9d0..a31704545 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -40,6 +40,13 @@ #define BBUNSUP(fl, msg) (fl)->v3warn(E_UNSUPPORTED, msg) #define GATEUNSUP(fl, tok) \ { BBUNSUP((fl), "Unsupported: Verilog 1995 gate primitive: " << (tok)); } +#define PRIMDLYUNSUP(nodep) \ + { \ + if (nodep) { \ + nodep->v3warn(ASSIGNDLY, "Unsupported: Ignoring delay on this primitive."); \ + nodep->deleteTree(); \ + } \ + } //====================================================================== // Statics (for here only) @@ -60,6 +67,7 @@ public: AstCase* m_caseAttrp = nullptr; // Current case statement for attribute adding AstNodeDType* m_varDTypep = nullptr; // Pointer to data type for next signal declaration AstNodeDType* m_memDTypep = nullptr; // Pointer to data type for next member declaration + AstNode* m_netDelayp = nullptr; // Pointer to delay for next signal declaration AstNodeModule* m_modp = nullptr; // Last module for timeunits bool m_pinAnsi = false; // In ANSI port list FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations @@ -138,6 +146,7 @@ public: if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr); m_varDTypep = dtypep; } + void setNetDelay(AstNode* netDelayp) { m_netDelayp = netDelayp; } void pinPush() { m_pinStack.push(m_pinNum); m_pinNum = 1; @@ -1708,11 +1717,13 @@ net_dataTypeE: var_data_type { $$ = $1; } | signingE rangeList delayE { $$ = GRAMMARP->addRange(new AstBasicDType{$2->fileline(), LOGIC, $1}, - $2, true); } // not implicit + $2, true); + GRAMMARP->setNetDelay($3); } // not implicit | signing { $$ = new AstBasicDType{$1, LOGIC, $1}; } // not implicit | /*implicit*/ delayE - { $$ = new AstBasicDType{CRELINE(), LOGIC}; } // not implicit + { $$ = new AstBasicDType{CRELINE(), LOGIC}; + GRAMMARP->setNetDelay($1); } // not implicit ; net_type: // ==IEEE: net_type @@ -2389,7 +2400,15 @@ module_common_item: // ==IEEE: module_common_item ; continuous_assign: // IEEE: continuous_assign - yASSIGN strengthSpecE delayE assignList ';' { $$ = $4; } + yASSIGN strengthSpecE delayE assignList ';' + { + $$ = $4; + if ($3) + for (auto* nodep = $$; nodep; nodep = nodep->nextp()) { + auto* const assignp = VN_AS(nodep, NodeAssign); + assignp->addTimingControlp(nodep == $$ ? $3 : $3->cloneTree(false)); + } + } ; initial_construct: // IEEE: initial_construct @@ -2630,22 +2649,21 @@ assignOne: variable_lvalue '=' expr { $$ = new AstAssignW($2,$1,$3); } ; -//UNSUPdelay_or_event_controlE: // IEEE: delay_or_event_control plus empty -//UNSUP /* empty */ { $$ = nullptr; } -//UNSUP | delay_control { $$ = $1; } -//UNSUP | event_control { $$ = $1; } +delay_or_event_controlE: // IEEE: delay_or_event_control plus empty + /* empty */ { $$ = nullptr; } + | delay_control { $$ = $1; } + | event_control { $$ = $1; } //UNSUP | yREPEAT '(' expr ')' event_control { } -//UNSUP ; - -delayE: - /* empty */ { } - | delay { } ; -delay: +delayE: + /* empty */ { $$ = nullptr; } + | delay { $$ = $1; } + ; + +delay: delay_control - { $1->v3warn(ASSIGNDLY, "Unsupported: Ignoring delay on this assignment/primitive."); - DEL($1); } + { $$ = $1; } ; delay_control: //== IEEE: delay_control @@ -2682,8 +2700,9 @@ netSig: // IEEE: net_decl_assignment - one element from { $$ = VARDONEA($1,*$1, nullptr, $2); } | netId sigAttrListE '=' expr { $$ = VARDONEA($1, *$1, nullptr, $2); - $$->addNext(new AstAssignW{$3, new AstVarRef{$1, *$1, VAccess::WRITE}, $4}); } - | netId variable_dimensionList sigAttrListE + auto* const assignp = new AstAssignW{$3, new AstVarRef{$1, *$1, VAccess::WRITE}, $4}; + if ($$->delayp()) assignp->addTimingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3 + $$->addNext(assignp); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } ; @@ -3141,12 +3160,10 @@ statement_item: // IEEE: statement_item | fexprLvalue '=' dynamic_array_new ';' { $$ = new AstAssign($2, $1, $3); } // // // IEEE: nonblocking_assignment - | fexprLvalue yP_LTE delayE expr ';' { $$ = new AstAssignDly($2,$1,$4); } - //UNSUP fexprLvalue yP_LTE delay_or_event_controlE expr ';' { UNSUP } - // - // // IEEE: procedural_continuous_assignment - | yASSIGN idClassSel '=' delayE expr ';' { $$ = new AstAssign($1,$2,$5); } - //UNSUP: delay_or_event_controlE above + | fexprLvalue yP_LTE delay_or_event_controlE expr ';' + { $$ = new AstAssignDly{$2, $1, $4, $3}; } + | yASSIGN idClassSel '=' delay_or_event_controlE expr ';' + { $$ = new AstAssign{$1, $2, $5, $4}; } | yDEASSIGN variable_lvalue ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 deassign"); } | yFORCE variable_lvalue '=' expr ';' @@ -3224,10 +3241,8 @@ statement_item: // IEEE: statement_item { // AssignDly because we don't have stratified queue, and need to // read events, clear next event, THEN apply this set $$ = new AstAssignDly($1, $2, new AstConst($1, AstConst::BitTrue())); } - //UNSUP yP_MINUSGTGT delay_or_event_controlE hierarchical_identifier/*event*/ ';' { UNSUP } - // // IEEE remove below - | yP_MINUSGTGT delayE idDotted/*hierarchical_identifier-event*/ ';' - { $$ = new AstAssignDly($1, $3, new AstConst($1, AstConst::BitTrue())); } + | yP_MINUSGTGT delay_or_event_controlE idDotted/*hierarchical_identifier-event*/ ';' + { $$ = new AstAssignDly{$1, $3, new AstConst{$1, AstConst::BitTrue()}, $2}; } // // // IEEE: loop_statement | yFOREVER stmtBlock { $$ = new AstWhile($1,new AstConst($1, AstConst::BitTrue()), $2); } @@ -3251,7 +3266,7 @@ statement_item: // IEEE: statement_item // | par_block { $$ = $1; } // // IEEE: procedural_timing_control_statement + procedural_timing_control - | delay_control stmtBlock { $$ = new AstDelay($1->fileline(), $1); $$->addNextNull($2); } + | delay_control stmtBlock { $$ = new AstDelay{$1->fileline(), $1, $2}; } | event_control stmtBlock { $$ = new AstEventControl(FILELINE_OR_CRE($1), $1, $2); } //UNSUP cycle_delay stmtBlock { UNSUP } // @@ -3313,11 +3328,10 @@ statementVerilatorPragmas: //UNSUP ; foperator_assignment: // IEEE: operator_assignment (for first part of expression) - fexprLvalue '=' delayE expr { $$ = new AstAssign($2,$1,$4); } + fexprLvalue '=' delay_or_event_controlE expr { $$ = new AstAssign{$2, $1, $4, $3}; } | fexprLvalue '=' yD_FOPEN '(' expr ')' { $$ = new AstFOpenMcd($3,$1,$5); } | fexprLvalue '=' yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen($3,$1,$5,$7); } // - //UNSUP ~f~exprLvalue '=' delay_or_event_controlE expr { UNSUP } //UNSUP ~f~exprLvalue yP_PLUS(etc) expr { UNSUP } | fexprLvalue yP_PLUSEQ expr { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),$3)); } | fexprLvalue yP_MINUSEQ expr { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),$3)); } @@ -4687,22 +4701,22 @@ stream_expressionOrDataType: // IEEE: from streaming_concatenation // Gate declarations gateDecl: - yBUF delayE gateBufList ';' { $$ = $3; } - | yBUFIF0 delayE gateBufif0List ';' { $$ = $3; } - | yBUFIF1 delayE gateBufif1List ';' { $$ = $3; } - | yNOT delayE gateNotList ';' { $$ = $3; } - | yNOTIF0 delayE gateNotif0List ';' { $$ = $3; } - | yNOTIF1 delayE gateNotif1List ';' { $$ = $3; } - | yAND delayE gateAndList ';' { $$ = $3; } - | yNAND delayE gateNandList ';' { $$ = $3; } - | yOR delayE gateOrList ';' { $$ = $3; } - | yNOR delayE gateNorList ';' { $$ = $3; } - | yXOR delayE gateXorList ';' { $$ = $3; } - | yXNOR delayE gateXnorList ';' { $$ = $3; } - | yPULLUP delayE gatePullupList ';' { $$ = $3; } - | yPULLDOWN delayE gatePulldownList ';' { $$ = $3; } - | yNMOS delayE gateBufif1List ';' { $$ = $3; } // ~=bufif1, as don't have strengths yet - | yPMOS delayE gateBufif0List ';' { $$ = $3; } // ~=bufif0, as don't have strengths yet + yBUF delayE gateBufList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yBUFIF0 delayE gateBufif0List ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yBUFIF1 delayE gateBufif1List ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yNOT delayE gateNotList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yNOTIF0 delayE gateNotif0List ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yNOTIF1 delayE gateNotif1List ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yAND delayE gateAndList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yNAND delayE gateNandList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yOR delayE gateOrList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yNOR delayE gateNorList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yXOR delayE gateXorList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yXNOR delayE gateXnorList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yPULLUP delayE gatePullupList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yPULLDOWN delayE gatePulldownList ';' { $$ = $3; PRIMDLYUNSUP($2); } + | yNMOS delayE gateBufif1List ';' { $$ = $3; PRIMDLYUNSUP($2); } // ~=bufif1, as don't have strengths yet + | yPMOS delayE gateBufif0List ';' { $$ = $3; PRIMDLYUNSUP($2); } // ~=bufif0, as don't have strengths yet // | yTRAN delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"tran"); } // Unsupported | yRCMOS delayE gateUnsupList ';' { $$ = $3; GATEUNSUP($3,"rcmos"); } // Unsupported diff --git a/test_regress/t/t_delay_stmtdly_bad.out b/test_regress/t/t_delay_stmtdly_bad.out index 87c088ddc..fe957acdb 100644 --- a/test_regress/t/t_delay_stmtdly_bad.out +++ b/test_regress/t/t_delay_stmtdly_bad.out @@ -1,17 +1,21 @@ -%Warning-ASSIGNDLY: t/t_delay.v:22:13: Unsupported: Ignoring delay on this assignment/primitive. +%Warning-ASSIGNDLY: t/t_delay.v:22:13: Unsupported: Ignoring timing control on this assignment. + : ... In instance t 22 | assign #(1.2000000000000000) dly1 = dly0 + 32'h1; | ^~~~~~~~~~~~~~~~~~ ... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. -%Warning-ASSIGNDLY: t/t_delay.v:27:19: Unsupported: Ignoring delay on this assignment/primitive. +%Warning-ASSIGNDLY: t/t_delay.v:27:19: Unsupported: Ignoring timing control on this assignment. + : ... In instance t 27 | dly0 <= #0 32'h11; | ^ -%Warning-ASSIGNDLY: t/t_delay.v:30:19: Unsupported: Ignoring delay on this assignment/primitive. +%Warning-ASSIGNDLY: t/t_delay.v:30:19: Unsupported: Ignoring timing control on this assignment. + : ... In instance t 30 | dly0 <= #0.12 dly0 + 32'h12; | ^~~~ -%Warning-ASSIGNDLY: t/t_delay.v:38:25: Unsupported: Ignoring delay on this assignment/primitive. +%Warning-ASSIGNDLY: t/t_delay.v:38:26: Unsupported: Ignoring timing control on this assignment. + : ... In instance t 38 | dly0 <= #(dly_s.dly) 32'h55; - | ^ + | ^~~ %Warning-STMTDLY: t/t_delay.v:43:11: Unsupported: Ignoring delay on this delayed statement. : ... In instance t 43 | #100 $finish; diff --git a/test_regress/t/t_gate_delay_unsup.out b/test_regress/t/t_gate_delay_unsup.out new file mode 100644 index 000000000..7a1697074 --- /dev/null +++ b/test_regress/t/t_gate_delay_unsup.out @@ -0,0 +1,12 @@ +%Warning-ASSIGNDLY: t/t_gate_basic.v:23:12: Unsupported: Ignoring delay on this primitive. + 23 | not #(0.108) NT0 (nt0, a[0]); + | ^~~~~ + ... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest + ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. +%Warning-ASSIGNDLY: t/t_gate_basic.v:24:11: Unsupported: Ignoring delay on this primitive. + 24 | and #1 AN0 (an0, a[0], b[0]); + | ^ +%Warning-ASSIGNDLY: t/t_gate_basic.v:25:12: Unsupported: Ignoring delay on this primitive. + 25 | nand #(2,3) ND0 (nd0, a[0], b[0], b[1]); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_gate_delay_unsup.pl b/test_regress/t/t_gate_delay_unsup.pl new file mode 100755 index 000000000..2f885e5ae --- /dev/null +++ b/test_regress/t/t_gate_delay_unsup.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. 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(linter => 1); + +top_filename("t/t_gate_basic.v"); + +lint( + verilator_flags2 => ["--lint-only -Wall -Wno-DECLFILENAME -Wno-UNUSED"], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_timing_intra_assign_delay.out b/test_regress/t/t_timing_intra_assign_delay.out new file mode 100644 index 000000000..f726ad4b4 --- /dev/null +++ b/test_regress/t/t_timing_intra_assign_delay.out @@ -0,0 +1,31 @@ +%Warning-ASSIGNDLY: t/t_timing_intra_assign_delay.v:12:11: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 12 | assign #10 val2 = val1; + | ^~ + ... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest + ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. +%Warning-STMTDLY: t/t_timing_intra_assign_delay.v:16:6: Unsupported: Ignoring delay on this delayed statement. + : ... In instance t + 16 | #10 val1 = 2; + | ^~ +%Error-UNSUPPORTED: t/t_timing_intra_assign_delay.v:17:5: Unsupported: fork statements + : ... In instance t + 17 | fork #5 val1 = 3; join_none + | ^~~~ +%Warning-ASSIGNDLY: t/t_timing_intra_assign_delay.v:18:13: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 18 | val1 = #10 val1 + 2; + | ^~ +%Warning-ASSIGNDLY: t/t_timing_intra_assign_delay.v:19:14: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 19 | val1 <= #10 val1 + 2; + | ^~ +%Error-UNSUPPORTED: t/t_timing_intra_assign_delay.v:20:5: Unsupported: fork statements + : ... In instance t + 20 | fork #5 val1 = 5; join_none + | ^~~~ +%Warning-STMTDLY: t/t_timing_intra_assign_delay.v:21:6: Unsupported: Ignoring delay on this delayed statement. + : ... In instance t + 21 | #20 $write("*-* All Finished *-*\n"); + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_timing_intra_assign_delay.pl b/test_regress/t/t_timing_intra_assign_delay.pl new file mode 100755 index 000000000..d61820774 --- /dev/null +++ b/test_regress/t/t_timing_intra_assign_delay.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. 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); + +lint( + verilator_flags2 => ['-Wall -Wno-DECLFILENAME'], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_timing_intra_assign_delay.v b/test_regress/t/t_timing_intra_assign_delay.v new file mode 100644 index 000000000..4ddc2461d --- /dev/null +++ b/test_regress/t/t_timing_intra_assign_delay.v @@ -0,0 +1,24 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t; + int val1, val2; + + always @val1 $write("[%0t] val1=%0d val2=%0d\n", $time, val1, val2); + + assign #10 val2 = val1; + + initial begin + val1 = 1; + #10 val1 = 2; + fork #5 val1 = 3; join_none + val1 = #10 val1 + 2; + val1 <= #10 val1 + 2; + fork #5 val1 = 5; join_none + #20 $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_timing_intra_assign_event.out b/test_regress/t/t_timing_intra_assign_event.out new file mode 100644 index 000000000..3fd9349f3 --- /dev/null +++ b/test_regress/t/t_timing_intra_assign_event.out @@ -0,0 +1,32 @@ +%Error-UNSUPPORTED: t/t_timing_intra_assign_event.v:15:5: Unsupported: event control statement in this location + : ... In instance t + : ... Suggest have one event control statement per procedure, at the top of the procedure + 15 | @e val = 2; + | ^ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_timing_intra_assign_event.v:16:5: Unsupported: fork statements + : ... In instance t + 16 | fork begin + | ^~~~ +%Warning-ASSIGNDLY: t/t_timing_intra_assign_event.v:21:11: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 21 | val = @e val + 2; + | ^ + ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. +%Warning-ASSIGNDLY: t/t_timing_intra_assign_event.v:22:12: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 22 | val <= @e val + 2; + | ^ +%Error-UNSUPPORTED: t/t_timing_intra_assign_event.v:23:5: Unsupported: fork statements + : ... In instance t + 23 | fork begin + | ^~~~ +%Warning-STMTDLY: t/t_timing_intra_assign_event.v:29:6: Unsupported: Ignoring delay on this delayed statement. + : ... In instance t + 29 | #1 $write("*-* All Finished *-*\n"); + | ^ +%Warning-STMTDLY: t/t_timing_intra_assign_event.v:33:12: Unsupported: Ignoring delay on this delayed statement. + : ... In instance t + 33 | initial #1 ->e; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_timing_intra_assign_event.pl b/test_regress/t/t_timing_intra_assign_event.pl new file mode 100755 index 000000000..d61820774 --- /dev/null +++ b/test_regress/t/t_timing_intra_assign_event.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. 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); + +lint( + verilator_flags2 => ['-Wall -Wno-DECLFILENAME'], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_timing_intra_assign_event.v b/test_regress/t/t_timing_intra_assign_event.v new file mode 100644 index 000000000..d98da3a66 --- /dev/null +++ b/test_regress/t/t_timing_intra_assign_event.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t; + int val; + event e; + + always @val $write("val=%0d\n", val); + + initial begin + val = 1; + @e val = 2; + fork begin + @e #1 val = 3; + ->e; + end join_none + ->e; + val = @e val + 2; + val <= @e val + 2; + fork begin + @e val = 5; + ->e; + end join_none + ->e; + ->e; + #1 $write("*-* All Finished *-*\n"); + $finish; + end + + initial #1 ->e; +endmodule diff --git a/test_regress/t/t_timing_net_delay.out b/test_regress/t/t_timing_net_delay.out new file mode 100644 index 000000000..116ccc0a0 --- /dev/null +++ b/test_regress/t/t_timing_net_delay.out @@ -0,0 +1,11 @@ +%Warning-ASSIGNDLY: t/t_timing_net_delay.v:13:15: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 13 | wire[3:0] #4 val1 = cyc; + | ^ + ... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest + ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. +%Warning-ASSIGNDLY: t/t_timing_net_delay.v:17:12: Unsupported: Ignoring timing control on this assignment. + : ... In instance t + 17 | assign #4 val2 = cyc; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_timing_net_delay.pl b/test_regress/t/t_timing_net_delay.pl new file mode 100755 index 000000000..d61820774 --- /dev/null +++ b/test_regress/t/t_timing_net_delay.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. 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); + +lint( + verilator_flags2 => ['-Wall -Wno-DECLFILENAME'], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_timing_net_delay.v b/test_regress/t/t_timing_net_delay.v new file mode 100644 index 000000000..aa125ca8c --- /dev/null +++ b/test_regress/t/t_timing_net_delay.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + wire[3:0] #4 val1 = cyc; + wire[3:0] #4 val2; + reg[3:0] cyc = 0; + + assign #4 val2 = cyc; + + always @(posedge clk) begin + cyc <= cyc + 1; +`ifdef TEST_VERBOSE + $write("[%0t] cyc=%0d, val1=%0d, val2=%0d\n", $time, cyc, val1, val2); +`endif + if (cyc >= 4 && val1 != cyc-1 && val2 != cyc-3) $stop; + if (cyc == 15) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule