@@ -20,6 +20,7 @@ Author: Daniel Kroening, kroening@kroening.com
2020#include < util/std_expr.h>
2121#include < util/string2int.h>
2222
23+ #include " aval_bval_encoding.h"
2324#include " convert_literals.h"
2425#include " expr2verilog.h"
2526#include " verilog_bits.h"
@@ -488,6 +489,31 @@ exprt verilog_typecheck_exprt::convert_expr_function_call(
488489
489490/* ******************************************************************\
490491
492+ Function: verilog_typecheck_exprt::isunknown
493+
494+ Inputs:
495+
496+ Outputs:
497+
498+ Purpose:
499+
500+ \*******************************************************************/
501+
502+ constant_exprt verilog_typecheck_exprt::isunknown (const constant_exprt &expr)
503+ {
504+ // constant folding for $isunknown
505+ auto bval = ::bval (expr);
506+ auto bval_simplified = verilog_simplifier (bval, ns);
507+ CHECK_RETURN (bval_simplified.is_constant ());
508+ auto all_zeros = to_bv_type (bval_simplified.type ()).all_zeros_expr ();
509+ if (bval_simplified == all_zeros)
510+ return false_exprt{};
511+ else
512+ return true_exprt{};
513+ }
514+
515+ /* ******************************************************************\
516+
491517Function: verilog_typecheck_exprt::bits
492518
493519 Inputs:
@@ -979,6 +1005,18 @@ exprt verilog_typecheck_exprt::convert_system_function(
9791005
9801006 return std::move (expr);
9811007 }
1008+ else if (identifier == " $isunknown" )
1009+ {
1010+ if (arguments.size () != 1 )
1011+ {
1012+ throw errort ().with_location (expr.source_location ())
1013+ << " $isunknown takes one argument" ;
1014+ }
1015+
1016+ expr.type () = bool_typet ();
1017+
1018+ return std::move (expr);
1019+ }
9821020 else if (identifier == " $past" )
9831021 {
9841022 if (arguments.size () == 0 || arguments.size () >= 4 )
@@ -1784,6 +1822,17 @@ exprt verilog_typecheck_exprt::elaborate_constant_system_function_call(
17841822 DATA_INVARIANT (arguments.size () == 1 , " $typename takes one argument" );
17851823 return typename_string (arguments[0 ]);
17861824 }
1825+ else if (identifier == " $isunknown" )
1826+ {
1827+ DATA_INVARIANT (arguments.size () == 1 , " $isunknown takes one argument" );
1828+
1829+ auto op = elaborate_constant_expression (arguments[0 ]);
1830+
1831+ if (!op.is_constant ())
1832+ return std::move (expr); // give up
1833+ else
1834+ return isunknown (to_constant_expr (op));
1835+ }
17871836 else
17881837 return std::move (expr); // don't know it, won't elaborate
17891838}
0 commit comments