Skip to content

Commit 5724218

Browse files
committed
Verilog: constant folding for indexed part select expressions
This implements constant folding for indexed part select expressions, following the pattern in #766. Fixes #784.
1 parent a5c8dfe commit 5724218

File tree

5 files changed

+91
-48
lines changed

5 files changed

+91
-48
lines changed

regression/verilog/expressions/part-select-constant1.sv

+2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ module main;
33
// part-select expressions yield constants
44
parameter p = 'b1010;
55
parameter q = p[3:1];
6+
parameter r = p[1 +: 3];
67

78
assert final (q == 'b101);
9+
assert final (r == 'b101);
810

911
endmodule

src/verilog/verilog_expr.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,80 @@ exprt verilog_non_indexed_part_select_exprt::lower() const
168168
{
169169
return ::lower(*this);
170170
}
171+
172+
static exprt
173+
lower(const verilog_indexed_part_select_plus_or_minus_exprt &part_select)
174+
{
175+
auto get_width = [](const typet &t) -> mp_integer
176+
{
177+
if(t.id() == ID_bool)
178+
return 1;
179+
180+
if(
181+
t.id() == ID_unsignedbv || t.id() == ID_signedbv ||
182+
t.id() == ID_verilog_signedbv || t.id() == ID_verilog_unsignedbv)
183+
{
184+
return to_bitvector_type(t).get_width();
185+
}
186+
187+
PRECONDITION(false);
188+
};
189+
190+
PRECONDITION(
191+
part_select.id() == ID_verilog_indexed_part_select_plus ||
192+
part_select.id() == ID_verilog_indexed_part_select_minus);
193+
194+
const exprt &src = part_select.src();
195+
196+
mp_integer src_width = get_width(src.type());
197+
mp_integer src_offset = string2integer(src.type().get_string(ID_C_offset));
198+
199+
// The width of the indexed part select must be an
200+
// elaboration-time constant.
201+
auto width =
202+
numeric_cast_v<mp_integer>(to_constant_expr(part_select.width()));
203+
204+
// The index need not be a constant.
205+
const exprt &index = part_select.index();
206+
207+
if(index.is_constant())
208+
{
209+
auto index_int = numeric_cast_v<mp_integer>(to_constant_expr(index));
210+
211+
// Construct the extractbits expression
212+
mp_integer bottom;
213+
214+
if(part_select.id() == ID_verilog_indexed_part_select_plus)
215+
{
216+
bottom = index_int - src_offset;
217+
}
218+
else // ID_verilog_indexed_part_select_minus
219+
{
220+
bottom = bottom - width + 1;
221+
}
222+
223+
return extractbits_exprt{
224+
std::move(src), from_integer(bottom, integer_typet{}), part_select.type()}
225+
.with_source_location(part_select);
226+
}
227+
else
228+
{
229+
// Index not constant.
230+
// Use logical right-shift followed by (constant) extractbits.
231+
auto index_adjusted =
232+
minus_exprt{index, from_integer(src_offset, index.type())};
233+
234+
auto src_shifted = lshr_exprt(src, index_adjusted);
235+
236+
return extractbits_exprt{
237+
std::move(src_shifted),
238+
from_integer(0, integer_typet{}),
239+
part_select.type()}
240+
.with_source_location(part_select);
241+
}
242+
}
243+
244+
exprt verilog_indexed_part_select_plus_or_minus_exprt::lower() const
245+
{
246+
return ::lower(*this);
247+
}

src/verilog/verilog_expr.h

+2
Original file line numberDiff line numberDiff line change
@@ -2280,6 +2280,8 @@ class verilog_indexed_part_select_plus_or_minus_exprt : public ternary_exprt
22802280
{
22812281
return op2();
22822282
}
2283+
2284+
exprt lower() const;
22832285
};
22842286

22852287
inline const verilog_indexed_part_select_plus_or_minus_exprt &

src/verilog/verilog_synthesis.cpp

+1-48
Original file line numberDiff line numberDiff line change
@@ -358,54 +358,7 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
358358
expr.id() == ID_verilog_indexed_part_select_minus)
359359
{
360360
auto &part_select = to_verilog_indexed_part_select_plus_or_minus_expr(expr);
361-
exprt &src = part_select.src();
362-
363-
mp_integer src_width = get_width(src.type());
364-
mp_integer src_offset = string2integer(src.type().get_string(ID_C_offset));
365-
366-
// The width of the indexed part select must be an
367-
// elaboration-time constant.
368-
auto width =
369-
numeric_cast_v<mp_integer>(to_constant_expr(part_select.width()));
370-
371-
// The index need not be a constant.
372-
exprt &index = part_select.index();
373-
374-
if(index.is_constant())
375-
{
376-
auto index_int = numeric_cast_v<mp_integer>(to_constant_expr(index));
377-
378-
// Construct the extractbits expression
379-
mp_integer bottom, top;
380-
381-
if(part_select.id() == ID_verilog_indexed_part_select_plus)
382-
{
383-
bottom = index_int - src_offset;
384-
top = bottom + width - 1;
385-
}
386-
else // ID_verilog_indexed_part_select_minus
387-
{
388-
top = index_int - src_offset;
389-
bottom = bottom - width + 1;
390-
}
391-
392-
return extractbits_exprt{
393-
std::move(src), from_integer(bottom, integer_typet{}), expr.type()}
394-
.with_source_location(expr);
395-
}
396-
else
397-
{
398-
// Index not constant.
399-
// Use logical right-shift followed by (constant) extractbits.
400-
auto index_adjusted =
401-
minus_exprt{index, from_integer(src_offset, index.type())};
402-
403-
auto src_shifted = lshr_exprt(src, index_adjusted);
404-
405-
return extractbits_exprt{
406-
std::move(src_shifted), from_integer(0, integer_typet{}), expr.type()}
407-
.with_source_location(expr);
408-
}
361+
return part_select.lower();
409362
}
410363
else if(expr.id() == ID_verilog_logical_equality)
411364
{

src/verilog/verilog_typecheck_expr.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,15 @@ exprt verilog_typecheck_exprt::elaborate_constant_expression(exprt expr)
16601660
auto &part_select = to_verilog_non_indexed_part_select_expr(expr);
16611661
expr = part_select.lower();
16621662
}
1663+
else if(
1664+
expr.id() == ID_verilog_indexed_part_select_plus ||
1665+
expr.id() == ID_verilog_indexed_part_select_minus)
1666+
{
1667+
// Our simplifier does not know these, do lowering.
1668+
auto &part_select =
1669+
to_verilog_indexed_part_select_plus_or_minus_expr(expr);
1670+
expr = part_select.lower();
1671+
}
16631672
else if(expr.id() == ID_reduction_or)
16641673
{
16651674
// The simplifier doesn't know how to simplify reduction_or

0 commit comments

Comments
 (0)