Skip to content

SystemVerilog: wildcard equality and inequality #661

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
Sep 9, 2024
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
14 changes: 12 additions & 2 deletions regression/verilog/expressions/wildcard_equality1.desc
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
KNOWNBUG
CORE broken-smt-backend
wildcard_equality1.sv
--bound 0
^EXIT=0$
^\[main\.property01\] always 10 ==\? 10 === 1: PROVED up to bound 0$
^\[main\.property02\] always 10 ==\? 20 === 0: PROVED up to bound 0$
^\[main\.property03\] always 10 !=\? 20 === 1: PROVED up to bound 0$
^\[main\.property04\] always 10 ==\? 20 === 0: PROVED up to bound 0$
^\[main\.property05\] always 2'b00 ==\? 2'b0x === 1: PROVED up to bound 0$
^\[main\.property06\] always 2'b10 ==\? 2'b0x === 0: PROVED up to bound 0$
^\[main\.property07\] always 2'b00 !=\? 2'b0x === 0: PROVED up to bound 0$
^\[main\.property08\] always 2'b10 !=\? 2'b0x === 1: PROVED up to bound 0$
^\[main\.property09\] always 2'b11 ==\? 2'b11 === 0: REFUTED$
^\[main\.property10\] always 2'sb11 ==\? 2'sb11 === 1: PROVED up to bound 0$
^EXIT=10$
^SIGNAL=0$
--
^warning: ignoring
Expand Down
2 changes: 2 additions & 0 deletions src/hw_cbmc_irep_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ IREP_ID_ONE(Verilog)
IREP_ID_ONE(verilog_assignment_pattern)
IREP_ID_ONE(verilog_logical_equality)
IREP_ID_ONE(verilog_logical_inequality)
IREP_ID_ONE(verilog_wildcard_equality)
IREP_ID_ONE(verilog_wildcard_inequality)
IREP_ID_ONE(verilog_explicit_cast)
IREP_ID_ONE(verilog_size_cast)
IREP_ID_ONE(verilog_implicit_typecast)
Expand Down
34 changes: 34 additions & 0 deletions src/verilog/aval_bval_encoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,37 @@ exprt aval_bval(const verilog_logical_inequality_exprt &expr)
return if_exprt{
has_xz, make_x(), aval_bval_conversion(equality, lower_to_aval_bval(type))};
}

exprt aval_bval(const verilog_wildcard_equality_exprt &expr)
{
auto &type = expr.type();
PRECONDITION(type.id() == ID_verilog_unsignedbv);

// We are using masking based on the pattern given as rhs.
// The aval is the comparison value, and the
// negation of bval is the mask.
const auto &pattern_aval = ::aval(expr.rhs());
const auto &pattern_bval = ::bval(expr.rhs());
auto mask_expr = bitnot_exprt{pattern_bval};

return equal_exprt{
bitand_exprt{aval(expr.lhs()), mask_expr},
bitand_exprt{pattern_aval, mask_expr}};
}

exprt aval_bval(const verilog_wildcard_inequality_exprt &expr)
{
auto &type = expr.type();
PRECONDITION(type.id() == ID_verilog_unsignedbv);

// We are using masking based on the pattern given as rhs.
// The aval is the comparison value, and the
// negation of bval is the mask.
const auto &pattern_aval = ::aval(expr.rhs());
const auto &pattern_bval = ::bval(expr.rhs());
auto mask_expr = bitnot_exprt{pattern_bval};

return notequal_exprt{
bitand_exprt{aval(expr.lhs()), mask_expr},
bitand_exprt{pattern_aval, mask_expr}};
}
5 changes: 5 additions & 0 deletions src/verilog/aval_bval_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@ 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 &);

/// lowering for ==?
exprt aval_bval(const verilog_wildcard_equality_exprt &);
/// lowering for !=?
exprt aval_bval(const verilog_wildcard_inequality_exprt &);

#endif
12 changes: 12 additions & 0 deletions src/verilog/expr2verilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,18 @@ expr2verilogt::convert(const exprt &src, verilog_precedencet &precedence)
"!==",
precedence = verilog_precedencet::EQUALITY);

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

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

else if(src.id()==ID_not)
return convert_unary(
to_not_expr(src), "!", precedence = verilog_precedencet::NOT);
Expand Down
56 changes: 31 additions & 25 deletions src/verilog/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -372,32 +372,34 @@ int yyverilogerror(const char *error)
%token TOK_UWIRE "uwire"

/* System Verilog Operators */
%token TOK_VERTBARMINUSGREATER "|->"
%token TOK_VERTBAREQUALGREATER "|=>"
%token TOK_PLUSPLUS "++"
%token TOK_MINUSMINUS "--"
%token TOK_PLUSEQUAL "+="
%token TOK_PLUSCOLON "+:"
%token TOK_MINUSEQUAL "-="
%token TOK_MINUSCOLON "-:"
%token TOK_ASTERICEQUAL "*="
%token TOK_SLASHEQUAL "/="
%token TOK_PERCENTEQUAL "%="
%token TOK_AMPEREQUAL "&="
%token TOK_CARETEQUAL "^="
%token TOK_VERTBAREQUAL "|="
%token TOK_LESSLESSEQUAL "<<="
%token TOK_GREATERGREATEREQUAL ">>="
%token TOK_LESSLESSLESSEQUAL "<<<="
%token TOK_VERTBARMINUSGREATER "|->"
%token TOK_VERTBAREQUALGREATER "|=>"
%token TOK_PLUSPLUS "++"
%token TOK_MINUSMINUS "--"
%token TOK_PLUSEQUAL "+="
%token TOK_PLUSCOLON "+:"
%token TOK_MINUSEQUAL "-="
%token TOK_MINUSCOLON "-:"
%token TOK_ASTERICEQUAL "*="
%token TOK_SLASHEQUAL "/="
%token TOK_PERCENTEQUAL "%="
%token TOK_AMPEREQUAL "&="
%token TOK_CARETEQUAL "^="
%token TOK_VERTBAREQUAL "|="
%token TOK_LESSLESSEQUAL "<<="
%token TOK_GREATERGREATEREQUAL ">>="
%token TOK_LESSLESSLESSEQUAL "<<<="
%token TOK_GREATERGREATERGREATEREQUAL ">>>="
%token TOK_HASHHASH "##"
%token TOK_HASHMINUSHASH "#-#"
%token TOK_HASHEQUALHASH "#=#"
%token TOK_COLONCOLON "::"
%token TOK_LSQASTERIC "[*"
%token TOK_LSQPLUS "[+"
%token TOK_LSQEQUAL "[="
%token TOK_LSQMINUSGREATER "[->"
%token TOK_HASHHASH "##"
%token TOK_HASHMINUSHASH "#-#"
%token TOK_HASHEQUALHASH "#=#"
%token TOK_COLONCOLON "::"
%token TOK_EQUALEQUALQUESTION "==?"
%token TOK_EXCLAMEQUALQUESTION "!=?"
%token TOK_LSQASTERIC "[*"
%token TOK_LSQPLUS "[+"
%token TOK_LSQEQUAL "[="
%token TOK_LSQMINUSGREATER "[->"

/* System Verilog Keywords */
%token TOK_ACCEPT_ON "accept_on"
Expand Down Expand Up @@ -3546,6 +3548,10 @@ expression:
{ init($$, ID_verilog_logical_equality); mto($$, $1); mto($$, $3); }
| expression TOK_EXCLAMEQUAL expression
{ init($$, ID_verilog_logical_inequality); mto($$, $1); mto($$, $3); }
| expression TOK_EQUALEQUALQUESTION expression
{ init($$, ID_verilog_wildcard_equality); mto($$, $1); mto($$, $3); }
| expression TOK_EXCLAMEQUALQUESTION expression
{ init($$, ID_verilog_wildcard_inequality); mto($$, $1); mto($$, $3); }
| expression TOK_EQUALEQUALEQUAL expression
{ init($$, ID_verilog_case_equality); mto($$, $1); mto($$, $3); }
| expression TOK_EXCLAMEQUALEQUAL expression
Expand Down
2 changes: 2 additions & 0 deletions src/verilog/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ void verilog_scanner_init()
"->" { SYSTEM_VERILOG_OPERATOR(TOK_MINUSGREATER, "->"); }
"'" { SYSTEM_VERILOG_OPERATOR('\'', "'"); }
"::" { SYSTEM_VERILOG_OPERATOR(TOK_COLONCOLON, "::"); }
"==?" { SYSTEM_VERILOG_OPERATOR(TOK_EQUALEQUALQUESTION, "==?"); }
"!=?" { SYSTEM_VERILOG_OPERATOR(TOK_EXCLAMEQUALQUESTION, "!=?"); }
/* Table 16-1 in 1800-2017 suggests the following tokens for sequence operators */
"[*" { SYSTEM_VERILOG_OPERATOR(TOK_LSQASTERIC, "[*"); }
"[+" { SYSTEM_VERILOG_OPERATOR(TOK_LSQPLUS, "[+"); }
Expand Down
44 changes: 44 additions & 0 deletions src/verilog/verilog_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,50 @@ to_verilog_logical_inequality_expr(exprt &expr)
return static_cast<verilog_logical_inequality_exprt &>(expr);
}

/// ==?
class verilog_wildcard_equality_exprt : public equal_exprt
{
public:
};

inline const verilog_wildcard_equality_exprt &
to_verilog_wildcard_equality_expr(const exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_wildcard_equality);
binary_exprt::check(expr);
return static_cast<const verilog_wildcard_equality_exprt &>(expr);
}

inline verilog_wildcard_equality_exprt &
to_verilog_wildcard_equality_expr(exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_wildcard_equality);
binary_exprt::check(expr);
return static_cast<verilog_wildcard_equality_exprt &>(expr);
}

/// !=?
class verilog_wildcard_inequality_exprt : public equal_exprt
{
public:
};

inline const verilog_wildcard_inequality_exprt &
to_verilog_wildcard_inequality_expr(const exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_wildcard_inequality);
binary_exprt::check(expr);
return static_cast<const verilog_wildcard_inequality_exprt &>(expr);
}

inline verilog_wildcard_inequality_exprt &
to_verilog_wildcard_inequality_expr(exprt &expr)
{
PRECONDITION(expr.id() == ID_verilog_wildcard_inequality);
binary_exprt::check(expr);
return static_cast<verilog_wildcard_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 @@ -402,6 +402,18 @@ exprt verilog_synthesist::synth_expr(exprt expr, symbol_statet symbol_state)
op = synth_expr(op, symbol_state);
return aval_bval(to_verilog_logical_inequality_expr(expr));
}
else if(expr.id() == ID_verilog_wildcard_equality)
{
for(auto &op : expr.operands())
op = synth_expr(op, symbol_state);
return aval_bval(to_verilog_wildcard_equality_expr(expr));
}
else if(expr.id() == ID_verilog_wildcard_inequality)
{
for(auto &op : expr.operands())
op = synth_expr(op, symbol_state);
return aval_bval(to_verilog_wildcard_inequality_expr(expr));
}
else if(expr.has_operands())
{
for(auto &op : expr.operands())
Expand Down
14 changes: 14 additions & 0 deletions src/verilog/verilog_typecheck_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2599,6 +2599,20 @@ exprt verilog_typecheck_exprt::convert_binary_expr(binary_exprt expr)

return std::move(expr);
}
else if(
expr.id() == ID_verilog_wildcard_equality ||
expr.id() == ID_verilog_wildcard_inequality)
{
// ==? and !=?
Forall_operands(it, expr)
convert_expr(*it);

tc_binary_expr(expr);

expr.type() = verilog_unsignedbv_typet(1);

return std::move(expr);
}
else if(expr.id()==ID_verilog_case_equality ||
expr.id()==ID_verilog_case_inequality)
{
Expand Down