From db1af07d7235224c0bfcab688d60dfb0b277c289 Mon Sep 17 00:00:00 2001 From: John Coiner Date: Sat, 10 Mar 2018 12:52:11 -0500 Subject: [PATCH] On convergence errors, show activity. --- Changes | 2 + src/V3EmitC.cpp | 53 +++++++++++-------- test_regress/t/t_unopt_converge_initial.v | 25 +++++++++ .../t/t_unopt_converge_initial_run_bad.pl | 22 ++++++++ 4 files changed, 79 insertions(+), 23 deletions(-) create mode 100644 test_regress/t/t_unopt_converge_initial.v create mode 100755 test_regress/t/t_unopt_converge_initial_run_bad.pl diff --git a/Changes b/Changes index fe52b438d..0b29e3d61 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Add --no-debug-leak to reduce memory use under debug. [John Coiner] +**** On convergence errors, show activity. [John Coiner] + **** Fix GCC 8.0 issues, bug1273. **** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard] diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 4e2214edd..85360b519 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -981,6 +981,7 @@ class EmitCImp : EmitCStmts { // High level void emitImp(AstNodeModule* modp); void emitStaticDecl(AstNodeModule* modp); + void emitSettleLoop(std::string eval_call, bool initial); void emitWrapEval(AstNodeModule* modp); void emitInt(AstNodeModule* modp); @@ -1729,6 +1730,29 @@ void EmitCImp::emitSensitives() { } } +void EmitCImp::emitSettleLoop(std::string eval_call, bool initial) { + putsDecoration("// Evaluate till stable\n"); + puts("int __VclockLoop = 0;\n"); + puts("QData __Vchange = 1;\n"); + puts("do {\n"); + puts( eval_call + "\n"); + puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit()) + +")) {\n"); + puts( "// About to fail, so enable debug to see what's not settling.\n"); + puts( "// Note you must run make with OPT=-DVL_DEBUG for debug prints.\n"); + puts( "int __Vsaved_debug = Verilated::debug();\n"); + puts( "Verilated::debug(1);\n"); + puts( "__Vchange = _change_request(vlSymsp);\n"); + puts( "Verilated::debug(__Vsaved_debug);\n"); + puts( "VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't "); + if (initial) puts ("DC "); + puts( "converge\");\n"); + puts( "} else {\n"); + puts( "__Vchange = _change_request(vlSymsp);\n"); + puts( "}\n"); + puts("} while (VL_UNLIKELY(__Vchange));\n"); +} + void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("\nvoid "+modClassName(modp)+"::eval() {\n"); puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+++++TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n"); @@ -1750,20 +1774,10 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { puts("VL_DEBUG_IF(VL_DBG_MSGF(\"Train starting, trainId="+cvtToStr(trainId)+"\\n\"););\n"); puts("Verilated::trainId("+cvtToStr(trainId)+");\n"); } - - putsDecoration("// Evaluate till stable\n"); - puts("int __VclockLoop = 0;\n"); - puts("QData __Vchange = 1;\n"); - puts("while (VL_LIKELY(__Vchange)) {\n"); - puts( "VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n"); - if (v3Global.opt.trace()) { - puts("vlSymsp->__Vm_activity = true;\n"); - } - puts( "_eval(vlSymsp);\n"); - puts( "__Vchange = _change_request(vlSymsp);\n"); - puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit()) - +")) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n"); - puts("}\n"); + emitSettleLoop( + (string("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Clock loop\\n\"););\n") + + (v3Global.opt.trace() ? "vlSymsp->__Vm_activity = true;\n" : "") + + "_eval(vlSymsp);"), false); if (v3Global.opt.threads()) { // THREADED-TODO move to end of all trains on thread puts("Verilated::endOfThreadTrain(vlSymsp->__Vm_evalMsgQp);\n"); } @@ -1780,15 +1794,8 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) { if (v3Global.opt.trace()) { puts("vlSymsp->__Vm_activity = true;\n"); } - puts( "int __VclockLoop = 0;\n"); - puts( "QData __Vchange = 1;\n"); - puts( "while (VL_LIKELY(__Vchange)) {\n"); - puts( "_eval_settle(vlSymsp);\n"); - puts( "_eval(vlSymsp);\n"); - puts( "__Vchange = _change_request(vlSymsp);\n"); - puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit()) - +")) VL_FATAL_MT(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n"); - puts( "}\n"); + emitSettleLoop((string("_eval_settle(vlSymsp);\n") + +"_eval(vlSymsp);"), true); puts("}\n"); splitSizeInc(10); } diff --git a/test_regress/t/t_unopt_converge_initial.v b/test_regress/t/t_unopt_converge_initial.v new file mode 100644 index 000000000..7806042a4 --- /dev/null +++ b/test_regress/t/t_unopt_converge_initial.v @@ -0,0 +1,25 @@ +// 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 [31:0] x; // Avoid eliminating x + + reg [31:0] x; + always @* begin + x = x ^ $random; + end + +endmodule diff --git a/test_regress/t/t_unopt_converge_initial_run_bad.pl b/test_regress/t/t_unopt_converge_initial_run_bad.pl new file mode 100755 index 000000000..497906511 --- /dev/null +++ b/test_regress/t/t_unopt_converge_initial_run_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# 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 +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +top_filename("t/t_unopt_converge_initial.v"); + +compile ( + v_flags2 => ['+define+ALLOW_UNOPT'], + ); + +execute ( + fails=>1, + expect=> '%Error: \S+:\d+: Verilated model didn\'t DC converge', + ) if $Self->{vlt}; + +ok(1); +1;