forked from github/verilator
Fix +: and -: on unpacked arrays. (#2304)
This commit is contained in:
parent
98889b3f4e
commit
a41ea180fa
2
Changes
2
Changes
@ -7,6 +7,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
**** Fix FST tracing of little bit endian signals. [Geza Lore]
|
||||
|
||||
**** Fix +: and -: on unpacked arrays. (#2304) [engr248]
|
||||
|
||||
|
||||
* Verilator 4.034 2020-05-03
|
||||
|
||||
|
@ -191,6 +191,13 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void warnTri(AstNode* nodep) {
|
||||
if (VN_IS(nodep, Const) && VN_CAST(nodep, Const)->num().isFourState()) {
|
||||
nodep->v3error(
|
||||
"Selection index is constantly unknown or tristated: " << nodep->name());
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
// If adding new visitors, ensure V3Width's visit(TYPE) calls into here
|
||||
|
||||
@ -451,6 +458,7 @@ private:
|
||||
UINFO(6, "SELPLUS/MINUS " << nodep << endl);
|
||||
// Below 2 lines may change nodep->widthp()
|
||||
if (debug() >= 9) nodep->dumpTree(cout, "--SELPM0: ");
|
||||
V3Const::constifyEdit(nodep->rhsp()); // May relink pointed to node, ok if not const
|
||||
V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node
|
||||
checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant");
|
||||
if (debug() >= 9) nodep->dumpTree(cout, "--SELPM3: ");
|
||||
@ -458,6 +466,7 @@ private:
|
||||
AstNode* fromp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->thsp()->unlinkFrBack();
|
||||
warnTri(rhsp);
|
||||
int width = VN_CAST(widthp, Const)->toSInt();
|
||||
if (width > (1 << 28)) {
|
||||
nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "
|
||||
@ -467,9 +476,35 @@ private:
|
||||
FromData fromdata = fromDataForArray(nodep, fromp);
|
||||
AstNodeDType* ddtypep = fromdata.m_dtypep;
|
||||
VNumRange fromRange = fromdata.m_fromRange;
|
||||
if (VN_IS(ddtypep, BasicDType) || VN_IS(ddtypep, PackArrayDType)
|
||||
|| (VN_IS(ddtypep, NodeUOrStructDType)
|
||||
&& VN_CAST(ddtypep, NodeUOrStructDType)->packedUnsup())) {
|
||||
if (VN_IS(ddtypep, UnpackArrayDType)) {
|
||||
// Slice +: and -: extraction
|
||||
if (fromRange.elements() == width && VN_IS(rhsp, Const)
|
||||
&& VN_CAST(rhsp, Const)->toSInt()
|
||||
== fromRange.lo()) { // Extracting whole of original array
|
||||
nodep->replaceWith(fromp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else if (fromRange.elements() == 1) { // Extracting single element
|
||||
AstArraySel* newp = new AstArraySel(nodep->fileline(), fromp, rhsp);
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else if (VN_IS(rhsp, Const)) { // Slice
|
||||
vlsint32_t rhs = VN_CAST(rhsp, Const)->toSInt();
|
||||
// down array: lsb/lo +: width
|
||||
// down array: msb/hi -: width
|
||||
// up array: msb/lo +: width
|
||||
// up array: lsb/hi -: width
|
||||
vlsint32_t msb = VN_IS(nodep, SelPlus) ? rhs + width - 1 : rhs;
|
||||
vlsint32_t lsb = VN_IS(nodep, SelPlus) ? rhs : rhs - width + 1;
|
||||
AstSliceSel* newp = new AstSliceSel(nodep->fileline(), fromp,
|
||||
VNumRange(msb, lsb, fromRange.littleEndian()));
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else {
|
||||
nodep->v3error("Unsupported: Slice of non-constant bounds");
|
||||
}
|
||||
} else if (VN_IS(ddtypep, BasicDType) || VN_IS(ddtypep, PackArrayDType)
|
||||
|| (VN_IS(ddtypep, NodeUOrStructDType)
|
||||
&& VN_CAST(ddtypep, NodeUOrStructDType)->packedUnsup())) {
|
||||
int elwidth = 1;
|
||||
AstNode* newwidthp = widthp;
|
||||
if (const AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) {
|
||||
|
21
test_regress/t/t_inst_slice_part_select.pl
Executable file
21
test_regress/t/t_inst_slice_part_select.pl
Executable 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 2019 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;
|
93
test_regress/t/t_inst_slice_part_select.v
Normal file
93
test_regress/t/t_inst_slice_part_select.v
Normal file
@ -0,0 +1,93 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2020 by engr248.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
wire [31:0] in = 0;
|
||||
wire [31:0] out;
|
||||
|
||||
Test test(
|
||||
.out(out[31:0]),
|
||||
.clk(clk),
|
||||
.in (in[31:0])
|
||||
);
|
||||
|
||||
always @ (posedge clk) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
interface Intf ();
|
||||
endinterface
|
||||
|
||||
module Select
|
||||
#(
|
||||
parameter int NUM_MASTER = 1
|
||||
)
|
||||
(
|
||||
Intf Upstream,
|
||||
Intf Downstream[NUM_MASTER]
|
||||
);
|
||||
endmodule
|
||||
|
||||
module Crossbar
|
||||
#(
|
||||
parameter int NUM_MASTER = 1,
|
||||
parameter int NUM_SLAVE = 1
|
||||
)
|
||||
(
|
||||
Intf Masters[NUM_MASTER]
|
||||
);
|
||||
|
||||
Intf selectOut[(NUM_MASTER * (NUM_SLAVE))-1 : 0]();
|
||||
|
||||
|
||||
genvar i;
|
||||
|
||||
for (i = 0; i < NUM_MASTER; i = i + 1) begin
|
||||
Select #(
|
||||
.NUM_MASTER(NUM_SLAVE)
|
||||
)
|
||||
select_inst (
|
||||
.Upstream(Masters[i]),
|
||||
// Following line seems to trigger a bad calculation for dimension where port
|
||||
// is calculated as width 1 (correctly) and expression is calculated as NUM_MASTER*NUM_SLAVE rather than NUM_SLAVE
|
||||
.Downstream(selectOut[(i)*(NUM_SLAVE) +: (NUM_SLAVE)])
|
||||
// The following line works as intended and should be functionally identical to the above line
|
||||
// .Downstream(selectOut[(i+1)*(NUM_SLAVE)-1 : i*(NUM_SLAVE)])
|
||||
);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test
|
||||
(
|
||||
input clk,
|
||||
input [31:0] in,
|
||||
output reg [31:0] out
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
out <= in;
|
||||
end
|
||||
|
||||
Intf MST[10]();
|
||||
|
||||
Crossbar #(
|
||||
.NUM_MASTER(10),
|
||||
.NUM_SLAVE(1)
|
||||
)
|
||||
xbar_inst (
|
||||
.Masters(MST)
|
||||
);
|
||||
|
||||
endmodule
|
@ -23,10 +23,10 @@
|
||||
: ... In instance t
|
||||
17 | dim1[1][1][1] = 0;
|
||||
| ^
|
||||
%Error: t/t_mem_multi_ref_bad.v:19:11: Illegal +: or -: select; type already selected, or bad dimension: data type is 'logic[1:0]$[1:0][1:0]'
|
||||
: ... In instance t
|
||||
%Warning-SELRANGE: t/t_mem_multi_ref_bad.v:19:19: Selection index out of range: 1 outside 0:0
|
||||
: ... In instance t
|
||||
19 | dim2[0 +: 1][1] = 0;
|
||||
| ^
|
||||
| ^
|
||||
%Error: t/t_mem_multi_ref_bad.v:23:16: Illegal bit or array select; type does not have a bit range, or bad dimension: data type is 'logic'
|
||||
: ... In instance t
|
||||
23 | dim0nv[1][1] = 0;
|
||||
|
@ -1,5 +1,4 @@
|
||||
%Error: t/t_select_bad_tri.v:11:13: Selection index is constantly unknown or tristated: lsb=7'bxxxxxxx width=32'sh47
|
||||
: ... In instance t
|
||||
%Error: t/t_select_bad_tri.v:11:24: Selection index is constantly unknown or tristated: 1'bx
|
||||
11 | if (in[( (1'h0 / 1'b0) )+:71] != 71'h0) $stop;
|
||||
| ^
|
||||
%Error: Exiting due to
|
||||
| ^
|
||||
%Error: Internal Error: ../V3Number.cpp:#: toUInt with 4-state 1'bx
|
||||
|
21
test_regress/t/t_unpacked_slice.pl
Executable file
21
test_regress/t/t_unpacked_slice.pl
Executable 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 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);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
57
test_regress/t/t_unpacked_slice.v
Normal file
57
test_regress/t/t_unpacked_slice.v
Normal file
@ -0,0 +1,57 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2020 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`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)
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
|
||||
parameter int sliceddn[7:0] = '{'h100, 'h101, 'h102, 'h103, 'h104, 'h105, 'h106, 'h107};
|
||||
parameter int slicedup[0:7] = '{'h100, 'h101, 'h102, 'h103, 'h104, 'h105, 'h106, 'h107};
|
||||
int alldn[7:0];
|
||||
int allup[0:7];
|
||||
int twodn[1:0];
|
||||
int twoup[0:1];
|
||||
|
||||
initial begin
|
||||
`checkh(sliceddn[7], 'h100);
|
||||
alldn[7:0] = sliceddn[7:0];
|
||||
`checkh(alldn[7], 'h100);
|
||||
alldn[7:0] = sliceddn[0 +: 8]; // down: lsb/lo +: width
|
||||
`checkh(alldn[7], 'h100);
|
||||
alldn[7:0] = sliceddn[7 -: 8]; // down: msb/hi -: width
|
||||
`checkh(alldn[7], 'h100);
|
||||
twodn[1:0] = sliceddn[6:5];
|
||||
`checkh(twodn[1], 'h101);
|
||||
`checkh(twodn[0], 'h102);
|
||||
twodn[1:0] = sliceddn[4 +: 2];
|
||||
`checkh(twodn[1], 'h102);
|
||||
`checkh(twodn[0], 'h103);
|
||||
twodn[1:0] = sliceddn[4 -: 2];
|
||||
`checkh(twodn[1], 'h103);
|
||||
`checkh(twodn[0], 'h104);
|
||||
|
||||
`checkh(slicedup[7], 'h107);
|
||||
allup[0:7] = slicedup[0:7];
|
||||
`checkh(alldn[7], 'h100);
|
||||
allup[0:7] = slicedup[0 +: 8]; // up: msb/lo +: width
|
||||
`checkh(alldn[7], 'h100);
|
||||
allup[0:7] = slicedup[7 -: 8]; // up: lsb/hi -: width
|
||||
`checkh(alldn[7], 'h100);
|
||||
twoup[0:1] = slicedup[5:6];
|
||||
`checkh(twoup[1], 'h106);
|
||||
`checkh(twoup[0], 'h105);
|
||||
twoup[0:1] = slicedup[4 +: 2];
|
||||
`checkh(twoup[1], 'h105);
|
||||
`checkh(twoup[0], 'h104);
|
||||
twoup[0:1] = slicedup[4 -: 2];
|
||||
`checkh(twoup[1], 'h104);
|
||||
`checkh(twoup[0], 'h103);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
@ -24,12 +24,11 @@ module t (/*AUTOARG*/
|
||||
byte i, j;
|
||||
// bug1044
|
||||
for ( i = 0; i < 9; i = i + 1 )
|
||||
for ( j=0; j<(TEST_PARAM[i*8+:8]); j=j+1 )
|
||||
begin
|
||||
// verilator lint_off WIDTH
|
||||
in_tmp[TEST_PARAM[i*8+:8]+j] = in[TEST_PARAM[i*8+:8]+j];
|
||||
// verilator lint_on WIDTH
|
||||
end
|
||||
// verilator lint_off WIDTH
|
||||
for ( j=0; j<(TEST_PARAM[i*8+:8]); j=j+1) begin
|
||||
in_tmp[TEST_PARAM[i*8+:8]+j] = in[TEST_PARAM[i*8+:8]+j];
|
||||
end
|
||||
// verilator lint_on WIDTH
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user