Fix pullup/pulldowns on bit selects, bug1274.

This commit is contained in:
Wilson Snyder 2018-02-10 19:08:07 -05:00
parent 7f5b1a402c
commit 1376e5de92
7 changed files with 141 additions and 26 deletions

View File

@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix GCC 8.0 issues, bug1273.
**** Fix pullup/pulldowns on bit selects, bug1274. [Rob Stoddard]
* Verilator 3.920 2018-02-01

View File

@ -984,32 +984,37 @@ class TristateVisitor : public TristateBaseVisitor {
virtual void visit(AstPull* nodep) {
UINFO(9,dbgState()<<nodep<<endl);
if (m_graphing) {
if (AstVarRef* lhsp = nodep->lhsp()->castVarRef()) {
lhsp->lvalue(true);
m_logicp = nodep;
m_tgraph.setTristate(nodep);
associateLogic(nodep, lhsp->varp());
m_logicp = NULL;
} else {
nodep->v3error("Unsupported pullup/down (weak driver) construct.");
}
} else {
// Replace any pullup/pulldowns with assignw logic and set the
// direction of the pull in the user3() data on the var. Given
// the complexity of merging tristate drivers at any level, the
// current limitation of this implementation is that a pullup/down
// gets applied to all bits of a bus and a bus cannot have drivers
// in opposite directions on indvidual pins.
if (AstVarRef* lhsp = nodep->lhsp()->castVarRef()) {
lhsp->lvalue(true);
m_tgraph.didProcess(nodep);
m_tgraph.didProcess(lhsp->varp());
AstVar* varp = lhsp->varp();
setPullDirection(varp, nodep);
} else {
nodep->v3error("Unsupported pullup/down (weak driver) construct.");
}
AstVarRef* varrefp = NULL;
if (nodep->lhsp()->castVarRef()) {
varrefp = nodep->lhsp()->castVarRef();
} else if (nodep->lhsp()->castSel()
&& nodep->lhsp()->castSel()->fromp()->castVarRef()) {
varrefp = nodep->lhsp()->castSel()->fromp()->castVarRef();
}
if (!varrefp) {
if (debug()>=4) nodep->dumpTree(cout, "- ");
nodep->v3error("Unsupported pullup/down (weak driver) construct.");
} else {
if (m_graphing) {
varrefp->lvalue(true);
m_logicp = nodep;
m_tgraph.setTristate(nodep);
associateLogic(nodep, varrefp->varp());
m_logicp = NULL;
} else {
// Replace any pullup/pulldowns with assignw logic and set the
// direction of the pull in the user3() data on the var. Given
// the complexity of merging tristate drivers at any level, the
// current limitation of this implementation is that a pullup/down
// gets applied to all bits of a bus and a bus cannot have drivers
// in opposite directions on indvidual pins.
varrefp->lvalue(true);
m_tgraph.didProcess(nodep);
m_tgraph.didProcess(varrefp->varp());
setPullDirection(varrefp->varp(), nodep);
}
}
if (!m_graphing) {
nodep->unlinkFrBack();
pushDeletep(nodep); VL_DANGLING(nodep); // Node must persist as user3p points to it
}

View File

@ -556,6 +556,7 @@ private:
// LSB is self-determined (IEEE 2012 11.5.1)
// We also use SELs to shorten a signed constant etc, in this case they are signed.
if (nodep->didWidth()) return;
if (!m_vup) nodep->v3fatalSrc("Select under an unexpected context");
if (m_vup->prelim()) {
if (debug()>=9) nodep->dumpTree(cout,"-selWidth: ");
userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT,PRELIM).p());
@ -949,6 +950,10 @@ private:
}
m_attrp = oldAttr;
}
virtual void visit(AstPull* nodep) {
// May have select underneath, let seek natural size
userIterateChildren(nodep, WidthVP(SELF,BOTH).p());
}
virtual void visit(AstText* nodep) {
// Only used in CStmts which don't care....
}

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, 2018 by Rod Steward.
module IOBUF ( input T, input I, output O, inout IO );
assign O = IO;
assign IO = T ? 1'bz : I;
endmodule
module t
(
input [7:0] inlines,
output [7:0] outlines,
inout [7:0] iolines,
input inctrl
);
generate for (genvar i = 4; i < 8; i = i+1) begin: Gen_D
IOBUF d ( .T(inctrl), .I(inlines[i]), .O(outlines[i]), .IO(iolines[i]) );
pullup d_pup (iolines[i]);
end
endgenerate
IOBUF d_0 ( .T(inctrl), .I(inlines[0]), .O(outlines[0]), .IO(iolines[0]) );
pullup d_0_pup (iolines[0]);
IOBUF d_1 ( .T(inctrl), .I(inlines[1]), .O(outlines[1]), .IO(iolines[1]) );
pullup d_1_pup (iolines[1]);
IOBUF d_2 ( .T(inctrl), .I(inlines[2]), .O(outlines[2]), .IO(iolines[2]) );
pullup d_2_pup (iolines[2]);
IOBUF d_3 ( .T(inctrl), .I(inlines[3]), .O(outlines[3]), .IO(iolines[3]) );
pullup d_3_pup (iolines[3]);
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,23 @@
#!/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.
$Self->{vlt} or $Self->skip("Verilator only test");
compile (
v_flags2 => ["--lint-only"],
fails=>$Self->{v3},
expect=>
'%Error: t/t_tri_pullvec_bad.v:\d+: Unsupported: Conflicting pull directions.
%Error: t/t_tri_pullvec_bad.v:\d+: ... Location of conflicting pull.
%Error: t/t_tri_pullvec_bad.v:\d+: Unsupported: Conflicting pull directions.
%Error: Exiting due to .*'
);
ok(1);
1;

View File

@ -0,0 +1,19 @@
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2018 by Wilson Snyder
module t (clk);
input clk;
tri [3:0] w;
pullup p0 (w[0]);
pulldown p1 (w[1]);
pulldown p2 (w[2]);
pullup p3 (w[3]);
always_ff @ (posedge clk) begin
if (w != 4'b1001) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule