From 5cd5c05c05938f191a2ce19a1d50d910c33a51ae Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 6 Jun 2020 15:54:44 -0400 Subject: [PATCH] Support --bbox-unsup parsing of event control expressions --- src/V3AstNodes.h | 21 ++++++++++++++++ src/V3LinkParse.cpp | 31 ++++++++++++++++++++++++ src/verilog.y | 15 ++++-------- test_regress/t/t_event_control_unsup.out | 9 +++++++ test_regress/t/t_event_control_unsup.pl | 23 ++++++++++++++++++ test_regress/t/t_event_control_unsup.v | 22 +++++++++++++++++ test_regress/t/t_lint_comb_bad.out | 7 +++--- 7 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 test_regress/t/t_event_control_unsup.out create mode 100755 test_regress/t/t_event_control_unsup.pl create mode 100644 test_regress/t/t_event_control_unsup.v diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index faaead3ab..7b1691737 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -3116,6 +3116,7 @@ public: // virtual void dump(std::ostream& str) const; AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list + void sensesp(AstSenTree* nodep) { setOp1p(nodep); } VAlwaysKwd keyword() const { return m_keyword; } }; @@ -4803,6 +4804,26 @@ public: virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); } }; +class AstTimingControl : public AstNodeStmt { + // Parents: stmtlist +public: + AstTimingControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) + : ASTGEN_SUPER(fl) { + setNOp1p(sensesp); + setNOp2p(stmtsp); + } + ASTNODE_NODE_FUNCS(TimingControl) + virtual string verilogKwd() const { return "@(%l) %r"; } + virtual bool isGateOptimizable() const { return false; } + virtual bool isPredictOptimizable() const { return false; } + virtual bool isPure() const { return false; } + virtual bool isOutputter() const { return false; } + virtual int instrCount() const { return 0; } + virtual V3Hash sameHash() const { return V3Hash(); } + AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } + AstNode* stmtsp() const { return op2p(); } +}; + class AstTimeFormat : public AstNodeStmt { // Parents: stmtlist public: diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 8fb47dc64..680b76ebc 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -498,26 +498,57 @@ private: } virtual void visit(AstPrintTimeScale* nodep) VL_OVERRIDE { // Inlining may change hierarchy, so just save timescale where needed + cleanFileline(nodep); iterateChildren(nodep); nodep->name(m_modp->name()); nodep->timeunit(m_modp->timeunit()); } virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } virtual void visit(AstTime* nodep) VL_OVERRIDE { + cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } virtual void visit(AstTimeD* nodep) VL_OVERRIDE { + cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } virtual void visit(AstTimeImport* nodep) VL_OVERRIDE { + cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } + virtual void visit(AstTimingControl* nodep) VL_OVERRIDE { + cleanFileline(nodep); + iterateChildren(nodep); + AstAlways* alwaysp = VN_CAST(nodep->backp(), Always); + if (alwaysp && alwaysp->keyword() == VAlwaysKwd::ALWAYS_COMB) { + alwaysp->v3error("Timing control statements not legal under always_comb\n" + << nodep->warnMore() << "... Suggest use a normal 'always'"); + } else if (alwaysp && !alwaysp->sensesp()) { + // Verilator is still ony supporting SenTrees under an always, + // so allow the parser to handle everything and shim to + // historical AST here + if (AstSenTree* sensesp = nodep->sensesp()) { + sensesp->unlinkFrBackWithNext(); + alwaysp->sensesp(sensesp); + } + if (nodep->stmtsp()) alwaysp->addStmtp(nodep->stmtsp()->unlinkFrBackWithNext()); + } else { + if (!v3Global.opt.bboxUnsup()) { + nodep->v3error("Unsupported: timing control statement in this location\n" + << nodep->warnMore() + << "... Suggest have one timing control statement " + << "per procedure, at the top of the procedure"); + } + } + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + } virtual void visit(AstNode* nodep) VL_OVERRIDE { // Default: Just iterate diff --git a/src/verilog.y b/src/verilog.y index b1ac37556..b4e68ff55 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2201,9 +2201,9 @@ module_common_item: // ==IEEE: module_common_item | final_construct { $$ = $1; } // // IEEE: always_construct // // Verilator only - event_control attached to always - | yALWAYS event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS, $2,$3); } - | yALWAYS_FF event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_FF, $2,$3); } - | yALWAYS_LATCH event_controlE stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_LATCH, $2,$3); } + | yALWAYS stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS, NULL, $2); } + | yALWAYS_FF stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_FF, NULL, $2); } + | yALWAYS_LATCH stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_LATCH, NULL, $2); } | yALWAYS_COMB stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_COMB, NULL, $2); } // | loop_generate_construct { $$ = $1; } @@ -2757,11 +2757,6 @@ attr_event_control: // ==IEEE: event_control | '@' '*' { $$ = NULL; } ; -event_controlE: - /* empty */ { $$ = NULL; } - | event_control { $$ = $1; } - ; - event_control: // ==IEEE: event_control '@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); } | '@' '(' '*' ')' { $$ = NULL; } @@ -2776,7 +2771,7 @@ event_control: // ==IEEE: event_control // // 1995 delay with a sequence with parameters. // // Alternatively split this out of event_control, and delay_or_event_controlE // // and anywhere delay_or_event_controlE is called allow two expressions - //| '@' idClassSel '(' list_of_argumentsE ')' { } + //UNSUP '@' idClassSel '(' list_of_argumentsE ')' { } ; event_expression: // IEEE: event_expression - split over several @@ -3023,7 +3018,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); } - //UNSUP event_control stmtBlock { UNSUP } + | event_control stmtBlock { $$ = new AstTimingControl(FILELINE_OR_CRE($1), $1, $2); } //UNSUP cycle_delay stmtBlock { UNSUP } // | seq_block { $$ = $1; } diff --git a/test_regress/t/t_event_control_unsup.out b/test_regress/t/t_event_control_unsup.out new file mode 100644 index 000000000..c3920aa63 --- /dev/null +++ b/test_regress/t/t_event_control_unsup.out @@ -0,0 +1,9 @@ +%Error: t/t_event_control_unsup.v:14:7: Unsupported: timing control statement in this location + : ... Suggest have one timing control statement per procedure, at the top of the procedure + 14 | @(clk); + | ^ +%Error: t/t_event_control_unsup.v:16:7: Unsupported: timing control statement in this location + : ... Suggest have one timing control statement per procedure, at the top of the procedure + 16 | @(clk); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_event_control_unsup.pl b/test_regress/t/t_event_control_unsup.pl new file mode 100755 index 000000000..f4321c541 --- /dev/null +++ b/test_regress/t/t_event_control_unsup.pl @@ -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( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +#execute( +# check_finished => 1, +# ); + +ok(1); +1; diff --git a/test_regress/t/t_event_control_unsup.v b/test_regress/t/t_event_control_unsup.v new file mode 100644 index 000000000..ec4d2004b --- /dev/null +++ b/test_regress/t/t_event_control_unsup.v @@ -0,0 +1,22 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2003 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + initial begin; + @(clk); + $write("[%0t] Got\n", $time); + @(clk); + $write("[%0t] Got\n", $time); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_lint_comb_bad.out b/test_regress/t/t_lint_comb_bad.out index 902480d1d..391b09a97 100644 --- a/test_regress/t/t_lint_comb_bad.out +++ b/test_regress/t/t_lint_comb_bad.out @@ -1,4 +1,5 @@ -%Error: t/t_lint_comb_bad.v:14:16: syntax error, unexpected '@' +%Error: t/t_lint_comb_bad.v:14:4: Timing control statements not legal under always_comb + : ... Suggest use a normal 'always' 14 | always_comb @(*) begin - | ^ -%Error: Cannot continue + | ^~~~~~~~~~~ +%Error: Exiting due to