Skip to content

aval/bval encoding for shifts #1078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions regression/verilog/expressions/shl3.desc
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
KNOWNBUG
CORE
shl3.sv
--bound 0
^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
--
aval/bval encoding is missing.
3 changes: 1 addition & 2 deletions regression/verilog/expressions/shr3.desc
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
KNOWNBUG
CORE
shr3.sv
--bound 0
^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
--
aval/bval encoding is missing.
26 changes: 26 additions & 0 deletions src/verilog/aval_bval_encoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,29 @@ exprt aval_bval(const typecast_exprt &expr)
auto op_aval_zero = to_bv_type(op_aval.type()).all_zeros_expr();
return and_exprt{not_exprt{op_has_xz}, notequal_exprt{op_aval, op_aval_zero}};
}

exprt aval_bval(const shift_exprt &expr)
{
PRECONDITION(is_four_valued(expr.type()));

auto distance_has_xz = has_xz(expr.distance());
auto distance_aval = aval(expr.distance());

// the shift distance must have a numerical interpretation
auto distance_aval_casted = typecast_exprt{
distance_aval,
unsignedbv_typet{to_bitvector_type(distance_aval.type()).get_width()}};

// shift aval and bval separately
auto op_aval = aval(expr.op());
auto op_bval = bval(expr.op());

auto aval_shifted = shift_exprt{op_aval, expr.id(), distance_aval_casted};
auto bval_shifted = shift_exprt{op_bval, expr.id(), distance_aval_casted};

auto combined = combine_aval_bval(
aval_shifted, bval_shifted, lower_to_aval_bval(expr.type()));

auto x = make_x(expr.type());
return if_exprt{distance_has_xz, x, combined};
}
2 changes: 2 additions & 0 deletions src/verilog/aval_bval_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,7 @@ exprt aval_bval(const verilog_iff_exprt &);
exprt aval_bval(const verilog_implies_exprt &);
/// lowering for typecasts
exprt aval_bval(const typecast_exprt &);
/// lowering for shifts
exprt aval_bval(const shift_exprt &);

#endif
7 changes: 7 additions & 0 deletions src/verilog/verilog_lowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,13 @@ exprt verilog_lowering(exprt expr)

return expr;
}
else if(expr.id() == ID_lshr || expr.id() == ID_ashr || expr.id() == ID_shl)
{
if(is_four_valued(expr.type()))
return aval_bval(to_shift_expr(expr));
else
return expr;
}
else
return expr; // leave as is

Expand Down
52 changes: 40 additions & 12 deletions src/verilog/verilog_typecheck_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2868,15 +2868,22 @@ Function: verilog_typecheck_exprt::convert_shl_expr

exprt verilog_typecheck_exprt::convert_shl_expr(shl_exprt expr)
{
convert_expr(expr.op0());
convert_expr(expr.op1());
convert_expr(expr.lhs());
convert_expr(expr.rhs());

no_bool_ops(expr);

// the bit width of a shift is always the bit width of the left operand
const typet &op0_type=expr.op0().type();

expr.type()=op0_type;
const typet &lhs_type = expr.lhs().type();
const typet &rhs_type = expr.rhs().type();

// The bit width of a shift is always the bit width of the left operand.
// The result is four-valued if either of the operands is four-valued.
if(is_four_valued(lhs_type))
expr.type() = lhs_type;
else if(is_four_valued(rhs_type))
expr.type() = four_valued(lhs_type);
else
expr.type() = lhs_type;

return std::move(expr);
}
Expand Down Expand Up @@ -3066,16 +3073,26 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
must_be_integral(expr.rhs());
no_bool_ops(expr);

const typet &op0_type = expr.op0().type();
const typet &lhs_type = expr.lhs().type();
const typet &rhs_type = expr.rhs().type();

if(
op0_type.id() == ID_signedbv || op0_type.id() == ID_verilog_signedbv ||
op0_type.id() == ID_integer)
lhs_type.id() == ID_signedbv || lhs_type.id() == ID_verilog_signedbv ||
lhs_type.id() == ID_integer)
{
expr.id(ID_ashr);
}
else
expr.id(ID_lshr);

expr.type()=op0_type;
// The bit width of a shift is always the bit width of the left operand.
// The result is four-valued if either of the operands is four-valued.
if(is_four_valued(lhs_type))
expr.type() = lhs_type;
else if(is_four_valued(rhs_type))
expr.type() = four_valued(lhs_type);
else
expr.type() = lhs_type;

return std::move(expr);
}
Expand All @@ -3092,7 +3109,18 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)
must_be_integral(expr.lhs());
must_be_integral(expr.rhs());
no_bool_ops(expr);
expr.type()=expr.op0().type();

const typet &lhs_type = expr.lhs().type();
const typet &rhs_type = expr.rhs().type();

// The bit width of a shift is always the bit width of the left operand.
// The result is four-valued if either of the operands is four-valued.
if(is_four_valued(lhs_type))
expr.type() = lhs_type;
else if(is_four_valued(rhs_type))
expr.type() = four_valued(lhs_type);
else
expr.type() = lhs_type;

return std::move(expr);
}
Expand Down
Loading