Fix generated inouts with duplicated modules, bug498.
This commit is contained in:
parent
d9598db117
commit
641024c235
|
|
@ -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]";
|
||||||
|
|
|
||||||
|
|
@ -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:"); }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue