Fix loop error message to report line, bug513.

This commit is contained in:
Wilson Snyder 2012-05-16 19:31:24 -04:00
parent 8d960a2eb9
commit a9a49345ba
4 changed files with 87 additions and 8 deletions

View File

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

View File

@ -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<GraphAcycVertex*> m_work; // List of vertices with optimization work left
vector<OrigEdgeList*> 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 "<<avertexp);
if (inVertexp == avertexp) {
if (debug()) v3error("Non-cutable edge forms a loop, vertex="<<avertexp);
v3error("Circular logic when ordering code (non-cutable edge loop)");
m_origGraphp->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");
}

View File

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

View File

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