From c75de0f37c98982ab43a5e76b21ffb54b23e017c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 26 Apr 2012 20:40:13 -0400 Subject: [PATCH] Add INITIALDLY warning on initial assignments, bug478. --- Changes | 2 ++ bin/verilator | 9 ++++++++ src/V3Active.cpp | 26 +++++++++++++-------- src/V3Error.h | 4 +++- test_regress/t/t_initial_dlyass.pl | 19 ++++++++++++++++ test_regress/t/t_initial_dlyass.v | 31 ++++++++++++++++++++++++++ test_regress/t/t_initial_dlyass_bad.pl | 21 +++++++++++++++++ 7 files changed, 102 insertions(+), 10 deletions(-) create mode 100755 test_regress/t/t_initial_dlyass.pl create mode 100644 test_regress/t/t_initial_dlyass.v create mode 100755 test_regress/t/t_initial_dlyass_bad.pl diff --git a/Changes b/Changes index 30f13630e..75bc61418 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,8 @@ indicates the contributor was also the author of the fix; Thanks! *** Support nmos and pmos, bug488. [Alex Solomatnikov] +*** Add INITIALDLY warning on initial assignments, bug478. [Alex Solomatnikov] + *** Add PINMISSING and PINNOCONNECT lint checks. *** Fix generate operators not short circuiting, bug413. [by Jeremy Bennett] diff --git a/bin/verilator b/bin/verilator index ceb0210c8..ecfa11adc 100755 --- a/bin/verilator +++ b/bin/verilator @@ -2718,6 +2718,15 @@ command line to specify the top include source directory. Disabled by default as this is a code style warning; it will simulate correctly. +=item INITIALDLY + +Warns that you have a delayed assignment inside of an initial or final +block. If this message is suppressed, Verilator will convert this to a +non-delayed assignment. See also the COMBDLY warning. + +Ignoring this warning may make Verilator simulations differ from other +simulators. + =item LITENDIAN Warns that a vector is declared with little endian bit numbering diff --git a/src/V3Active.cpp b/src/V3Active.cpp index d9004ea0f..006811e03 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -164,16 +164,22 @@ public: // Active AssignDly replacement functions class ActiveDlyVisitor : public ActiveBaseVisitor { +public: + enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL }; private: - bool m_combo; // Combo logic + CheckType m_check; // Combo logic or other AstNode* m_alwaysp; // Always we're under AstNode* m_assignp; // In assign // VISITORS virtual void visit(AstAssignDly* nodep, AstNUser*) { - if (m_combo) { + if (m_check != CT_SEQ) { // Convert to a non-delayed assignment UINFO(5," ASSIGNDLY "<v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=)."); + if (m_check == CT_INITIAL) { + nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=)."); + } else { + nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=)."); + } AstNode* newp = new AstAssign (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()); @@ -182,7 +188,7 @@ private: } } virtual void visit(AstAssign* nodep, AstNUser*) { - if (!m_combo) { + if (m_check == CT_SEQ) { AstNode* las = m_assignp; m_assignp = nodep; nodep->lhsp()->iterateAndNext(*this); @@ -191,7 +197,7 @@ private: } virtual void visit(AstVarRef* nodep, AstNUser*) { AstVar* varp=nodep->varp(); - if (!m_combo + if (m_check == CT_SEQ && m_assignp && !varp->isUsedLoopIdx() // Ignore loop indicies && !varp->isTemp() @@ -213,9 +219,9 @@ private: } public: // CONSTUCTORS - ActiveDlyVisitor(AstNode* nodep, bool combo) { + ActiveDlyVisitor(AstNode* nodep, CheckType check) { m_alwaysp = nodep; - m_combo = combo; + m_check = check; m_assignp = NULL; nodep->accept(*this); } @@ -252,6 +258,7 @@ private: virtual void visit(AstInitial* nodep, AstNUser*) { // Relink to IACTIVE, unless already under it UINFO(4," INITIAL "<fileline()); nodep->unlinkFrBack(); wantactivep->addStmtsp(nodep); @@ -284,6 +291,7 @@ private: nodep->unlinkFrBack()->deleteTree(); nodep=NULL; return; } + ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL); if (!m_scopeFinalp) { m_scopeFinalp = new AstCFunc(nodep->fileline(), "_final", m_namer.scopep()); m_scopeFinalp->argTypes(EmitCBaseVisitor::symClassVar()); @@ -354,10 +362,10 @@ private: // Warn and/or convert any delayed assignments if (combo && !sequent) { - ActiveDlyVisitor dlyvisitor (nodep, true); + ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_COMBO); } else if (!combo && sequent) { - ActiveDlyVisitor dlyvisitor (nodep, false); + ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ); } } virtual void visit(AstAlways* nodep, AstNUser*) { diff --git a/src/V3Error.h b/src/V3Error.h index b2dbac90e..8c451102d 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -76,6 +76,7 @@ public: IMPLICIT, // Implicit wire IMPURE, // Impure function not being inlined INCABSPATH, // Include has absolute path + INITIALDLY, // Initial delayed statement LITENDIAN, // Little bit endian vector MODDUP, // Duplicate module MULTIDRIVEN, // Driven from multiple blocks @@ -119,7 +120,8 @@ public: "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST", "COMBDLY", "DEFPARAM", "DECLFILENAME", "ENDLABEL", "GENCLK", - "IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH", + "IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", + "INCABSPATH", "INITIALDLY", "LITENDIAN", "MODDUP", "MULTIDRIVEN", "PINMISSING", "PINNOCONNECT", diff --git a/test_regress/t/t_initial_dlyass.pl b/test_regress/t/t_initial_dlyass.pl new file mode 100755 index 000000000..fc8d21fa6 --- /dev/null +++ b/test_regress/t/t_initial_dlyass.pl @@ -0,0 +1,19 @@ +#!/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. + +compile ( + verilator_flags2 => ['-Wno-INITIALDLY'], + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_initial_dlyass.v b/test_regress/t/t_initial_dlyass.v new file mode 100644 index 000000000..629599a4b --- /dev/null +++ b/test_regress/t/t_initial_dlyass.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer cyc; initial cyc = 0; + integer a; + integer b; + + initial begin + a <= 22; + b <= 33; + end + + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc==99) begin + if (a != 22) $stop; + if (b != 33) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_initial_dlyass_bad.pl b/test_regress/t/t_initial_dlyass_bad.pl new file mode 100755 index 000000000..b0af1d491 --- /dev/null +++ b/test_regress/t/t_initial_dlyass_bad.pl @@ -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. + +top_filename("t_initial_dlyass.v"); + +compile ( + v_flags2 => ["--lint-only"], + fails=>1, + expect=> +qr{%Warning-INITIALDLY: t/t_initial_dlyass.v:\d+: Delayed assignments .* +%Error: Exiting due to.*}, + ); + +ok(1); +1;