diff --git a/Changes b/Changes index 7591fe19b..31d91319e 100644 --- a/Changes +++ b/Changes @@ -35,6 +35,10 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix model restore crash, bug1013. [Jason McMullan] +**** Fix arrayed instances to unpacked of same size, bug1015. [Varun Koyyalagunta] + +**** Fix slices of unpacked arrays with non-zero LSBs. + * Verilator 3.878 2015-11-01 diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index cb02f54a1..cde203715 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -257,7 +257,20 @@ private: UINFO(4," PIN "<modVarp()->width(); int expwidth = nodep->exprp()->width(); - if (expwidth == pinwidth) { + pair pinDim = nodep->modVarp()->dtypep()->dimensions(false); + pair expDim = nodep->exprp()->dtypep()->dimensions(false); + UINFO(4," PINVAR "<modVarp()<exprp()<exprp()->unlinkFrBack(); + exprp = new AstArraySel (exprp->fileline(), exprp, + (m_instNum-m_instLsb)); + nodep->exprp(exprp); + } else if (expwidth == pinwidth) { // NOP: Arrayed instants: widths match so connect to each instance } else if (expwidth == pinwidth*m_cellRangep->elementsConst()) { // Arrayed instants: one bit for each of the instants (each assign is 1 pinwidth wide) @@ -276,7 +289,7 @@ private: } else { nodep->v3fatalSrc("Width mismatch; V3Width should have errored out."); } - } else if(AstArraySel* arrselp = nodep->exprp()->castArraySel()) { + } else if (AstArraySel* arrselp = nodep->exprp()->castArraySel()) { if (AstUnpackArrayDType* arrp = arrselp->lhsp()->dtypep()->castUnpackArrayDType()) { if (!arrp->subDTypep()->castIfaceRefDType()) return; diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 874b7a111..dc43af2a3 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -99,7 +99,9 @@ class SliceCloneVisitor : public AstNVisitor { // Reassign the bitp() if (nodep->length() > 1) { if (AstConst* bitp = nodep->bitp()->castConst()) { - unsigned idx = nodep->start() + m_selBits[m_vecIdx][m_depth]; + AstUnpackArrayDType* adtypep = nodep->fromp()->dtypep()->skipRefp()->castUnpackArrayDType(); + if (!adtypep) nodep->v3fatalSrc("slice select tried to expand an array without an ArrayDType"); + unsigned idx = nodep->start() + m_selBits[m_vecIdx][m_depth] - adtypep->lsb(); AstNode* constp = new AstConst(bitp->fileline(), V3Number(bitp->fileline(), bitp->castConst()->num().width(), idx)); bitp->replaceWith(constp); } else { @@ -272,7 +274,9 @@ class SliceVisitor : public AstNVisitor { int x = msb; msb = lsb; lsb = x; } UINFO(9," ArraySel-child: "<fileline(), topp, new AstConst(nodep->fileline(),lsb)); + AstArraySel* newp = new AstArraySel(nodep->fileline(), topp, + // "lsb-lsb": Arrays are zero-based so index 0 is always lsb + new AstConst(nodep->fileline(), lsb-lsb)); if (!newp->dtypep()) { newp->v3fatalSrc("ArraySel dtyping failed when resolving slice"); // see ArraySel constructor } @@ -503,5 +507,5 @@ public: void V3Slice::sliceAll(AstNetlist* rootp) { UINFO(2,__FUNCTION__<<": "<= 3); + V3Global::dumpCheckGlobalTree("slice.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } diff --git a/test_regress/t/t_inst_slice.pl b/test_regress/t/t_inst_slice.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_inst_slice.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_inst_slice.v b/test_regress/t/t_inst_slice.v new file mode 100644 index 000000000..397a8d0db --- /dev/null +++ b/test_regress/t/t_inst_slice.v @@ -0,0 +1,84 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2015 by Varun Koyyalagunta. + +// bug1015 +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer cyc=0; + reg [63:0] crc; + reg [63:0] sum; + + // Take CRC data and apply to testblock inputs + wire [1:0] i = crc[1:0]; + logic [1:0] o [13:10] ; + + Test test (/*AUTOINST*/ + // Outputs + .o (o/*[1:0].[3:0]*/), + // Inputs + .i (i[1:0])); + + // Aggregate outputs into a single result vector + wire [63:0] result = {32'h0, 6'h0,o[13], 6'h0,o[12], 6'h0,o[11], 6'h0,o[10]}; + + // Test loop + always @ (posedge clk) begin +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d crc=%x result=%x sum=%x\n",$time, cyc, crc, result, sum); +`endif + cyc <= cyc + 1; + crc <= {crc[62:0], crc[63]^crc[2]^crc[0]}; + sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]}; + if (cyc==0) begin + // Setup + crc <= 64'h5aef0c8d_d70a4497; + sum <= '0; + end + else if (cyc<10) begin + sum <= '0; + end + else if (cyc<90) begin + end + else if (cyc==99) begin + $write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum); + if (crc !== 64'hc77bb9b3784ea091) $stop; + // What checksum will we end up with (above print should match) +`define EXPECTED_SUM 64'hb42b2f48a0a9375a + if (sum !== `EXPECTED_SUM) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule + +module Test + ( + output logic [1:0] o [3:0], + //but this works + //logic [N-1:0] o + input [1:0] i); + + parameter N = 4; + + logic [1:0] a [3:0]; initial a = '{2'h0,2'h1,2'h2,2'h3}; + + sub sub [N-1:0] (.o (o), // many-to-many + .a (a), // many-to-many + .i (i)); // many-to-one +endmodule + +module sub + ( + input logic [1:0] i, + input logic [1:0] a, + output logic [1:0] o + ); + assign o = i + a; +endmodule diff --git a/test_regress/t/t_inst_slice_noinl.pl b/test_regress/t/t_inst_slice_noinl.pl new file mode 100755 index 000000000..56c4c8f6f --- /dev/null +++ b/test_regress/t/t_inst_slice_noinl.pl @@ -0,0 +1,21 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 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. + +top_filename("t/t_inst_slice.v"); + +compile ( + v_flags2 => ["-Oi"], + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1;