Skip to content

Commit ab21468

Browse files
committed
aval/bval encoding for shifts
This adds an aval/bval encoding for four-valued shift expressions to the Verilog frontend.
1 parent 90801d3 commit ab21468

File tree

4 files changed

+77
-12
lines changed

4 files changed

+77
-12
lines changed

src/verilog/aval_bval_encoding.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,29 @@ exprt aval_bval(const typecast_exprt &expr)
444444
auto op_aval_zero = to_bv_type(op_aval.type()).all_zeros_expr();
445445
return and_exprt{not_exprt{op_has_xz}, notequal_exprt{op_aval, op_aval_zero}};
446446
}
447+
448+
exprt aval_bval(const shift_exprt &expr)
449+
{
450+
PRECONDITION(is_four_valued(expr.type()));
451+
452+
auto distance_has_xz = has_xz(expr.distance());
453+
auto distance_aval = aval(expr.distance());
454+
455+
// the shift distance must have a numerical interpretation
456+
auto distance_aval_casted = typecast_exprt{
457+
distance_aval,
458+
unsignedbv_typet{to_bitvector_type(distance_aval.type()).get_width()}};
459+
460+
// shift aval and bval separately
461+
auto op_aval = aval(expr.op());
462+
auto op_bval = bval(expr.op());
463+
464+
auto aval_shifted = shift_exprt{op_aval, expr.id(), distance_aval_casted};
465+
auto bval_shifted = shift_exprt{op_bval, expr.id(), distance_aval_casted};
466+
467+
auto combined = combine_aval_bval(
468+
aval_shifted, bval_shifted, lower_to_aval_bval(expr.type()));
469+
470+
auto x = make_x(expr.type());
471+
return if_exprt{distance_has_xz, x, combined};
472+
}

src/verilog/aval_bval_encoding.h

+2
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,7 @@ exprt aval_bval(const verilog_iff_exprt &);
6363
exprt aval_bval(const verilog_implies_exprt &);
6464
/// lowering for typecasts
6565
exprt aval_bval(const typecast_exprt &);
66+
/// lowering for shifts
67+
exprt aval_bval(const shift_exprt &);
6668

6769
#endif

src/verilog/verilog_lowering.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ Author: Daniel Kroening, [email protected]
2121
#include "verilog_expr.h"
2222
#include "verilog_types.h"
2323

24+
#include <iostream>
25+
2426
/// Lowers
2527
/// * the three Verilog real types to floatbv;
2628
/// * Verilog integer to signedbv[32]
@@ -608,6 +610,13 @@ exprt verilog_lowering(exprt expr)
608610

609611
return expr;
610612
}
613+
else if(expr.id() == ID_lshr || expr.id() == ID_ashr || expr.id() == ID_shl)
614+
{
615+
if(is_four_valued(expr.type()))
616+
return aval_bval(to_shift_expr(expr));
617+
else
618+
return expr;
619+
}
611620
else
612621
return expr; // leave as is
613622

src/verilog/verilog_typecheck_expr.cpp

+40-12
Original file line numberDiff line numberDiff line change
@@ -2868,15 +2868,22 @@ Function: verilog_typecheck_exprt::convert_shl_expr
28682868

28692869
exprt verilog_typecheck_exprt::convert_shl_expr(shl_exprt expr)
28702870
{
2871-
convert_expr(expr.op0());
2872-
convert_expr(expr.op1());
2873-
2871+
convert_expr(expr.lhs());
2872+
convert_expr(expr.rhs());
2873+
28742874
no_bool_ops(expr);
28752875

2876-
// the bit width of a shift is always the bit width of the left operand
2877-
const typet &op0_type=expr.op0().type();
2878-
2879-
expr.type()=op0_type;
2876+
const typet &lhs_type = expr.lhs().type();
2877+
const typet &rhs_type = expr.rhs().type();
2878+
2879+
// The bit width of a shift is always the bit width of the left operand.
2880+
// The result is four-valued if either of the operands is four-valued.
2881+
if(is_four_valued(lhs_type))
2882+
expr.type() = lhs_type;
2883+
else if(is_four_valued(rhs_type))
2884+
expr.type() = four_valued(lhs_type);
2885+
else
2886+
expr.type() = lhs_type;
28802887

28812888
return std::move(expr);
28822889
}
@@ -3066,16 +3073,26 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
30663073
must_be_integral(expr.rhs());
30673074
no_bool_ops(expr);
30683075

3069-
const typet &op0_type = expr.op0().type();
3076+
const typet &lhs_type = expr.lhs().type();
3077+
const typet &rhs_type = expr.rhs().type();
30703078

30713079
if(
3072-
op0_type.id() == ID_signedbv || op0_type.id() == ID_verilog_signedbv ||
3073-
op0_type.id() == ID_integer)
3080+
lhs_type.id() == ID_signedbv || lhs_type.id() == ID_verilog_signedbv ||
3081+
lhs_type.id() == ID_integer)
3082+
{
30743083
expr.id(ID_ashr);
3084+
}
30753085
else
30763086
expr.id(ID_lshr);
30773087

3078-
expr.type()=op0_type;
3088+
// The bit width of a shift is always the bit width of the left operand.
3089+
// The result is four-valued if either of the operands is four-valued.
3090+
if(is_four_valued(lhs_type))
3091+
expr.type() = lhs_type;
3092+
else if(is_four_valued(rhs_type))
3093+
expr.type() = four_valued(lhs_type);
3094+
else
3095+
expr.type() = lhs_type;
30793096

30803097
return std::move(expr);
30813098
}
@@ -3092,7 +3109,18 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
30923109
must_be_integral(expr.lhs());
30933110
must_be_integral(expr.rhs());
30943111
no_bool_ops(expr);
3095-
expr.type()=expr.op0().type();
3112+
3113+
const typet &lhs_type = expr.lhs().type();
3114+
const typet &rhs_type = expr.rhs().type();
3115+
3116+
// The bit width of a shift is always the bit width of the left operand.
3117+
// The result is four-valued if either of the operands is four-valued.
3118+
if(is_four_valued(lhs_type))
3119+
expr.type() = lhs_type;
3120+
else if(is_four_valued(rhs_type))
3121+
expr.type() = four_valued(lhs_type);
3122+
else
3123+
expr.type() = lhs_type;
30963124

30973125
return std::move(expr);
30983126
}

0 commit comments

Comments
 (0)