diff --git a/Changes b/Changes index c1896f163..0b71f4d7d 100644 --- a/Changes +++ b/Changes @@ -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 diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 305db626d..88d36e490 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -984,32 +984,37 @@ class TristateVisitor : public TristateBaseVisitor { virtual void visit(AstPull* nodep) { UINFO(9,dbgState()<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 } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index dd66e32d6..ff23cfe1f 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -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.... } diff --git a/test_regress/t/t_tri_array_pull.pl b/test_regress/t/t_tri_array_pull.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_tri_array_pull.pl @@ -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; diff --git a/test_regress/t/t_tri_array_pull.v b/test_regress/t/t_tri_array_pull.v new file mode 100644 index 000000000..e1ce8e2af --- /dev/null +++ b/test_regress/t/t_tri_array_pull.v @@ -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 diff --git a/test_regress/t/t_tri_pullvec_bad.pl b/test_regress/t/t_tri_pullvec_bad.pl new file mode 100755 index 000000000..8c2848e04 --- /dev/null +++ b/test_regress/t/t_tri_pullvec_bad.pl @@ -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; diff --git a/test_regress/t/t_tri_pullvec_bad.v b/test_regress/t/t_tri_pullvec_bad.v new file mode 100644 index 000000000..c0724c40e --- /dev/null +++ b/test_regress/t/t_tri_pullvec_bad.v @@ -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