diff --git a/Changes b/Changes index c8148f4f3..9c06d0728 100644 --- a/Changes +++ b/Changes @@ -7,17 +7,19 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Support concat selection (#2721). +**** Fix little endian interface pin swizzling (#2475). [Don Owen] + **** Fix TIMESCALE warnings on primitives (#2763). [Xuanqi] **** Fix $fread extra semicolon inside statements. [Leendert van Doorn] **** Fix class extends with VM_PARALLEL_BUILDS (#2775). [Iru Cai] -**** Fix shifts by > 32 bit values (#2785). [qrq992] +**** Fix shifts by > 32 bit values (#2785). [qrq992] -**** Fix examples not flushing vcd (#2787). [Richard E George] +**** Fix examples not flushing vcd (#2787). [Richard E George] -**** Fix little endian packed array pattern assignment (#2795). [Alex Torregrosa] +**** Fix little endian packed array pattern assignment (#2795). [Alex Torregrosa] * Verilator 4.108 2021-01-10 diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index fb950ae6c..bec64d058 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -396,7 +396,8 @@ private: AstNode* prevPinp = nullptr; // Clone the var referenced by the pin, and clone each var referenced by the varref // Clone pin varp: - for (int i = pinArrp->lo(); i <= pinArrp->hi(); ++i) { + for (int in = 0; in < pinArrp->elementsConst(); ++in) { + int i = pinArrp->left() + in * pinArrp->declRange().leftToRightInc(); string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__"; AstVar* varNewp = nullptr; @@ -429,16 +430,20 @@ private: newp->modVarp(varNewp); newp->name(newp->name() + "__BRA__" + cvtToStr(i) + "__KET__"); // And replace exprp with a new varxref - int offset = 0; const AstVarRef* varrefp = VN_CAST(newp->exprp(), VarRef); + int offset = 0; if (varrefp) { } else if (AstSliceSel* slicep = VN_CAST(newp->exprp(), SliceSel)) { varrefp = VN_CAST(slicep->fromp(), VarRef); UASSERT(VN_IS(slicep->rhsp(), Const), "Slices should be constant"); offset = VN_CAST(slicep->rhsp(), Const)->toSInt(); } - if (!varrefp) { newp->exprp()->v3error("Unexpected connection to arrayed port"); } - string newname = varrefp->name() + "__BRA__" + cvtToStr(i + offset) + "__KET__"; + int expr_i = i; + if (auto* exprArrp = VN_CAST(newp->exprp()->dtypep(), UnpackArrayDType)) + expr_i = exprArrp->left() + + (in + offset) * exprArrp->declRange().leftToRightInc(); + if (!varrefp) newp->exprp()->v3error("Unexpected connection to arrayed port"); + string newname = varrefp->name() + "__BRA__" + cvtToStr(expr_i) + "__KET__"; AstVarXRef* newVarXRefp = new AstVarXRef(nodep->fileline(), newname, "", VAccess::WRITE); newVarXRefp->varp(newp->modVarp()); diff --git a/test_regress/t/t_mod_interface_array4.pl b/test_regress/t/t_mod_interface_array4.pl new file mode 100755 index 000000000..2cb5eeaff --- /dev/null +++ b/test_regress/t/t_mod_interface_array4.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2021 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_mod_interface_array4.v b/test_regress/t/t_mod_interface_array4.v new file mode 100644 index 000000000..62ab2eebd --- /dev/null +++ b/test_regress/t/t_mod_interface_array4.v @@ -0,0 +1,78 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2021 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) + +interface intf (); + integer index; +endinterface + +module sub + ( + input logic clk, + input int cyc, + intf alh[1:2], + intf ahl[2:1], + intf blh[1:2], + intf bhl[2:1] + ); + + always @(posedge clk) begin + if (cyc == 5) begin + `checkh(alh[1].index, 2); + `checkh(alh[2].index, 1); + `checkh(ahl[1].index, 1); + `checkh(ahl[2].index, 2); + `checkh(blh[1].index, 1); + `checkh(blh[2].index, 2); + `checkh(bhl[1].index, 2); + `checkh(bhl[2].index, 1); + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule + +module t + ( + clk + ); + input clk; + + intf ifa1_intf[2:1](); + intf ifa2_intf[2:1](); + intf ifb1_intf[1:2](); + intf ifb2_intf[1:2](); + + int cyc; + + sub sub + ( + .clk, + .cyc, + .alh(ifa1_intf), + .ahl(ifa2_intf), + .blh(ifb1_intf), + .bhl(ifb2_intf) + ); + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 1) begin + ifa1_intf[1].index = 1; + ifa1_intf[2].index = 2; + ifa2_intf[1].index = 1; + ifa2_intf[2].index = 2; + ifb1_intf[1].index = 1; + ifb1_intf[2].index = 2; + ifb2_intf[1].index = 1; + ifb2_intf[2].index = 2; + end + end + +endmodule