Skip to content

Commit c301e4c

Browse files
committed
Verilog: fix array index direction for descending and ascending ranges
Arrays declared with descending ranges (e.g., [4:0]) or ascending ranges with non-zero offsets were not correctly mapping Verilog indices to internal array indices. This affected both packed and unpacked arrays. For unpacked arrays, the Verilog index is now adjusted to the internal index based on the range direction and offset. For packed arrays, the assignment pattern operands are reversed for descending ranges so that internal index 0 corresponds to Verilog index 0, and the bitvector lowering is updated to match. Per IEEE 1800-2017 section 10.9.1, assignment patterns assign elements left-to-right starting from the left index of the range.
1 parent 1388e9a commit c301e4c

File tree

7 files changed

+56
-20
lines changed

7 files changed

+56
-20
lines changed

regression/verilog/arrays/array_conversion3.desc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ array_conversion3.sv
66
^\[main\.p13\] main\.array1\[2\] == 3: PROVED .*$
77
^\[main\.p14\] main\.array1\[3\] == 4: PROVED .*$
88
^\[main\.p15\] main\.array1 == 32'h1020304: PROVED .*$
9-
^\[main\.p21\] main\.array2\[0\] == 4: REFUTED$
10-
^\[main\.p22\] main\.array2\[1\] == 3: REFUTED$
11-
^\[main\.p23\] main\.array2\[2\] == 2: REFUTED$
12-
^\[main\.p24\] main\.array2\[3\] == 1: REFUTED$
9+
^\[main\.p21\] main\.array2\[0\] == 4: PROVED .*$
10+
^\[main\.p22\] main\.array2\[1\] == 3: PROVED .*$
11+
^\[main\.p23\] main\.array2\[2\] == 2: PROVED .*$
12+
^\[main\.p24\] main\.array2\[3\] == 1: PROVED .*$
1313
^\[main\.p25\] main\.array2 == 32'h1020304: PROVED .*$
14-
^EXIT=10$
14+
^EXIT=0$
1515
^SIGNAL=0$
1616
--
1717
--
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
KNOWNBUG
1+
CORE
22
packed_direction1.sv
33
--module main
44
^EXIT=0$
55
^SIGNAL=0$
66
--
77
--
8-
This gives the wrong answer.

regression/verilog/arrays/unpacked_direction1.desc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
KNOWNBUG
1+
CORE
22
unpacked_direction1.sv
33
--module main
4+
^\[main\.p0\] main\.my_array0\[0\] == 1: PROVED .*$
5+
^\[main\.p1\] main\.my_array1\[0\] == 1: PROVED .*$
6+
^\[main\.p2\] main\.my_array2\[0 \+ 5 - 3'b001 - 0\] == 5: PROVED .*$
47
^EXIT=0$
58
^SIGNAL=0$
69
--
710
--
8-
This gives the wrong answer.

regression/verilog/structs/array_in_struct1.sv

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ module main;
1616
p12: assert property (s.array1[1] == 2);
1717
p13: assert property (s.array1[2] == 3);
1818
p14: assert property (s.array1[3] == 4);
19-
p21: assert property (s.array2[0] == 1);
20-
p22: assert property (s.array2[1] == 2);
21-
p23: assert property (s.array2[2] == 3);
22-
p24: assert property (s.array2[3] == 4);
19+
p21: assert property (s.array2[0] == 4);
20+
p22: assert property (s.array2[1] == 3);
21+
p23: assert property (s.array2[2] == 2);
22+
p24: assert property (s.array2[3] == 1);
2323

2424
endmodule

src/verilog/verilog_elaborate_type.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ typet verilog_typecheck_exprt::convert_packed_array_type(
173173

174174
array_typet result{element_type, size};
175175
result.set(ID_offset, from_integer(offset, integer_typet()));
176+
result.set(ID_C_increasing, range.increasing());
176177
result.set(ID_C_verilog_type, ID_verilog_packed_array);
177178

178179
return std::move(result).with_source_location(source_location);

src/verilog/verilog_lowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ exprt to_bitvector(const exprt &src)
233233
bool is_packed =
234234
array_type.get(ID_C_verilog_type) == ID_verilog_packed_array;
235235

236-
if(is_packed && !array_type.get_bool(ID_C_increasing))
236+
if(is_packed && array_type.get_bool(ID_C_increasing))
237237
{
238238
for(std::size_t index = 0; index < size_int; index++)
239239
{

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,18 @@ void verilog_typecheck_exprt::assignment_conversion(
231231
assignment_conversion(rhs.operands()[i], element_type);
232232
}
233233

234+
// For packed arrays with descending range (e.g., [3:0]),
235+
// the assignment pattern lists elements from the left (highest)
236+
// index to the right (lowest), but internally index 0 must
237+
// correspond to Verilog index 0 (the lowest). Reverse the
238+
// operands so that internal[0] = last element = Verilog index 0.
239+
if(
240+
array_type.get(ID_C_verilog_type) == ID_verilog_packed_array &&
241+
!array_type.get_bool(ID_C_increasing))
242+
{
243+
std::reverse(rhs.operands().begin(), rhs.operands().end());
244+
}
245+
234246
// turn into array expression
235247
rhs.id(ID_array);
236248
rhs.type() = lhs_type;
@@ -3000,13 +3012,35 @@ exprt verilog_typecheck_exprt::convert_bit_select_expr(binary_exprt expr)
30003012
typet _index_type = index_type(array_type);
30013013
op1 = typecast_exprt{op1, _index_type};
30023014

3003-
if(
3004-
array_type.get_bool(ID_C_increasing) &&
3005-
array_type.get(ID_C_verilog_type) == ID_verilog_packed_array)
3015+
// For unpacked arrays, the internal representation stores
3016+
// elements starting from the left index of the range.
3017+
// We need to adjust the Verilog index to the internal index.
3018+
if(array_type.get(ID_C_verilog_type) == ID_verilog_unpacked_array)
30063019
{
3007-
expr.op1() = minus_exprt{
3008-
minus_exprt{typecast_exprt{array_type.size(), _index_type}, expr.op1()},
3009-
from_integer(1, _index_type)};
3020+
auto offset_expr = static_cast<const exprt &>(array_type.find(ID_offset));
3021+
3022+
if(array_type.get_bool(ID_C_increasing))
3023+
{
3024+
// ascending range [l:r] with l<r, e.g., [0:4]
3025+
// internal index = verilog_index - offset
3026+
if(!offset_expr.is_zero())
3027+
{
3028+
expr.op1() =
3029+
minus_exprt{expr.op1(), typecast_exprt{offset_expr, _index_type}};
3030+
}
3031+
}
3032+
else
3033+
{
3034+
// descending range [l:r] with l>=r, e.g., [4:0]
3035+
// internal index = (offset + size - 1) - verilog_index
3036+
expr.op1() = minus_exprt{
3037+
minus_exprt{
3038+
plus_exprt{
3039+
typecast_exprt{offset_expr, _index_type},
3040+
typecast_exprt{array_type.size(), _index_type}},
3041+
from_integer(1, _index_type)},
3042+
expr.op1()};
3043+
}
30103044
}
30113045

30123046
expr.type() = array_type.element_type();

0 commit comments

Comments
 (0)