Fix range inheritance on port without data type (#2753).

This commit is contained in:
Wilson Snyder 2021-03-11 19:22:19 -05:00
parent e88dff6929
commit 29ed866061
9 changed files with 376 additions and 12 deletions

View File

@ -16,6 +16,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix slice-assign overflow (#2803) (#2811). [David Turner]
**** Fix interface array connection ordering broken in v4.110 (#2827). [Don Owen]
**** Fix or-reduction on different scopes broken in 4.110 (#2828). [Yinan Xu]

View File

@ -396,7 +396,7 @@ private:
AstNode* prevPinp = nullptr;
// Clone the var referenced by the pin, and clone each var referenced by the varref
// Clone pin varp:
for (int in = 0; in < pinArrp->elementsConst(); ++in) {
for (int in = 0; in < pinArrp->elementsConst(); ++in) { // 0 = leftmost
int i = pinArrp->left() + in * pinArrp->declRange().leftToRightInc();
string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__";
AstVar* varNewp = nullptr;
@ -430,19 +430,22 @@ private:
newp->modVarp(varNewp);
newp->name(newp->name() + "__BRA__" + cvtToStr(i) + "__KET__");
// And replace exprp with a new varxref
const AstVarRef* varrefp = VN_CAST(newp->exprp(), VarRef);
int offset = 0;
if (varrefp) {
} else if (AstSliceSel* slicep = VN_CAST(newp->exprp(), SliceSel)) {
const AstVarRef* varrefp = VN_CAST(newp->exprp(), VarRef); // Maybe null
int expr_i = i;
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();
int slice_index
= slicep->declRange().left() + in * slicep->declRange().leftToRightInc();
auto* exprArrp = VN_CAST(varrefp->dtypep(), UnpackArrayDType);
UASSERT_OBJ(exprArrp, slicep, "Slice of non-array");
expr_i = slice_index + exprArrp->lo();
} else if (!varrefp) {
newp->exprp()->v3error("Unexpected connection to arrayed port");
} else if (auto* exprArrp = VN_CAST(varrefp->dtypep(), UnpackArrayDType)) {
expr_i = exprArrp->left() + in * exprArrp->declRange().leftToRightInc();
}
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);

View File

@ -76,4 +76,3 @@ module sub
end
endmodule

View File

@ -0,0 +1,24 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
top_filename("t/t_mod_interface_array4.v");
compile(
v_flags2 => ["-Oi"],
);
execute(
check_finished => 1,
);
ok(1);
1;

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,112 @@
// 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 value;
endinterface
module fanout
#(parameter int N = 1)
(
intf upstream,
intf downstream[N-1:0]
);
genvar i;
for (i = 0; i < N; i = i + 1)
assign downstream[i].value = upstream.value;
endmodule
module xbar
(
input logic clk,
input int cyc,
intf Masters[1:0]
);
localparam NUM_DEMUX_OUT = 2 * 4;
localparam NUM_MUX_IN = 2 * 4;
intf demuxOut[NUM_DEMUX_OUT-1:0]();
intf muxIn[NUM_MUX_IN-1:0]();
//fan out master connections to the crossbar matrix
fanout #(.N(4)) fanout_inst0
(.upstream(Masters[0]),
.downstream(demuxOut[3:0]));
fanout #(.N(4)) fanout_inst1
(.upstream(Masters[1]),
.downstream(demuxOut[7:4]));
//the crossbar matrix assignments, done as 1D arrays because verilator doesn't currently support >1D arrays of interfaces
genvar slv, mst;
for (slv = 0; slv < 4; slv = slv + 1) begin
for (mst = 0; mst < 2; mst = mst + 1) begin
localparam int muxIdx = (slv*2)+mst;
localparam int demuxIdx = slv+(mst*4);
assign muxIn[muxIdx].value = demuxOut[demuxIdx].value;
end
end
always @(posedge clk) begin
if (cyc == 5) begin
`checkh(Masters[0].value, 2);
`checkh(Masters[1].value, 1);
// The first 4 demuxOut values should have the value of the first Master
`checkh(demuxOut[0].value, Masters[0].value);
`checkh(demuxOut[1].value, Masters[0].value);
`checkh(demuxOut[2].value, Masters[0].value);
`checkh(demuxOut[3].value, Masters[0].value);
// The next 4 demuxOut values should have the value of the second Master
`checkh(demuxOut[4].value, Masters[1].value);
`checkh(demuxOut[5].value, Masters[1].value);
`checkh(demuxOut[6].value, Masters[1].value);
`checkh(demuxOut[7].value, Masters[1].value);
// Each 2 mux inputs should have one input from each master, in order from low to high
`checkh(muxIn[0].value, Masters[0].value);
`checkh(muxIn[1].value, Masters[1].value);
`checkh(muxIn[2].value, Masters[0].value);
`checkh(muxIn[3].value, Masters[1].value);
`checkh(muxIn[4].value, Masters[0].value);
`checkh(muxIn[5].value, Masters[1].value);
`checkh(muxIn[6].value, Masters[0].value);
`checkh(muxIn[7].value, Masters[1].value);
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module t
(
clk
);
input clk;
intf masters[1:0]();
int cyc;
xbar sub
(.clk,
.cyc,
.Masters(masters));
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 1) begin
masters[0].value <= 2;
masters[1].value <= 1;
end
end
endmodule

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,158 @@
// 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 t
(
clk
);
input clk;
intf ifa1_intf[4:1]();
intf ifa2_intf[4:1]();
intf ifb1_intf[1:4]();
intf ifb2_intf[1:4]();
int cyc;
sub sub0
(
.n(0),
.clk,
.cyc,
.alh(ifa1_intf[2:1]),
.ahl(ifa2_intf[2:1]),
.blh(ifb1_intf[1:2]),
.bhl(ifb2_intf[1:2])
);
sub sub1
(
.n(1),
.clk,
.cyc,
.alh(ifa1_intf[4:3]),
.ahl(ifa2_intf[4:3]),
.blh(ifb1_intf[3:4]),
.bhl(ifb2_intf[3:4])
);
`ifndef verilator // Backwards slicing not supported
sub sub2
(
.n(2),
.clk,
.cyc,
.alh(ifa1_intf[1:2]), // backwards vs decl
.ahl(ifa2_intf[1:2]), // backwards vs decl
.blh(ifb1_intf[2:1]), // backwards vs decl
.bhl(ifb2_intf[2:1]) // backwards vs decl
);
sub sub3
(
.n(3),
.clk,
.cyc,
.alh(ifa1_intf[3:4]), // backwards vs decl
.ahl(ifa2_intf[3:4]), // backwards vs decl
.blh(ifb1_intf[4:3]), // backwards vs decl
.bhl(ifb2_intf[4:3]) // backwards vs decl
);
`endif
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 1) begin
ifa1_intf[1].index = 'h101;
ifa1_intf[2].index = 'h102;
ifa1_intf[3].index = 'h103;
ifa1_intf[4].index = 'h104;
ifa2_intf[1].index = 'h201;
ifa2_intf[2].index = 'h202;
ifa2_intf[3].index = 'h203;
ifa2_intf[4].index = 'h204;
ifb1_intf[1].index = 'h301;
ifb1_intf[2].index = 'h302;
ifb1_intf[3].index = 'h303;
ifb1_intf[4].index = 'h304;
ifb2_intf[1].index = 'h401;
ifb2_intf[2].index = 'h402;
ifb2_intf[3].index = 'h403;
ifb2_intf[4].index = 'h404;
end
end
endmodule
module sub
(
input logic clk,
input int cyc,
input int n,
intf alh[1:2],
intf ahl[2:1],
intf blh[1:2],
intf bhl[2:1]
);
always @(posedge clk) begin
if (cyc == 5) begin
if (n == 0) begin
`checkh(alh[1].index, 'h102);
`checkh(alh[2].index, 'h101);
`checkh(ahl[1].index, 'h201);
`checkh(ahl[2].index, 'h202);
`checkh(blh[1].index, 'h301);
`checkh(blh[2].index, 'h302);
`checkh(bhl[1].index, 'h402);
`checkh(bhl[2].index, 'h401);
end
else if (n == 1) begin
`checkh(alh[1].index, 'h104);
`checkh(alh[2].index, 'h103);
`checkh(ahl[1].index, 'h203);
`checkh(ahl[2].index, 'h204);
`checkh(blh[1].index, 'h303);
`checkh(blh[2].index, 'h304);
`checkh(bhl[1].index, 'h404);
`checkh(bhl[2].index, 'h403);
end
else if (n == 2) begin
`checkh(alh[1].index, 'h101);
`checkh(alh[2].index, 'h102);
`checkh(ahl[1].index, 'h202);
`checkh(ahl[2].index, 'h201);
`checkh(blh[1].index, 'h302);
`checkh(blh[2].index, 'h301);
`checkh(bhl[1].index, 'h401);
`checkh(bhl[2].index, 'h402);
end
else if (n == 3) begin
`checkh(alh[1].index, 'h103);
`checkh(alh[2].index, 'h104);
`checkh(ahl[1].index, 'h204);
`checkh(ahl[2].index, 'h203);
`checkh(blh[1].index, 'h304);
`checkh(blh[2].index, 'h303);
`checkh(bhl[1].index, 'h403);
`checkh(bhl[2].index, 'h404);
end
end
if (cyc == 9 && n == 0) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule

View File

@ -0,0 +1,24 @@
#!/usr/bin/env 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.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
top_filename("t/t_mod_interface_array6.v");
compile(
v_flags2 => ["-Oi"],
);
execute(
check_finished => 1,
);
ok(1);
1;