diff --git a/Changes b/Changes index 7d9269d95..67802221a 100644 --- a/Changes +++ b/Changes @@ -23,6 +23,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix slicing mix of big and little-endian, bug1033. [Geoff Barrett] +**** Fix pattern assignment width propagation, bug1037. [Johan Bjork] + * Verilator 3.880 2015-12-19 diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 4a59173b8..a2fe5c56c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1600,7 +1600,8 @@ private: // Determine initial values vdtypep = memp; patp->dtypep(memp); - patp->accept(*this,WidthVP(memp,BOTH).p()); + patp->accept(*this,WidthVP(memp,BOTH).p()); // See visit(AstPatMember* + // Convert to concat for now AstNode* valuep = patp->lhssp()->unlinkFrBack(); if (valuep->castConst()) { @@ -1653,8 +1654,8 @@ private: vdtypep = arrayp->subDTypep(); // Don't want the RHS an array patp->dtypep(vdtypep); - // Determine values - might be another InitArray - patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p()); + // Determine values - might be another InitArray + patp->accept(*this,WidthVP(patp->dtypep(),BOTH).p()); // See visit(AstPatMember* // Convert to InitArray or constify immediately AstNode* valuep = patp->lhssp()->unlinkFrBack(); if (valuep->castConst()) { @@ -1760,8 +1761,8 @@ private: UINFO(9," PATMEMBER "<lhssp()->nextp()) nodep->v3fatalSrc("PatMember value should be singular w/replicates removed"); // Need to propagate assignment type downwards, even on prelim - nodep->iterateChildren(*this,WidthVP(nodep->dtypep(),BOTH).p()); - iterateCheck(nodep,"Pattern value",nodep->lhssp(),CONTEXT,FINAL,vdtypep,EXTEND_LHS); + nodep->iterateChildren(*this,WidthVP(nodep->dtypep(),PRELIM).p()); + iterateCheck(nodep,"Pattern value",nodep->lhssp(),ASSIGN,FINAL,vdtypep,EXTEND_LHS); } int visitPatMemberRep(AstPatMember* nodep) { uint32_t times = 1; diff --git a/test_regress/t/t_struct_pat_width.pl b/test_regress/t/t_struct_pat_width.pl new file mode 100755 index 000000000..4f0058853 --- /dev/null +++ b/test_regress/t/t_struct_pat_width.pl @@ -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 ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; + diff --git a/test_regress/t/t_struct_pat_width.v b/test_regress/t/t_struct_pat_width.v new file mode 100644 index 000000000..bf7c1e95d --- /dev/null +++ b/test_regress/t/t_struct_pat_width.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2016 by Wilson Snyder. + +module t (clk); + input clk; + typedef struct packed { + logic [2:0] _foo; + logic [2:0] _bar; + } struct_t; + + logic [2:0] meh; + struct_t param; + localparam integer twentyone = 21; + + // verilator lint_off WIDTH + assign param = '{ + _foo: twentyone % 8 + 1, + _bar: (twentyone / 8) + 1 + }; + assign meh = twentyone % 8 + 1; + // verilator lint_on WIDTH + + always @ (posedge clk) begin +`ifdef TEST_VERBOSE + $display("param: %d, %d, %b, %d", param._foo, param._bar, param, meh); +`endif + if (param._foo != 6) $stop; + if (param._bar != 3) $stop; + if (param != 6'b110011) $stop; + if (meh != 6) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule