From a9a49345ba86bf52b34b44941a587c4e09fd6a7f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 16 May 2012 19:31:24 -0400 Subject: [PATCH] Fix loop error message to report line, bug513. --- Changes | 2 ++ src/V3GraphAcyc.cpp | 27 ++++++++++++++------ test_regress/t/t_order_loop_bad.pl | 25 ++++++++++++++++++ test_regress/t/t_order_loop_bad.v | 41 ++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 8 deletions(-) create mode 100755 test_regress/t/t_order_loop_bad.pl create mode 100644 test_regress/t/t_order_loop_bad.v diff --git a/Changes b/Changes index bd80bbc77..6b9dd3ebc 100644 --- a/Changes +++ b/Changes @@ -31,6 +31,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix newlines in radix values, bug507. [Walter Lavino] +**** Fix loop error message to report line, bug513. [Jeremy Bennett] + * Verilator 3.833 2012/04/15 diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 93832ba57..e7bf4dd97 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -102,6 +102,7 @@ private: // GraphEdge::user() OrigEdgeList* Old graph edges // GraphVertex::user bool Detection of loops in simplifyDupIterate // MEMBERS + V3Graph* m_origGraphp; // Original graph V3Graph m_breakGraph; // Graph with only breakable edges represented V3List m_work; // List of vertices with optimization work left vector m_origEdgeDelp; // List of deletions to do when done @@ -183,7 +184,8 @@ private: avertexp->m_work.unlink(m_work, avertexp); } public: // CONSTRUCTORS - GraphAcyc(V3EdgeFuncP edgeFuncp) { + GraphAcyc(V3Graph* origGraphp, V3EdgeFuncP edgeFuncp) { + m_origGraphp = origGraphp; m_origEdgeFuncp = edgeFuncp; } ~GraphAcyc() { @@ -192,7 +194,7 @@ public: } m_origEdgeDelp.clear(); } - void main(V3Graph* origGraphp); + void main(); }; //-------------------------------------------------------------------- @@ -340,7 +342,16 @@ void GraphAcyc::simplifyOut (GraphAcycVertex* avertexp) { for (V3GraphEdge* nextp, *inEdgep = avertexp->inBeginp(); inEdgep; inEdgep=nextp) { nextp = inEdgep->inNextp(); V3GraphVertex* inVertexp = inEdgep->fromp(); - if (inVertexp == avertexp) v3fatalSrc("Non-cutable edge forms a loop "<reportLoops(&V3GraphEdge::followNotCutable, + avertexp->origVertexp()); // calls OrderGraph::loopsVertexCb + // Things are unlikely to end well at this point, + // but we'll try something to get to further errors... + inEdgep->cutable(true); + return; + } // Make a new edge connecting the two vertices directly edgeFromEdge(inEdgep, inVertexp, outVertexp); // Remove old edge @@ -522,17 +533,17 @@ bool GraphAcyc::placeIterate(GraphAcycVertex* vertexp, uint32_t currentRank) { //----- Main algorithm entry point -void GraphAcyc::main (V3Graph* origGraphp) { +void GraphAcyc::main () { m_breakGraph.userClearEdges(); // Color based on possible loops - origGraphp->stronglyConnected(m_origEdgeFuncp); + m_origGraphp->stronglyConnected(m_origEdgeFuncp); // Make a new graph with vertices that have only a single vertex // for each group of old vertices that are interconnected with unbreakable // edges (and thus can't represent loops - if we did the unbreakable // marking right, anyways) - buildGraph (origGraphp); + buildGraph (m_origGraphp); if (debug()>=6) m_breakGraph.dumpDotFilePrefixed("acyc_pre"); // Perform simple optimizations before any cuttings @@ -559,7 +570,7 @@ void GraphAcyc::main (V3Graph* origGraphp) { void V3Graph::acyclic(V3EdgeFuncP edgeFuncp) { UINFO(4, "Acyclic\n"); - GraphAcyc acyc (edgeFuncp); - acyc.main(this); + GraphAcyc acyc (this, edgeFuncp); + acyc.main(); UINFO(4, "Acyclic done\n"); } diff --git a/test_regress/t/t_order_loop_bad.pl b/test_regress/t/t_order_loop_bad.pl new file mode 100755 index 000000000..a2b472616 --- /dev/null +++ b/test_regress/t/t_order_loop_bad.pl @@ -0,0 +1,25 @@ +#!/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 ( + v_flags2 => ["--lint-only"], + fails=>1, + verilator_make_gcc => 0, + make_top_shell => 0, + make_main => 0, + expect=> +'%Error: Circular logic when ordering code .* +%Error: Example path: t/t_order_loop_bad.v:\d+: ALWAYS +%Error: Example path: t/t_order_loop_bad.v:\d+: v.ready +%Error: Example path: t/t_order_loop_bad.v:\d+: ACTIVE +.*', + ); + +ok(1); +1; diff --git a/test_regress/t/t_order_loop_bad.v b/test_regress/t/t_order_loop_bad.v new file mode 100644 index 000000000..231c2d0cd --- /dev/null +++ b/test_regress/t/t_order_loop_bad.v @@ -0,0 +1,41 @@ +// DESCRIPTION: Verilator: Non-cutable edge in loop +// +// This code (stripped down from a much larger application) has a loop between +// the use of ready in the first two always blocks. However it should +// trivially trigger the $write on the first clk posedge. +// +// This is a regression test against issue 513. +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Jeremy Bennett. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + reg ready; + + initial begin + ready = 1'b0; + end + + always @(posedge ready) begin + if ((ready === 1'b1)) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + always @(posedge ready) begin + if ((ready === 1'b0)) begin + ready = 1'b1 ; + end + end + + always @(posedge clk) begin + ready = 1'b1; + end + +endmodule