Skip to content

Commit 793cf05

Browse files
committed
Verilog: extract .lower() method for part select expressions
This moves the lowering for Verilog's part select expressions into an explicit .lower() method.
1 parent e720965 commit 793cf05

File tree

3 files changed

+77
-45
lines changed

3 files changed

+77
-45
lines changed

src/verilog/verilog_expr.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Author: Daniel Kroening, [email protected]
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+
}

src/verilog/verilog_expr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,9 @@ class verilog_non_indexed_part_select_exprt : public ternary_exprt
22032203
{
22042204
return op2();
22052205
}
2206+
2207+
// lowering to extractbits
2208+
exprt lower() const;
22062209
};
22072210

22082211
inline const verilog_non_indexed_part_select_exprt &

src/verilog/verilog_synthesis.cpp

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -344,51 +344,7 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
344344
else if(expr.id() == ID_verilog_non_indexed_part_select)
345345
{
346346
auto &part_select = to_verilog_non_indexed_part_select_expr(expr);
347-
auto &src = part_select.src();
348-
349-
auto op1 = numeric_cast_v<mp_integer>(to_constant_expr(part_select.msb()));
350-
auto op2 = numeric_cast_v<mp_integer>(to_constant_expr(part_select.lsb()));
351-
352-
mp_integer src_width = get_width(src.type());
353-
mp_integer src_offset = string2integer(src.type().get_string(ID_C_offset));
354-
355-
// 1800-2017 sec 11.5.1: out-of-bounds bit-select is
356-
// x for 4-state and 0 for 2-state values. We
357-
// achieve that by padding the operand from either end,
358-
// or both.
359-
exprt src_padded = src;
360-
361-
if(op2 < src_offset)
362-
{
363-
// lsb too small, pad below
364-
auto padding_width = src_offset - op2;
365-
auto padding = from_integer(
366-
0, unsignedbv_typet{numeric_cast_v<std::size_t>(padding_width)});
367-
auto new_type = unsignedbv_typet{numeric_cast_v<std::size_t>(
368-
get_width(src_padded.type()) + padding_width)};
369-
src_padded = concatenation_exprt(src_padded, padding, new_type);
370-
op2 += padding_width;
371-
op1 += padding_width;
372-
}
373-
374-
if(op1 >= src_width + src_offset)
375-
{
376-
// msb too large, pad above
377-
auto padding_width = op1 - (src_width + src_offset) + 1;
378-
auto padding = from_integer(
379-
0, unsignedbv_typet{numeric_cast_v<std::size_t>(padding_width)});
380-
auto new_type = unsignedbv_typet{numeric_cast_v<std::size_t>(
381-
get_width(src_padded.type()) + padding_width)};
382-
src_padded = concatenation_exprt(padding, src_padded, new_type);
383-
}
384-
385-
op2 -= src_offset;
386-
op1 -= src_offset;
387-
388-
// Construct the extractbits expression
389-
return extractbits_exprt{
390-
src_padded, from_integer(op2, integer_typet()), expr.type()}
391-
.with_source_location(expr.source_location());
347+
return part_select.lower();
392348
}
393349
else if(
394350
expr.id() == ID_verilog_indexed_part_select_plus ||

0 commit comments

Comments
 (0)