Fix dead modules under generate cells not getting removed

git-svn-id: file://localhost/svn/verilator/trunk/verilator@773 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2006-09-01 14:05:20 +00:00
parent fe99abeccc
commit 7f1b16837e
7 changed files with 181 additions and 15 deletions

11
Changes
View File

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

View File

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

View File

@ -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<AstVar*> m_varsp; // List of all encountered to avoid another loop through three
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through three
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
vector<AstVarScope*> 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 "<<modp<<endl);
// And its children may now be killable too....
for (AstNode* nodep = modp->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;
}
}
}

View File

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

19
test_regress/t/t_func_lib.pl Executable file
View File

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

View File

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

View File

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