Merge pull request #964 from larsclausen/bits-array

Support $bits() for arrays and array slices
This commit is contained in:
Cary R 2023-06-28 07:50:43 -07:00 committed by GitHub
commit 17461e02de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 16 deletions

View File

@ -4289,10 +4289,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty()) {
const index_component_t&index_tail = name_tail.index.back();
// Skip full array word net selects.
if (!sr.net || (name_tail.index.size() > sr.net->unpacked_dimensions())) {
use_sel = index_tail.sel;
}
use_sel = index_tail.sel;
}
unsigned use_width = UINT_MAX;
@ -4380,13 +4377,12 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
}
}
if (use_width != UINT_MAX) {
size_t use_depth = name_tail.index.size();
if (use_width != UINT_MAX && (!sr.net || use_depth > sr.net->unpacked_dimensions())) {
// We have a bit/part select. Account for any remaining dimensions
// beyond the indexed dimension.
size_t use_depth = name_tail.index.size();
if (sr.net) {
if (use_depth >= sr.net->unpacked_dimensions())
use_depth -= sr.net->unpacked_dimensions();
use_depth -= sr.net->unpacked_dimensions();
use_width *= sr.net->slice_width(use_depth);
}
@ -4426,23 +4422,29 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
}
}
size_t use_depth = name_tail.index.size();
// Unindexed indentifier
if (use_width == UINT_MAX)
use_width = 1;
// Account for unpacked dimensions by assuming that the
// unpacked dimensions are consumed first, so subtract
// the unpacked dimensions from the dimension depth
// useable for making the slice.
if (use_depth >= sr.net->unpacked_dimensions()) {
use_depth -= sr.net->unpacked_dimensions();
} else {
// In this case, we have a slice of an unpacked
// array. This likely handled as an array instead
// of a slice. Hmm...
// In this case, we have an unpacked array or a slice of an
// unpacked array. These expressions strictly speaking do
// not have a width. But we use the value calculated here
// for things $bits(), so return the full number of bits of
// the expression.
const auto &dims = sr.net->unpacked_dims();
for (size_t idx = use_depth; idx < dims.size(); idx++)
use_width *= dims[idx].width();
use_depth = 0;
}
expr_type_ = sr.net->data_type();
expr_width_ = sr.net->slice_width(use_depth);
expr_width_ = sr.net->slice_width(use_depth) * use_width;
min_width_ = expr_width_;
signed_flag_ = sr.net->get_signed();
if (debug_elaborate) {
@ -4648,6 +4650,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
if (!result || !type_is_vectorable(expr_type_))
return result;
auto net_type = result->net_type();
if (net_type && !net_type->packed())
return result;
return pad_to_width(result, expr_wid, signed_flag_, *this);
}

37
ivtest/ivltests/bits4.v Normal file
View File

@ -0,0 +1,37 @@
// Check that passing a array identifiers and array slices to $bits works as expected
module test;
bit failed = 1'b0;
`define check(expr, value) do begin \
if ($bits(expr) !== value) begin \
$display("FAILED(%d): $bits(", `"expr`", ") is %0d", `__LINE__, $bits(expr), " expected %0d", value); \
failed = 1'b1; \
end \
end while (0)
typedef bit T[3:0];
T x;
byte y[7:0][2:0];
initial begin
integer i;
i = 4;
`check(x, 4);
`check(y, $bits(byte) * 3 * 8);
`check(y[0], $bits(byte) * 3);
`check(y[1:0], $bits(byte) * 3 * 2);
`check(y[1+:3], $bits(byte) * 3 * 3);
`check(y[4-:4], $bits(byte) * 3 * 4);
`check(y[i-:2], $bits(byte) * 3 * 2);
`check(y[i+:2], $bits(byte) * 3 * 2);
if (!failed) begin
$display("PASSED");
end
end
endmodule

View File

@ -3,6 +3,7 @@
# describes the test.
array_packed_write_read vvp_tests/array_packed_write_read.json
bits4 vvp_tests/bits4.json
bitsel11 vvp_tests/bitsel11.json
br_gh13a vvp_tests/br_gh13a.json
br_gh13a-vlog95 vvp_tests/br_gh13a-vlog95.json

View File

@ -0,0 +1,5 @@
{
"type" : "normal",
"source" : "bits4.v",
"iverilog-args" : [ "-g2005-sv" ]
}

View File

@ -2432,10 +2432,10 @@ NetESignal::NetESignal(NetNet*n, NetExpr*w)
net_->incr_eref();
set_line(*n);
// If it is an array we don't have a type for it yet. But for array
// elements the NetNet returns the element type.
if (word_)
set_net_type(net_->net_type());
else
set_net_type(net_->array_type());
}
NetESignal::~NetESignal()