Fix internal error on interface arrays, bug1135.

This commit is contained in:
Wilson Snyder 2017-03-15 20:03:53 -04:00
parent e637dd2390
commit 8f8147d646
4 changed files with 174 additions and 24 deletions

View File

@ -15,6 +15,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix internal error on initializing parameter array, bug1131. [Jie Xu] **** Fix internal error on initializing parameter array, bug1131. [Jie Xu]
**** Fix internal error on interface arrays, bug1135. [John Stevenson]
* Verilator 3.900 2017-01-15 * Verilator 3.900 2017-01-15

View File

@ -143,7 +143,7 @@ private:
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
explicit InstVisitor(AstNode* nodep) { explicit InstVisitor(AstNetlist* nodep) {
m_modp=NULL; m_modp=NULL;
m_cellp=NULL; m_cellp=NULL;
// //
@ -162,6 +162,9 @@ private:
int m_instNum; // Current instantiation number int m_instNum; // Current instantiation number
int m_instLsb; // Current instantiation number int m_instLsb; // Current instantiation number
typedef map<string,AstVar*> VarNameMap;
VarNameMap m_modVarNameMap; // Per module, name of cloned variables
static int debug() { static int debug() {
static int level = -1; static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__); if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
@ -169,6 +172,11 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modVarNameMap.clear();
nodep->iterateChildren(*this);
}
virtual void visit(AstCell* nodep) { virtual void visit(AstCell* nodep) {
if (nodep->rangep()) { if (nodep->rangep()) {
m_cellRangep = nodep->rangep(); m_cellRangep = nodep->rangep();
@ -232,11 +240,16 @@ private:
AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType(); AstUnpackArrayDType* arrdtype = nodep->dtypep()->castUnpackArrayDType();
AstNode* prev = NULL; AstNode* prev = NULL;
for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) { for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) {
AstVar* varNewp = nodep->cloneTree(false);
AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false); AstIfaceRefDType* ifaceRefp = arrdtype->subDTypep()->castIfaceRefDType()->cloneTree(false);
arrdtype->addNextHere(ifaceRefp); arrdtype->addNextHere(ifaceRefp);
ifaceRefp->cellp(NULL); ifaceRefp->cellp(NULL);
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__";
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
if (it == m_modVarNameMap.end()) {
AstVar* varNewp = nodep->cloneTree(false);
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
varNewp->name(varNewName);
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__"); varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
varNewp->dtypep(ifaceRefp); varNewp->dtypep(ifaceRefp);
if (!prev) { if (!prev) {
@ -245,8 +258,9 @@ private:
prev->addNextHere(varNewp); prev->addNextHere(varNewp);
} }
} }
nodep->addNextHere(prev); }
if (debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; } if (prev) nodep->addNextHere(prev);
if (prev && debug()==9) { prev->dumpTree(cout, "newintf: "); cout << endl; }
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@ -319,10 +333,18 @@ private:
// Clone the var referenced by the pin, and clone each var referenced by the varref // Clone the var referenced by the pin, and clone each var referenced by the varref
// Clone pin varp: // Clone pin varp:
for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) { for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) {
AstVar* varNewp = pinVarp->cloneTree(false);
AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType(); AstIfaceRefDType* ifaceRefp = pinArrp->subDTypep()->castIfaceRefDType();
ifaceRefp->cellp(NULL); ifaceRefp->cellp(NULL);
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
VarNameMap::iterator it = m_modVarNameMap.find(varNewName);
AstVar* varNewp;
if (it != m_modVarNameMap.end()) {
varNewp = it->second;
} else {
varNewp = pinVarp->cloneTree(false);
m_modVarNameMap.insert(make_pair(varNewName, varNewp));
varNewp->name(varNewName);
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__"); varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__");
varNewp->dtypep(ifaceRefp); varNewp->dtypep(ifaceRefp);
if (!prevp) { if (!prevp) {
@ -330,6 +352,7 @@ private:
} else { } else {
prevp->addNextHere(varNewp); prevp->addNextHere(varNewp);
} }
}
// Now also clone the pin itself and update its varref // Now also clone the pin itself and update its varref
AstPin* newp = nodep->cloneTree(false); AstPin* newp = nodep->cloneTree(false);
newp->modVarp(varNewp); newp->modVarp(varNewp);
@ -348,11 +371,12 @@ private:
prevPinp->addNextHere(newp); prevPinp->addNextHere(newp);
} }
} }
if (prevp) {
pinVarp->replaceWith(prevp); pinVarp->replaceWith(prevp);
nodep->replaceWith(prevPinp);
pushDeletep(pinVarp); pushDeletep(pinVarp);
} // else pinVarp already unlinked when another instance did this step
nodep->replaceWith(prevPinp);
pushDeletep(nodep); pushDeletep(nodep);
} }
} }
@ -365,7 +389,7 @@ private:
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
explicit InstDeVisitor(AstNode* nodep) { explicit InstDeVisitor(AstNetlist* nodep) {
m_cellRangep=NULL; m_cellRangep=NULL;
m_instNum=0; m_instNum=0;
m_instLsb=0; m_instLsb=0;

View File

@ -0,0 +1,19 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# 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
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
compile (
verilator_flags2 => ["--lint-only"],
fails=>0,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
);
ok(1);
1;

View File

@ -0,0 +1,105 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2017 by John Stevenson.
package pkg;
typedef logic [31:0] unique_id_t;
typedef struct packed {
unique_id_t foo;
} inner_thing_t;
typedef struct packed {
inner_thing_t bar;
inner_thing_t baz;
} outer_thing_t;
endpackage
import pkg::*;
interface the_intf
#(parameter M=5);
outer_thing_t [M-1:0] things;
logic valid;
modport i (
output things,
output valid);
modport t (
input things,
input valid);
endinterface
module ThingMuxOH
#(
parameter NTHINGS = 1,
parameter M = 5 )
(
input logic [NTHINGS-1:0] select_oh,
the_intf.t things_in [NTHINGS-1:0],
the_intf.i thing_out
);
endmodule
module Thinker
#(
parameter M = 5,
parameter N = 2)
(
input logic clk,
input logic reset,
input unique_id_t uids[0:N-1],
the_intf.t thing_inp,
the_intf.i thing_out
);
the_intf #(.M(M)) curr_things [N-1:0] ();
the_intf #(.M(M)) prev_things [N-1:0] ();
the_intf #(.M(M)) curr_thing ();
the_intf #(.M(M)) prev_thing ();
logic [N-1:0] select_oh;
// 1st mux:
ThingMuxOH #(
.NTHINGS ( N ),
.M ( M ))
curr_thing_mux(
.select_oh( select_oh ),
.things_in( curr_things ),
.thing_out( curr_thing ));
// 2nd mux, comment this out and no problem:
ThingMuxOH #(
.NTHINGS ( N ),
.M ( M ))
prev_thing_mux(
.select_oh( select_oh ),
.things_in( prev_things ),
.thing_out( prev_thing ));
endmodule
module t
(
input logic clk,
input logic reset
);
localparam M = 5;
localparam N = 2;
unique_id_t uids[0:N-1];
the_intf #(.M(M)) thing_inp();
the_intf #(.M(M)) thing_out();
Thinker #(
.M ( M ),
.N ( N ))
thinker(
.clk ( clk ),
.reset ( reset ),
.uids ( uids ),
.thing_inp( thing_inp ),
.thing_out( thing_out ));
endmodule