Fix little endian interface pin swizzling (#2475).

This commit is contained in:
Wilson Snyder 2021-02-20 22:11:20 -05:00
parent 191f76dd90
commit fd6edd90bc
4 changed files with 113 additions and 7 deletions

View File

@ -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

View File

@ -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());

View File

@ -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;

View File

@ -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