@@ -8,6 +8,10 @@ Author: Daniel Kroening, kroening@kroening.com
8
8
9
9
#include " verilog_expr.h"
10
10
11
+ #include < util/arith_tools.h>
12
+ #include < util/bitvector_expr.h>
13
+ #include < util/bitvector_types.h>
14
+ #include < util/mathematical_types.h>
11
15
#include < util/prefix.h>
12
16
13
17
#include " verilog_typecheck_base.h"
@@ -95,3 +99,72 @@ std::vector<irep_idt> verilog_module_sourcet::submodules() const
95
99
96
100
return result;
97
101
}
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