diff --git a/regression/verilog/asic-world-operators/relational.desc b/regression/verilog/asic-world-operators/relational.desc index 988a8ab9e..c3f343774 100644 --- a/regression/verilog/asic-world-operators/relational.desc +++ b/regression/verilog/asic-world-operators/relational.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE relational.sv --module main --bound 0 ^EXIT=0$ @@ -6,4 +6,3 @@ relational.sv -- ^warning: ignoring -- -x-related tests fail diff --git a/src/verilog/aval_bval_encoding.cpp b/src/verilog/aval_bval_encoding.cpp index d7e3a91b8..4f32514b3 100644 --- a/src/verilog/aval_bval_encoding.cpp +++ b/src/verilog/aval_bval_encoding.cpp @@ -610,6 +610,23 @@ exprt aval_bval(const shift_exprt &expr) return if_exprt{distance_has_xz, x, combined}; } +exprt aval_bval(const binary_relation_exprt &expr) +{ + auto &type = expr.type(); + + PRECONDITION(type.id() == ID_verilog_unsignedbv); + + auto has_xz = or_exprt{::has_xz(expr.lhs()), ::has_xz(expr.rhs())}; + + exprt two_valued_expr = binary_predicate_exprt{ + aval_underlying(expr.lhs()), expr.id(), aval_underlying(expr.rhs())}; + + return if_exprt{ + has_xz, + make_x(type), + aval_bval_conversion(two_valued_expr, lower_to_aval_bval(type))}; +} + exprt default_aval_bval_lowering(const exprt &expr) { auto &type = expr.type(); diff --git a/src/verilog/aval_bval_encoding.h b/src/verilog/aval_bval_encoding.h index 75ef6794c..960ad0b39 100644 --- a/src/verilog/aval_bval_encoding.h +++ b/src/verilog/aval_bval_encoding.h @@ -69,6 +69,8 @@ exprt aval_bval(const verilog_implies_exprt &); exprt aval_bval(const typecast_exprt &); /// lowering for shifts exprt aval_bval(const shift_exprt &); +/// lowering for <=, <, etc. +exprt aval_bval(const binary_relation_exprt &); /// If any operand has x/z, then the result is 'x'. /// Otherwise, the result is the expression applied to the aval diff --git a/src/verilog/verilog_lowering.cpp b/src/verilog/verilog_lowering.cpp index 31dc7eb5a..141723f0d 100644 --- a/src/verilog/verilog_lowering.cpp +++ b/src/verilog/verilog_lowering.cpp @@ -421,6 +421,17 @@ exprt verilog_lowering(exprt expr) else return expr; } + else if( + expr.id() == ID_le || expr.id() == ID_ge || expr.id() == ID_lt || + expr.id() == ID_ge) + { + if(is_four_valued(expr)) + { + return aval_bval(to_binary_relation_expr(expr)); + } + else + return expr; + } else if(expr.id() == ID_concatenation) { if( diff --git a/src/verilog/verilog_typecheck_expr.cpp b/src/verilog/verilog_typecheck_expr.cpp index 1e01aee9c..d38a7f4d6 100644 --- a/src/verilog/verilog_typecheck_expr.cpp +++ b/src/verilog/verilog_typecheck_expr.cpp @@ -3203,11 +3203,19 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr) else if(expr.id()==ID_lt || expr.id()==ID_gt || expr.id()==ID_le || expr.id()==ID_ge) { - expr.type()=bool_typet(); - convert_relation(expr); no_bool_ops(expr); + // This returns 'x' if either of the operands contains x or z. + if(is_four_valued(expr.lhs().type()) || is_four_valued(expr.rhs().type())) + { + expr.type() = verilog_unsignedbv_typet(1); + } + else + { + expr.type() = bool_typet{}; + } + return std::move(expr); } else if(expr.id() == ID_power)