Skip to content

Commit 98d69e5

Browse files
authored
Merge pull request #735 from diffblue/power1-fix
Verilog: four-valued power
2 parents eb18f6f + 97270ca commit 98d69e5

File tree

8 files changed

+162
-30
lines changed

8 files changed

+162
-30
lines changed
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
KNOWNBUG
1+
CORE broken-smt-backend
22
power1.sv
33
--bound 0
44
^EXIT=0$
55
^SIGNAL=0$
66
--
77
^warning: ignoring
88
--
9-
Lowering for power on three-valued logic is missing.

src/verilog/aval_bval_encoding.cpp

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ exprt aval(const exprt &src)
122122
}
123123
}
124124

125+
exprt aval_underlying(const exprt &src)
126+
{
127+
if(is_aval_bval(src.type()))
128+
{
129+
auto type = aval_bval_underlying(src.type());
130+
if(type.id() == ID_bool)
131+
return extractbit_exprt{src, 0};
132+
else
133+
return extractbits_exprt{src, 0, type};
134+
}
135+
else
136+
{
137+
return src;
138+
}
139+
}
140+
125141
exprt bval(const exprt &src)
126142
{
127143
if(is_aval_bval(src.type()))
@@ -225,10 +241,11 @@ exprt has_xz(const exprt &expr)
225241
}
226242

227243
/// return 'x', one bit
228-
exprt make_x()
244+
exprt make_x(const typet &type)
229245
{
230-
auto type = verilog_unsignedbv_typet{1};
231-
return lower_to_aval_bval(constant_exprt{ID_x, type});
246+
PRECONDITION(is_four_valued(type));
247+
auto width = to_bitvector_type(type).get_width();
248+
return lower_to_aval_bval(constant_exprt{std::string(width, 'x'), type});
232249
}
233250

234251
exprt aval_bval(const verilog_logical_equality_exprt &expr)
@@ -239,7 +256,9 @@ exprt aval_bval(const verilog_logical_equality_exprt &expr)
239256
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
240257
auto equality = equal_exprt{expr.lhs(), expr.rhs()};
241258
return if_exprt{
242-
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
259+
has_xz,
260+
make_x(type),
261+
aval_bval_conversion(equality, lower_to_aval_bval(type))};
243262
}
244263

245264
exprt aval_bval(const verilog_logical_inequality_exprt &expr)
@@ -250,7 +269,9 @@ exprt aval_bval(const verilog_logical_inequality_exprt &expr)
250269
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
251270
auto equality = notequal_exprt{expr.lhs(), expr.rhs()};
252271
return if_exprt{
253-
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
272+
has_xz,
273+
make_x(type),
274+
aval_bval_conversion(equality, lower_to_aval_bval(type))};
254275
}
255276

256277
exprt aval_bval(const verilog_wildcard_equality_exprt &expr)
@@ -289,12 +310,26 @@ exprt aval_bval(const verilog_wildcard_inequality_exprt &expr)
289310

290311
exprt aval_bval(const not_exprt &expr)
291312
{
292-
PRECONDITION(is_four_valued(expr.type()));
313+
auto &type = expr.type();
314+
PRECONDITION(is_four_valued(type));
293315
PRECONDITION(is_aval_bval(expr.op()));
294316

295317
auto has_xz = ::has_xz(expr.op());
296318
auto not_expr =
297319
not_exprt{extractbit_exprt{expr.op(), natural_typet{}.zero_expr()}};
298-
auto x = make_x();
320+
auto x = make_x(type);
299321
return if_exprt{has_xz, x, aval_bval_conversion(not_expr, x.type())};
300322
}
323+
324+
exprt aval_bval(const power_exprt &expr)
325+
{
326+
PRECONDITION(is_four_valued(expr.type()));
327+
PRECONDITION(is_aval_bval(expr.lhs()));
328+
PRECONDITION(is_aval_bval(expr.rhs()));
329+
330+
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
331+
auto power_expr =
332+
power_exprt{aval_underlying(expr.lhs()), aval_underlying(expr.rhs())};
333+
auto x = make_x(expr.type());
334+
return if_exprt{has_xz, x, aval_bval_conversion(power_expr, x.type())};
335+
}

src/verilog/aval_bval_encoding.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
#define CPROVER_VERILOG_AVAL_BVAL_H
1111

1212
#include <util/bitvector_types.h>
13+
#include <util/mathematical_expr.h>
1314

1415
#include "verilog_expr.h"
1516

@@ -47,5 +48,7 @@ exprt aval_bval(const not_exprt &);
4748
exprt aval_bval(const verilog_wildcard_equality_exprt &);
4849
/// lowering for !=?
4950
exprt aval_bval(const verilog_wildcard_inequality_exprt &);
51+
/// lowering for **
52+
exprt aval_bval(const power_exprt &);
5053

5154
#endif

src/verilog/verilog_synthesis.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -246,28 +246,35 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
246246
}
247247
else if(expr.id() == ID_power)
248248
{
249-
auto &power_expr = to_binary_expr(expr);
249+
auto &power_expr = to_power_expr(expr);
250250
DATA_INVARIANT(
251251
power_expr.lhs().type() == power_expr.type(),
252252
"power expression type consistency");
253253
power_expr.lhs() = synth_expr(power_expr.lhs(), symbol_state);
254254
power_expr.rhs() = synth_expr(power_expr.rhs(), symbol_state);
255-
auto rhs_int = numeric_cast<std::size_t>(power_expr.rhs());
256-
if(rhs_int.has_value())
255+
256+
// encode into aval/bval
257+
if(is_four_valued(expr.type()))
258+
return aval_bval(power_expr);
259+
else
257260
{
258-
if(*rhs_int == 0)
259-
return from_integer(1, expr.type());
260-
else if(*rhs_int == 1)
261-
return power_expr.lhs();
262-
else // >= 2
261+
auto rhs_int = numeric_cast<std::size_t>(power_expr.rhs());
262+
if(rhs_int.has_value())
263263
{
264-
auto factors = exprt::operandst{rhs_int.value(), power_expr.lhs()};
265-
// would prefer appropriate mult_exprt constructor
266-
return multi_ary_exprt{ID_mult, factors, expr.type()};
264+
if(*rhs_int == 0)
265+
return from_integer(1, expr.type());
266+
else if(*rhs_int == 1)
267+
return power_expr.lhs();
268+
else // >= 2
269+
{
270+
auto factors = exprt::operandst{rhs_int.value(), power_expr.lhs()};
271+
// would prefer appropriate mult_exprt constructor
272+
return multi_ary_exprt{ID_mult, factors, expr.type()};
273+
}
267274
}
275+
else
276+
return expr;
268277
}
269-
else
270-
return expr;
271278
}
272279
else if(expr.id()==ID_typecast)
273280
{

src/verilog/verilog_typecheck_base.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,44 @@ typet verilog_typecheck_baset::index_type(const array_typet &array_type)
265265
return unsignedbv_typet(address_bits(
266266
(array_size(array_type) + array_offset(array_type)).to_ulong()));
267267
}
268+
269+
/*******************************************************************\
270+
271+
Function: verilog_typecheck_baset::is_four_valued
272+
273+
Inputs:
274+
275+
Outputs:
276+
277+
Purpose:
278+
279+
\*******************************************************************/
280+
281+
bool verilog_typecheck_baset::is_four_valued(const typet &type)
282+
{
283+
return type.id() == ID_verilog_signedbv || type.id() == ID_verilog_unsignedbv;
284+
}
285+
286+
/*******************************************************************\
287+
288+
Function: verilog_typecheck_baset::four_valued
289+
290+
Inputs:
291+
292+
Outputs:
293+
294+
Purpose:
295+
296+
\*******************************************************************/
297+
298+
typet verilog_typecheck_baset::four_valued(const typet &type)
299+
{
300+
if(type.id() == ID_signedbv)
301+
return verilog_signedbv_typet{to_signedbv_type(type).get_width()};
302+
else if(type.id() == ID_unsignedbv)
303+
return verilog_unsignedbv_typet{to_unsignedbv_type(type).get_width()};
304+
else if(type.id() == ID_bool)
305+
return verilog_unsignedbv_typet{1};
306+
else
307+
return type;
308+
}

src/verilog/verilog_typecheck_base.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ class verilog_typecheck_baset:public typecheckt
5555
static mp_integer array_size(const array_typet &);
5656
static mp_integer array_offset(const array_typet &);
5757
static typet index_type(const array_typet &);
58+
59+
/// is the given type four-valued?
60+
static bool is_four_valued(const typet &);
61+
62+
/// create the four-valued type with same width and signedness
63+
/// as the given type
64+
static typet four_valued(const typet &);
5865
};
5966

6067
#endif

src/verilog/verilog_typecheck_expr.cpp

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111
#include <util/bitvector_expr.h>
1212
#include <util/ebmc_util.h>
1313
#include <util/expr_util.h>
14+
#include <util/mathematical_expr.h>
1415
#include <util/mathematical_types.h>
1516
#include <util/namespace.h>
1617
#include <util/prefix.h>
@@ -123,14 +124,11 @@ void verilog_typecheck_exprt::propagate_type(
123124
expr.has_operands())
124125
{
125126
// arithmetic
126-
127-
if(expr.id()==ID_plus ||
128-
expr.id()==ID_minus ||
129-
expr.id()==ID_mult ||
130-
expr.id()==ID_div ||
131-
expr.id()==ID_power ||
132-
expr.id()==ID_unary_minus ||
133-
expr.id()==ID_unary_plus)
127+
128+
if(
129+
expr.id() == ID_plus || expr.id() == ID_minus || expr.id() == ID_mult ||
130+
expr.id() == ID_div || expr.id() == ID_unary_minus ||
131+
expr.id() == ID_unary_plus)
134132
{
135133
if(type.id()!=ID_bool)
136134
{
@@ -2611,6 +2609,44 @@ Function: verilog_typecheck_exprt::convert_shl_expr
26112609
26122610
\*******************************************************************/
26132611

2612+
exprt verilog_typecheck_exprt::convert_power_expr(power_exprt expr)
2613+
{
2614+
convert_expr(expr.op0());
2615+
convert_expr(expr.op1());
2616+
2617+
no_bool_ops(expr);
2618+
2619+
// Is one of the operands four-valued?
2620+
if(is_four_valued(expr.op0().type()))
2621+
{
2622+
// We make the other operand also four-valued, if needed
2623+
expr.op1() = typecast_exprt{expr.op1(), four_valued(expr.op1().type())};
2624+
}
2625+
else if(is_four_valued(expr.op1().type()))
2626+
{
2627+
// We make the other operand also four-valued, if needed
2628+
expr.op0() = typecast_exprt{expr.op0(), four_valued(expr.op0().type())};
2629+
}
2630+
2631+
// 1800-2017 Table 11-21
2632+
// The width of a power is the width of the left operand
2633+
expr.type() = expr.op0().type();
2634+
2635+
return std::move(expr);
2636+
}
2637+
2638+
/*******************************************************************\
2639+
2640+
Function: verilog_typecheck_exprt::convert_shl_expr
2641+
2642+
Inputs:
2643+
2644+
Outputs:
2645+
2646+
Purpose:
2647+
2648+
\*******************************************************************/
2649+
26142650
exprt verilog_typecheck_exprt::convert_shl_expr(shl_exprt expr)
26152651
{
26162652
convert_expr(expr.op0());
@@ -2760,6 +2796,8 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
27602796

27612797
return std::move(expr);
27622798
}
2799+
else if(expr.id() == ID_power)
2800+
return convert_power_expr(to_power_expr(expr));
27632801
else if(expr.id()==ID_shl)
27642802
return convert_shl_expr(to_shl_expr(expr));
27652803
else if(expr.id()==ID_shr)

src/verilog/verilog_typecheck_expr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919
#include <stack>
2020

2121
class function_call_exprt;
22+
class power_exprt;
2223

2324
class verilog_typecheck_exprt:public verilog_typecheck_baset
2425
{
@@ -168,6 +169,7 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
168169
convert_system_function(const irep_idt &identifier, function_call_exprt);
169170
[[nodiscard]] exprt convert_bit_select_expr(binary_exprt);
170171
[[nodiscard]] exprt convert_replication_expr(replication_exprt);
172+
[[nodiscard]] exprt convert_power_expr(power_exprt);
171173
[[nodiscard]] exprt convert_shl_expr(shl_exprt);
172174
void implicit_typecast(exprt &, const typet &type);
173175
void tc_binary_expr(exprt &);

0 commit comments

Comments
 (0)