Support --bbox-unsup parsing of event control expressions

This commit is contained in:
Wilson Snyder 2020-06-06 15:54:44 -04:00
parent 933e796cc2
commit 5cd5c05c05
7 changed files with 115 additions and 13 deletions

View File

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

View File

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

View File

@ -2201,9 +2201,9 @@ module_common_item<nodep>: // ==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<sentreep>: // ==IEEE: event_control
| '@' '*' { $$ = NULL; }
;
event_controlE<sentreep>:
/* empty */ { $$ = NULL; }
| event_control { $$ = $1; }
;
event_control<sentreep>: // ==IEEE: event_control
'@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); }
| '@' '(' '*' ')' { $$ = NULL; }
@ -2776,7 +2771,7 @@ event_control<sentreep>: // ==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<senitemp>: // IEEE: event_expression - split over several
@ -3023,7 +3018,7 @@ statement_item<nodep>: // 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; }

View File

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

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(
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
#execute(
# check_finished => 1,
# );
ok(1);
1;

View File

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

View File

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