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:
parent
5dbae27f01
commit
8e7267f0e2
2
Changes
2
Changes
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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; );");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
Loading…
Reference in New Issue