@@ -228,3 +228,80 @@ exprt verilog_non_indexed_part_select_exprt::lower() const
228228{
229229 return ::lower (*this );
230230}
231+
232+ static exprt
233+ lower (const verilog_indexed_part_select_plus_or_minus_exprt &part_select)
234+ {
235+ auto get_width = [](const typet &t) -> mp_integer
236+ {
237+ if (t.id () == ID_bool)
238+ return 1 ;
239+
240+ if (
241+ t.id () == ID_unsignedbv || t.id () == ID_signedbv ||
242+ t.id () == ID_verilog_signedbv || t.id () == ID_verilog_unsignedbv)
243+ {
244+ return to_bitvector_type (t).get_width ();
245+ }
246+
247+ PRECONDITION (false );
248+ };
249+
250+ PRECONDITION (
251+ part_select.id () == ID_verilog_indexed_part_select_plus ||
252+ part_select.id () == ID_verilog_indexed_part_select_minus);
253+
254+ const exprt &src = part_select.src ();
255+
256+ mp_integer src_width = get_width (src.type ());
257+ mp_integer src_offset = string2integer (src.type ().get_string (ID_C_offset));
258+
259+ // The width of the indexed part select must be an
260+ // elaboration-time constant.
261+ auto width =
262+ numeric_cast_v<mp_integer>(to_constant_expr (part_select.width ()));
263+
264+ // The index need not be a constant.
265+ const exprt &index = part_select.index ();
266+
267+ if (index.is_constant ())
268+ {
269+ auto index_int = numeric_cast_v<mp_integer>(to_constant_expr (index));
270+
271+ // Construct the extractbits expression
272+ mp_integer bottom;
273+
274+ if (part_select.id () == ID_verilog_indexed_part_select_plus)
275+ {
276+ bottom = index_int - src_offset;
277+ }
278+ else // ID_verilog_indexed_part_select_minus
279+ {
280+ bottom = bottom - width + 1 ;
281+ }
282+
283+ return extractbits_exprt{
284+ std::move (src), from_integer (bottom, integer_typet{}), part_select.type ()}
285+ .with_source_location (part_select);
286+ }
287+ else
288+ {
289+ // Index not constant.
290+ // Use logical right-shift followed by (constant) extractbits.
291+ auto index_adjusted =
292+ minus_exprt{index, from_integer (src_offset, index.type ())};
293+
294+ auto src_shifted = lshr_exprt (src, index_adjusted);
295+
296+ return extractbits_exprt{
297+ std::move (src_shifted),
298+ from_integer (0 , integer_typet{}),
299+ part_select.type ()}
300+ .with_source_location (part_select);
301+ }
302+ }
303+
304+ exprt verilog_indexed_part_select_plus_or_minus_exprt::lower () const
305+ {
306+ return ::lower (*this );
307+ }
0 commit comments