diff --git a/Changes b/Changes index 36a705a1e..0e40eb6bf 100644 --- a/Changes +++ b/Changes @@ -5,21 +5,24 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.60** -*** Changed how internal functions are invoked to avoid aliasing in GCC 3.3+. - *** Added --inhibit-sim flag for environments using old __Vm_inhibitSim. *** Added `systemc_dtor for destructor extentions. [Allan Cochrane] *** Added -MP to make phony dependencies, ala GCC's. -**** Declare optimized lookup tables as 'static', to reduce D-Cache miss rate. +*** Changed how internal functions are invoked to reduce aliasing. + Useful when using GCC's -O2 or -fstrict-aliasing, to gain another ~4%. + +**** Fix coredump when unused modules have unused cells. [David Hewson] **** Fix memory leak when destroying modules. [John Stroebel] **** Fix $display %m name not matching Verilog name inside SystemC modules. -* Verilator 3.600 08/28/2006 +**** Declare optimized lookup tables as 'static', to reduce D-Cache miss rate. + +* Verilator 3.600 08/28/2006 Beta ** Support dotted cross-hierarchy variable and task references. diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 82f1b5964..1838cc2c0 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -88,7 +88,7 @@ private: bodysp = newFireAssert(nodep,message); // We assert the property is always true... so report when it fails // (Note this is opposite the behavior of coverage statements.) -//FIX 'never' operator: not hold in current or any future cycle + // Need: 'never' operator: not hold in current or any future cycle propp = new AstLogNot (nodep->fileline(), propp); } else { nodep->v3fatalSrc("Unknown node type"); diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index c6f3fdfd8..573b16113 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -34,6 +34,31 @@ #include "V3Dead.h" #include "V3Ast.h" +//###################################################################### + +class DeadModVisitor : public AstNVisitor { + // In a module that is dead, cleanup the in-use counts of the modules +private: + // NODE STATE + // ** Shared with DeadVisitor ** + // VISITORS + virtual void visit(AstCell* nodep, AstNUser*) { + nodep->iterateChildren(*this); + nodep->modp()->user(nodep->modp()->user() - 1); + } + //----- + virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate + virtual void visit(AstNode* nodep, AstNUser*) { + nodep->iterateChildren(*this); + } +public: + // CONSTRUCTORS + DeadModVisitor(AstModule* nodep) { + nodep->accept(*this); + } + virtual ~DeadModVisitor() {} +}; + //###################################################################### // Dead state, as a visitor of each AstNode @@ -46,8 +71,8 @@ private: // AstVarScope::user() -> int. Count of number of references // STATE - vector m_varsp; // List of all encountered to avoid another loop through three - vector m_vscsp; // List of all encountered to avoid another loop through three + vector m_varsp; // List of all encountered to avoid another loop through tree + vector m_vscsp; // List of all encountered to avoid another loop through tree bool m_elimUserVars; // Allow removal of user's vars //int debug() { return 9; } @@ -85,6 +110,8 @@ private: // METHODS void deadCheckMod() { // Kill any unused modules + // V3LinkCells has a graph that is capable of this too, but we need to do it + // after we've done all the generate blocks for (bool retry=true; retry; ) { retry=false; AstModule* nextmodp; @@ -93,14 +120,11 @@ private: if (modp->level()>2 && modp->user()==0) { // > 2 because L1 is the wrapper, L2 is the top user module UINFO(4," Dead module "<stmtsp(); nodep; nodep=nodep->nextp()) { - if (AstCell* cellp=nodep->castCell()) { - cellp->modp()->user( cellp->modp()->user() - 1); - retry = true; - } - } + // And its children may now be killable too; correct counts + // Recurse, as cells may not be directly under the module but in a generate + DeadModVisitor visitor(modp); modp->unlinkFrBack()->deleteTree(); modp=NULL; + retry = true; } } } diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 29b890e0e..fe9bad3c8 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -286,8 +286,14 @@ void process () { if (v3Global.opt.oGate()) { V3Gate::gateAll(v3Global.rootp()); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("gate.tree")); + // V3Gate calls constant propagation itself. } + // Remove unused vars + V3Const::constifyAll(v3Global.rootp()); + V3Dead::deadifyAll(v3Global.rootp(), true); + v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("const.tree")); + // Reorder assignments in pipelined blocks if (v3Global.opt.oReorder()) { V3Split::splitReorderAll(v3Global.rootp()); @@ -333,7 +339,7 @@ void process () { // Remove unused vars V3Const::constifyAll(v3Global.rootp()); - V3Dead::deadifyAll(v3Global.rootp(), false); + V3Dead::deadifyAll(v3Global.rootp(), true); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("const.tree")); #ifndef NEW_ORDERING diff --git a/test_regress/t/t_func_lib.pl b/test_regress/t/t_func_lib.pl new file mode 100755 index 000000000..6cb6deac8 --- /dev/null +++ b/test_regress/t/t_func_lib.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("./driver.pl", @ARGV, $0); die; } +# $Id$ +# 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 +# General Public License or the Perl Artistic License. + +compile ( + v_flags2 => ['-v', 't/t_func_lib_sub.v'], + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_lib.v b/test_regress/t/t_func_lib.v new file mode 100644 index 000000000..81161fb87 --- /dev/null +++ b/test_regress/t/t_func_lib.v @@ -0,0 +1,13 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003-2006 by Wilson Snyder. + +module t; + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule + diff --git a/test_regress/t/t_func_lib_sub.v b/test_regress/t/t_func_lib_sub.v new file mode 100644 index 000000000..d88dab5b6 --- /dev/null +++ b/test_regress/t/t_func_lib_sub.v @@ -0,0 +1,101 @@ +// $Id$ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003-2006 by Wilson Snyder. + +`define zednkw 200 + +module BreadAddrDP (zfghtn, cjtmau, knquim, kqxkkr); +input zfghtn; +input [4:0] cjtmau; +input vipmpg; +input [7:0] knquim; +input [7:0] kqxkkr; + +reg covfok; + +reg [15:0] xwieqw; +reg [2:0] ofnjjt; + +reg [37:0] hdsejo[0:1]; + +reg wxxzgd, tceppr, ratebp, fjizkr, iwwrnq; +reg vrqrih, ryyjxy; +reg fgzsox; + +wire xdjikl = ~wxxzgd & ~tceppr & ~ratebp & fjizkr; +wire iytyol = ~wxxzgd & ~tceppr & ratebp & ~fjizkr & ~xwieqw[10]; +wire dywooz = ~wxxzgd & ~tceppr & ratebp & ~fjizkr & xwieqw[10]; +wire qnpfus = ~wxxzgd & ~tceppr & ratebp & fjizkr; +wire fqlkrg = ~wxxzgd & tceppr & ~ratebp & ~fjizkr; + +wire ktsveg = hdsejo[0][6] | (hdsejo[0][37:34] == 4'h1); +wire smxixw = vrqrih | (ryyjxy & ktsveg); + +wire [7:0] grvsrs, kyxrft, uxhkka; + +wire [7:0] eianuv = 8'h01 << ofnjjt; +wire [7:0] jvpnxn = {8{qnpfus}} & eianuv; +wire [7:0] zlnzlj = {8{fqlkrg}} & eianuv; +wire [7:0] nahzat = {8{iytyol}} & eianuv; + +genvar i; +generate + for (i=0;i<8;i=i+1) + begin : dnlpyw + DecCountReg4 bzpytc (zfghtn, fgzsox, zlnzlj[i], + knquim[3:0], covfok, grvsrs[i]); + DecCountReg4 oghukp (zfghtn, fgzsox, zlnzlj[i], + knquim[7:4], covfok, kyxrft[i]); + DecCountReg4 ttvjoo (zfghtn, fgzsox, nahzat[i], + kqxkkr[3:0], covfok, uxhkka[i]); + end +endgenerate + +endmodule + +module DecCountReg4 (clk, fgzsox, fckiyr, uezcjy, covfok, juvlsh); +input clk, fgzsox, fckiyr, covfok; +input [3:0] uezcjy; +output juvlsh; + +task Xinit; +begin +`ifdef TEST_HARNESS + khgawe = 1'b0; +`endif +end +endtask +function X; +input vrdejo; +begin +`ifdef TEST_HARNESS + if ((vrdejo & ~vrdejo) !== 1'h0) khgawe = 1'b1; +`endif + X = vrdejo; +end +endfunction +task Xcheck; +input vzpwwy; +begin +end +endtask + +reg [3:0] udbvtl; + +assign juvlsh = |udbvtl; +wire [3:0] mppedc = {4{fgzsox}} & (fckiyr ? uezcjy : (udbvtl - 4'h1)); + +wire qqibou = ((juvlsh | fckiyr) & covfok) | ~fgzsox; + +always @(posedge clk) +begin + Xinit; + if (X(qqibou)) + udbvtl <= #`zednkw mppedc; + + Xcheck(fgzsox); +end + +endmodule