@@ -8,6 +8,10 @@ Author: Daniel Kroening, kroening@kroening.com
88
99#include " verilog_expr.h"
1010
11+ #include < util/arith_tools.h>
12+ #include < util/bitvector_expr.h>
13+ #include < util/bitvector_types.h>
14+ #include < util/mathematical_types.h>
1115#include < util/prefix.h>
1216
1317#include " verilog_typecheck_base.h"
@@ -95,3 +99,72 @@ std::vector<irep_idt> verilog_module_sourcet::submodules() const
9599
96100 return result;
97101}
102+
103+ static exprt lower (const verilog_non_indexed_part_select_exprt &part_select)
104+ {
105+ auto get_width = [](const typet &t) -> mp_integer
106+ {
107+ if (t.id () == ID_bool)
108+ return 1 ;
109+
110+ if (
111+ t.id () == ID_unsignedbv || t.id () == ID_signedbv ||
112+ t.id () == ID_verilog_signedbv || t.id () == ID_verilog_unsignedbv)
113+ {
114+ return to_bitvector_type (t).get_width ();
115+ }
116+
117+ PRECONDITION (false );
118+ };
119+
120+ auto &src = part_select.src ();
121+
122+ auto op1 = numeric_cast_v<mp_integer>(to_constant_expr (part_select.msb ()));
123+ auto op2 = numeric_cast_v<mp_integer>(to_constant_expr (part_select.lsb ()));
124+
125+ mp_integer src_width = get_width (src.type ());
126+ mp_integer src_offset = string2integer (src.type ().get_string (ID_C_offset));
127+
128+ // 1800-2017 sec 11.5.1: out-of-bounds bit-select is
129+ // x for 4-state and 0 for 2-state values. We
130+ // achieve that by padding the operand from either end,
131+ // or both.
132+ exprt src_padded = src;
133+
134+ if (op2 < src_offset)
135+ {
136+ // lsb too small, pad below
137+ auto padding_width = src_offset - op2;
138+ auto padding = from_integer (
139+ 0 , unsignedbv_typet{numeric_cast_v<std::size_t >(padding_width)});
140+ auto new_type = unsignedbv_typet{numeric_cast_v<std::size_t >(
141+ get_width (src_padded.type ()) + padding_width)};
142+ src_padded = concatenation_exprt (src_padded, padding, new_type);
143+ op2 += padding_width;
144+ op1 += padding_width;
145+ }
146+
147+ if (op1 >= src_width + src_offset)
148+ {
149+ // msb too large, pad above
150+ auto padding_width = op1 - (src_width + src_offset) + 1 ;
151+ auto padding = from_integer (
152+ 0 , unsignedbv_typet{numeric_cast_v<std::size_t >(padding_width)});
153+ auto new_type = unsignedbv_typet{numeric_cast_v<std::size_t >(
154+ get_width (src_padded.type ()) + padding_width)};
155+ src_padded = concatenation_exprt (padding, src_padded, new_type);
156+ }
157+
158+ op2 -= src_offset;
159+ op1 -= src_offset;
160+
161+ // Construct the extractbits expression
162+ return extractbits_exprt{
163+ src_padded, from_integer (op2, integer_typet ()), part_select.type ()}
164+ .with_source_location (part_select.source_location ());
165+ }
166+
167+ exprt verilog_non_indexed_part_select_exprt::lower () const
168+ {
169+ return ::lower (*this );
170+ }
0 commit comments