With VL_DEBUG, show wires causing convergance errors.

git-svn-id: file://localhost/svn/verilator/trunk/verilator@883 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2007-01-31 21:49:13 +00:00
parent 5dbae27f01
commit 8e7267f0e2
9 changed files with 133 additions and 7 deletions

View File

@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Add --trace-depth option for minimizing VCD file size. [Emerson Suguimoto]
*** With VL_DEBUG, show wires causing convergance errors. [Mike Shinkarovsky]
**** Fix isolate_assignments when many signals per always. [Mike Shinkarovsky]
**** Fix isolate_assignments across task/func temporaries. [Mike Shinkarovsky]

View File

@ -1635,12 +1635,18 @@ For example:
always @ (b) a=b
will toggle forever and thus the executable will give the didn't converge
error to prevent an infinite loop. To debug this, compile the Verilated
.cpp files with -DVL_DEBUG, then call Verilated::debug(1) in your main.cpp.
This will cause each module to print a message when it's invoked. From
that it should be obvious what routine(s) are part of the infinite loop.
Then in Gdb, add a break point at the routine entry point and "print *this"
on each loop so you can see what variables are changing each invocation.
error to prevent an infinite loop.
To debug this, run Verilator with --profile-cfuncs. Run make on the
generated files with "CPPFLAGS_ADD=-DVL_DEBUG". Then call
Verilated::debug(1) in your main.cpp.
This will cause each change in a variable to print a message. Near the
bottom you'll see the code and variable that causes the problem. For the
program above:
CHANGE: filename.v:1: b
CHANGE: filename.v:2: a
=back

View File

@ -687,6 +687,21 @@ class EmitCImp : EmitCStmts {
if (gotOne) {
puts(");\n");
//puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );");
for (vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
it != m_blkChangeDetVec.end(); ++it) {
AstChangeDet* nodep = *it;
if (nodep->lhsp()) {
puts("VL_DEBUG_IF( if(__req && (");
bool gotOneIgnore = false;
doubleOrDetect(nodep, gotOneIgnore);
string varname;
if (nodep->lhsp()->castVarRef()) {
varname = ": "+nodep->lhsp()->castVarRef()->varp()->prettyName();
}
puts(")) cout<<\"\tCHANGE: "+nodep->fileline()->ascii()
+varname+"\"<<endl; );");
}
}
}
}

View File

@ -198,10 +198,18 @@ public:
m_substTreep = NULL;
m_buffersOnly = buffersOnly;
m_lhsVarRef = NULL;
// Iterate
nodep->accept(*this);
// Check results
if (!m_substTreep) {
clearSimple("No assignment found\n");
}
for (GateVarRefList::const_iterator it = rhsVarRefs().begin();
it != rhsVarRefs().end(); ++it) {
if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) {
clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later.
}
}
if (debug()>=9 && !m_isSimple) {
nodep->dumpTree(cout,"\tgate!Ok: ");
}
@ -224,6 +232,7 @@ private:
//Entire netlist:
// AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet
// {statement}Node::userp -> GateLogicVertex* for this statement
// STATE
V3Graph m_graph; // Scoreboard of var usages/dependencies
GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
@ -458,6 +467,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
}
}
}
// Process it
if (!doit) {
if (allowMultiIn && (debug()>=9)) {
UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs

View File

@ -206,6 +206,7 @@ sub new {
'v3' => 0,
verilator_flags => [split(/\s+/,"-cc")],
verilator_make_gcc => 1,
verilated_debug => $Opt_Verilated_Debug,
stdout_filename => undef, # Redirect stdout
@_};
bless $self, $class;
@ -545,7 +546,7 @@ sub _make_main {
print $fh "int main(int argc, char **argv, char **env) {\n";
print $fh " double sim_time = 1000;\n";
}
print $fh " Verilated::debug(".($Opt_Verilated_Debug?1:0).");\n";
print $fh " Verilated::debug(".($self->{verilated_debug}?1:0).");\n";
print $fh " topp = new $VM_PREFIX (\"TOP\");\n";
my $set;
if ($self->sp) {

View File

@ -0,0 +1,26 @@
// $Id$
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2007 by Wilson Snyder.
module t (/*AUTOARG*/
// Outputs
x,
// Inputs
clk
);
`ifdef ALLOW_UNOPT
/*verilator lint_off UNOPTFLAT*/
`endif
input clk;
output x; // Avoid eliminating x
reg x;
always @* begin
x = ~x;
end
endmodule

View File

@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_unopt_converge.v");
#$Last_Self->{verilated_debug} = 1;
compile (
v_flags2 => ['+define+ALLOW_UNOPT'],
make_flags => 'CPPFLAGS_ADD=-DVL_DEBUG',
);
execute (
fails=>1,
expect=> '%Error: \S+:\d+: Verilated model didn\'t converge',
) if $Last_Self->{v3};
ok(1);
1;

View File

@ -0,0 +1,22 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_unopt_converge.v");
compile (
v_flags2 => ['+define+ALLOW_UNOPT'],
);
execute (
fails=>1,
expect=> '%Error: \S+:\d+: Verilated model didn\'t converge',
) if $Last_Self->{v3};
ok(1);
1;

View File

@ -0,0 +1,20 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; }
# $Id$
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2007 by Wilson Snyder. This program is free software; you can
# redistribute it and/or modify it under the terms of either the GNU
# General Public License or the Perl Artistic License.
top_filename("t/t_unopt_converge.v");
compile (
fails=>1,
expect=> '%Warning-UNOPT: t/t_unopt_converge.v:\d+: Signal unoptimizable: Feedback to public clock or circular logic: TOP->x
.*
%Error: Exiting due to '
) if $Last_Self->{v3};
ok(1);
1;