Skip to content

Commit

Permalink
Merge pull request #656 from diffblue/verilog_equality_lowering
Browse files Browse the repository at this point in the history
aval/bval lowering for Verilog logical equality
  • Loading branch information
kroening authored Sep 4, 2024
2 parents 66ab576 + 15b9299 commit f25aad5
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 10 deletions.
15 changes: 12 additions & 3 deletions regression/verilog/expressions/equality1.desc
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
KNOWNBUG
CORE broken-smt-backend
equality1.v
--bound 0
^EXIT=0$
^\[.*\] always 10 == 10 === 1: PROVED up to bound 0$
^\[.*\] always 10 == 20 === 0: PROVED up to bound 0$
^\[.*\] always 10 != 20 === 1: PROVED up to bound 0$
^\[.*\] always 10 == 20 === 0: PROVED up to bound 0$
^\[.*\] always 1'bx == 10 === 1'bx: PROVED up to bound 0$
^\[.*\] always 1'bz == 20 === 1'bx: PROVED up to bound 0$
^\[.*\] always 1'bx != 10 === 1'bx: PROVED up to bound 0$
^\[.*\] always 1'bz != 20 === 1'bx: PROVED up to bound 0$
^\[.*\] always 2'b11 == 2'b11 === 0: REFUTED$
^\[.*\] always 2'sb-1 == 2'sb-1 === 1: PROVED up to bound 0$
^EXIT=10$
^SIGNAL=0$
--
^warning: ignoring
--
Missing Verilog case equality implementation.
4 changes: 2 additions & 2 deletions regression/verilog/expressions/equality1.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module main;
always assert property06: ('bz==20)==='bx;
always assert property07: ('bx!=10)==='bx;
always assert property08: ('bz!=20)==='bx;
always assert property09: ('sb1=='b11)===0; // zero extension
always assert property10: ('sb1=='sb11)===1; // sign extension
always assert property09: (1'sb1==2'b11)===0; // zero extension
always assert property10: (1'sb1==2'sb11)===1; // sign extension

endmodule
15 changes: 13 additions & 2 deletions regression/verilog/expressions/equality2.desc
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
CORE broken-smt-backend
equality2.v
--bound 0
^EXIT=0$
^\[.*\] always 10 === 10 == 1: PROVED up to bound 0$
^\[.*\] always 10 === 20 == 0: PROVED up to bound 0$
^\[.*\] always 10 !== 10 == 0: PROVED up to bound 0$
^\[.*\] always 10 !== 20 == 1: PROVED up to bound 0$
^\[.*\] always 1'bx === 1'bx == 1: PROVED up to bound 0$
^\[.*\] always 1'bz === 1'bz == 1: PROVED up to bound 0$
^\[.*\] always 1'bx === 1'bz == 0: PROVED up to bound 0$
^\[.*\] always 1'bx === 1 == 0: PROVED up to bound 0$
^\[.*\] always 1'bz === 1 == 0: PROVED up to bound 0$
^\[.*\] always 1 === 1 == 1: PROVED up to bound 0$
^\[.*\] always 3'b11 === 3'b111 == 1: REFUTED$
^\[.*\] always 3'sb-1 === 3'sb-1 == 1: PROVED up to bound 0$
^EXIT=10$
^SIGNAL=0$
--
^warning: ignoring
--
Missing Verilog case equality implementation.
4 changes: 2 additions & 2 deletions regression/verilog/expressions/equality2.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module main;
always assert property08: ('bx==='b1)==0;
always assert property09: ('bz==='b1)==0;
always assert property10: ('b1==='b01)==1; // zero extension
always assert property11: ('b011==='sb11)==1; // zero extension
always assert property12: ('sb011==='sb11)==1; // sign extension
always assert property11: (3'b011===2'sb11)==1; // zero extension
always assert property12: (3'sb111===2'sb11)==1; // sign extension

endmodule
1 change: 1 addition & 0 deletions src/hw_cbmc_irep_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ IREP_ID_ONE(iff)
IREP_ID_ONE(offset)
IREP_ID_ONE(xnor)
IREP_ID_ONE(specify)
IREP_ID_ONE(x)
IREP_ID_ONE(verilog_empty_item)
IREP_ID_ONE(verilog_import_item)
IREP_ID_ONE(verilog_module)
Expand Down
49 changes: 49 additions & 0 deletions src/verilog/aval_bval_encoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Author: Daniel Kroening, [email protected]
#include <util/mathematical_types.h>
#include <util/std_expr.h>

#include "verilog_types.h"

bv_typet aval_bval_type(std::size_t width, irep_idt source_type)
{
PRECONDITION(!source_type.empty());
Expand All @@ -34,12 +36,22 @@ bool is_aval_bval(const typet &type)
return type.id() == ID_bv && !type.get(ID_C_verilog_aval_bval).empty();
}

bool is_aval_bval(const exprt &expr)
{
return is_aval_bval(expr.type());
}

std::size_t aval_bval_width(const typet &type)
{
PRECONDITION(is_aval_bval(type));
return to_bv_type(type).get_width() / 2;
}

std::size_t aval_bval_width(const exprt &expr)
{
return aval_bval_width(expr.type());
}

typet aval_bval_underlying(const typet &src)
{
auto id = src.get(ID_C_verilog_aval_bval);
Expand Down Expand Up @@ -198,3 +210,40 @@ exprt aval_bval_concatenation(

return combine_aval_bval(concatenate(new_aval), concatenate(new_bval), type);
}

/// return true iff 'expr' contains either x or z
exprt has_xz(const exprt &expr)
{
PRECONDITION(is_aval_bval(expr));
auto width = aval_bval_width(expr);
return notequal_exprt{bval(expr), bv_typet{width}.all_zeros_expr()};
}

/// return 'x', one bit
exprt make_x()
{
auto type = verilog_unsignedbv_typet{1};
return lower_to_aval_bval(constant_exprt{ID_x, type});
}

exprt aval_bval(const verilog_logical_equality_exprt &expr)
{
auto &type = expr.type();
PRECONDITION(type.id() == ID_verilog_unsignedbv);
// returns 'x' if either operand contains x or z
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
auto equality = equal_exprt{expr.lhs(), expr.rhs()};
return if_exprt{
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
}

exprt aval_bval(const verilog_logical_inequality_exprt &expr)
{
auto &type = expr.type();
PRECONDITION(type.id() == ID_verilog_unsignedbv);
// returns 'x' if either operand contains x or z
auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())};
auto equality = notequal_exprt{expr.lhs(), expr.rhs()};
return if_exprt{
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
}
6 changes: 5 additions & 1 deletion src/verilog/aval_bval_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ Author: Daniel Kroening, [email protected]
#define CPROVER_VERILOG_AVAL_BVAL_H

#include <util/bitvector_types.h>
#include <util/std_expr.h>

#include "verilog_expr.h"

// bit-concoding for four-valued types
//
Expand All @@ -36,4 +37,7 @@ exprt aval_bval_conversion(const exprt &, const typet &);

exprt aval_bval_concatenation(const exprt::operandst &, const typet &);

exprt aval_bval(const verilog_logical_equality_exprt &);
exprt aval_bval(const verilog_logical_inequality_exprt &);

#endif
8 changes: 8 additions & 0 deletions src/verilog/expr2verilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1222,10 +1222,18 @@ expr2verilogt::convert(const exprt &src, verilog_precedencet &precedence)
return convert_binary(
to_multi_ary_expr(src), "==", precedence = verilog_precedencet::EQUALITY);

else if(src.id() == ID_verilog_logical_equality)
return convert_binary(
to_multi_ary_expr(src), "==", precedence = verilog_precedencet::EQUALITY);

else if(src.id()==ID_notequal)
return convert_binary(
to_multi_ary_expr(src), "!=", precedence = verilog_precedencet::EQUALITY);

else if(src.id() == ID_verilog_logical_inequality)
return convert_binary(
to_multi_ary_expr(src), "!=", precedence = verilog_precedencet::EQUALITY);

else if(src.id()==ID_verilog_case_equality)
return convert_binary(
to_multi_ary_expr(src),
Expand Down
46 changes: 46 additions & 0 deletions src/verilog/verilog_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,52 @@ to_hierarchical_identifier_expr(exprt &expr)
return static_cast<hierarchical_identifier_exprt &>(expr);
}

/// ==
/// returns 'x' if either operand contains x or z
class verilog_logical_equality_exprt : public equal_exprt
{
public:
};

inline const verilog_logical_equality_exprt &
to_verilog_logical_equality_expr(const exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_logical_equality);
binary_exprt::check(expr);
return static_cast<const verilog_logical_equality_exprt &>(expr);
}

inline verilog_logical_equality_exprt &
to_verilog_logical_equality_expr(exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_logical_equality);
binary_exprt::check(expr);
return static_cast<verilog_logical_equality_exprt &>(expr);
}

/// !=
/// returns 'x' if either operand contains x or z
class verilog_logical_inequality_exprt : public equal_exprt
{
public:
};

inline const verilog_logical_inequality_exprt &
to_verilog_logical_inequality_expr(const exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_logical_inequality);
binary_exprt::check(expr);
return static_cast<const verilog_logical_inequality_exprt &>(expr);
}

inline verilog_logical_inequality_exprt &
to_verilog_logical_inequality_expr(exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_logical_inequality);
binary_exprt::check(expr);
return static_cast<verilog_logical_inequality_exprt &>(expr);
}

class function_call_exprt : public binary_exprt
{
public:
Expand Down
12 changes: 12 additions & 0 deletions src/verilog/verilog_synthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,18 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
.with_source_location(expr);
}
}
else if(expr.id() == ID_verilog_logical_equality)
{
for(auto &op : expr.operands())
op = synth_expr(op, symbol_state);
return aval_bval(to_verilog_logical_equality_expr(expr));
}
else if(expr.id() == ID_verilog_logical_inequality)
{
for(auto &op : expr.operands())
op = synth_expr(op, symbol_state);
return aval_bval(to_verilog_logical_inequality_expr(expr));
}
else if(expr.has_operands())
{
for(auto &op : expr.operands())
Expand Down

0 comments on commit f25aad5

Please sign in to comment.