Fix generated inouts with duplicated modules, bug498.

This commit is contained in:
Wilson Snyder 2012-04-27 19:41:13 -04:00
parent d9598db117
commit 641024c235
6 changed files with 74 additions and 6 deletions

View File

@ -632,6 +632,8 @@ void AstVar::dump(ostream& str) {
else if (isOutput()) str<<" [O]"; else if (isOutput()) str<<" [O]";
} }
if (isConst()) str<<" [CONST]"; if (isConst()) str<<" [CONST]";
if (isPullup()) str<<" [PULLUP]";
if (isPulldown()) str<<" [PULLDOWN]";
if (isUsedClock()) str<<" [CLK]"; if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]"; if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]"; if (isUsedLoopIdx()) str<<" [LOOP]";

View File

@ -237,7 +237,7 @@ public:
//###################################################################### //######################################################################
// Inst class functions // Inst class functions
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp, bool forTristate) { AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*, bool forTristate) {
// If a pin connection is "simple" leave it as-is // If a pin connection is "simple" leave it as-is
// Else create a intermediate wire to perform the interconnect // Else create a intermediate wire to perform the interconnect
// Return the new assignment, if one was made // Return the new assignment, if one was made
@ -269,7 +269,8 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
AstNode* pinexprp = pinp->exprp()->unlinkFrBack(); AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name(); string newvarname = "__Vcellinp__"+cellp->name()+"__"+pinp->name();
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp); AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
modp->addStmtp(newvarp); // Important to add statement next to cell, in case there is a generate with same named cell
cellp->addNextHere(newvarp);
if (pinVarp->isInout()) { if (pinVarp->isInout()) {
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)"); pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
} else if (pinVarp->isOutput()) { } else if (pinVarp->isOutput()) {
@ -296,7 +297,7 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false)); pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
} }
pinp->widthSignedFrom(pinp->exprp()); pinp->widthSignedFrom(pinp->exprp());
if (assignp) modp->addStmtp(assignp); if (assignp) cellp->addNextHere(assignp);
//if (1||debug()) { pinp->dumpTree(cout," out:"); } //if (1||debug()) { pinp->dumpTree(cout," out:"); }
//if (1||debug()) { assignp->dumpTree(cout," aout:"); } //if (1||debug()) { assignp->dumpTree(cout," aout:"); }
} }

View File

@ -591,6 +591,7 @@ class TristateVisitor : public TristateBaseVisitor {
// Propagate any pullups/pulldowns upwards if necessary // Propagate any pullups/pulldowns upwards if necessary
if (refp) { if (refp) {
if (AstPull* pullp = (AstPull*) nodep->modVarp()->user3p()) { if (AstPull* pullp = (AstPull*) nodep->modVarp()->user3p()) {
UINFO(9, "propagate pull to "<<refp->varp());
if (!refp->varp()->user3p()) { if (!refp->varp()->user3p()) {
refp->varp()->user3p(pullp); refp->varp()->user3p(pullp);
} else { } else {
@ -636,6 +637,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstNode* newp = new AstPull(nodep->fileline(), AstNode* newp = new AstPull(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true), new AstVarRef(nodep->fileline(), nodep, true),
nodep->isPullup()); nodep->isPullup());
UINFO(9,"New pull "<<newp);
m_modp->addStmtp(newp); m_modp->addStmtp(newp);
// We'll iterate on the new AstPull later // We'll iterate on the new AstPull later
} }
@ -725,6 +727,7 @@ class TristateVisitor : public TristateBaseVisitor {
// //
outvarp->user1p(envarp); outvarp->user1p(envarp);
outvarp->user3p(invarp->user3p()); outvarp->user3p(invarp->user3p());
if (invarp->user3p()) UINFO(9, "propagate pull to "<<outvarp);
} else if (invarp->user1p()) { } else if (invarp->user1p()) {
envarp = invarp->user1p()->castNode()->castVar(); // From CASEEQ, foo === 1'bz envarp = invarp->user1p()->castNode()->castVar(); // From CASEEQ, foo === 1'bz
} }
@ -788,6 +791,7 @@ class TristateVisitor : public TristateBaseVisitor {
AstPull* pullp = (AstPull*)lhsp->user3p(); AstPull* pullp = (AstPull*)lhsp->user3p();
if (pullp && pullp->direction() == 1) { if (pullp && pullp->direction() == 1) {
pull.setAllBits1(); pull.setAllBits1();
UINFO(9,"Has pullup "<<pullp<<endl);
} else { } else {
pull.setAllBits0(); // default pull direction is down. pull.setAllBits0(); // default pull direction is down.
} }

View File

@ -868,9 +868,9 @@ portDirNetE: // IEEE: part of port, optional net type and/or direction
/* empty */ { } /* empty */ { }
// // Per spec, if direction given default the nettype. // // Per spec, if direction given default the nettype.
// // The higher level rule may override this VARDTYPE with one later in the parse. // // The higher level rule may override this VARDTYPE with one later in the parse.
| port_direction { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); } | port_direction { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); }
| port_direction net_type { VARDECL(PORT); VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARNET | port_direction { VARDECL(PORT); } net_type { VARDTYPE(NULL/*default_nettype*/); } // net_type calls VARNET
| net_type { } // net_type calls VARNET | net_type { } // net_type calls VARNET
; ;
port_declNetE: // IEEE: part of port_declaration, optional net type port_declNetE: // IEEE: part of port_declaration, optional net type

18
test_regress/t/t_tri_gen.pl Executable file
View File

@ -0,0 +1,18 @@
#!/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 (
);
execute (
check_finished=>1,
);
ok(1);
1;

View File

@ -0,0 +1,43 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
tri z0;
tri z1;
updown #(0) updown0 (.z(z0));
updown #(1) updown1 (.z(z1));
always @ (posedge clk) begin
if (z0 !== 0) $stop;
if (z1 !== 1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
module updown #(parameter UP=0)
(inout z);
generate
if (UP) begin
t_up sub (.z);
end
else begin
t_down sub (.z);
end
endgenerate
endmodule
module t_up (inout tri1 z);
endmodule
module t_down (inout tri0 z);
endmodule