@@ -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+ }
0 commit comments