From 7c34d9d3c391fe2e1f38b117d52e5aa59be23569 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Thu, 16 Oct 2025 11:09:57 -0700 Subject: [PATCH] Verilog: lowering for four-valued zero-extend This adds a lowering for zero_extend expressions for four-valued operands. --- regression/verilog/expressions/equality4.desc | 5 ++--- src/verilog/aval_bval_encoding.cpp | 19 +++++++++++++++++++ src/verilog/aval_bval_encoding.h | 2 ++ src/verilog/verilog_lowering.cpp | 14 ++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/regression/verilog/expressions/equality4.desc b/regression/verilog/expressions/equality4.desc index 876c1fb1d..bc94403d6 100644 --- a/regression/verilog/expressions/equality4.desc +++ b/regression/verilog/expressions/equality4.desc @@ -1,9 +1,8 @@ -KNOWNBUG -equality4.v +CORE +equality4.sv ^EXIT=0$ ^SIGNAL=0$ -- ^warning: ignoring -- -zero_extend doesn't work for four-valued operands. diff --git a/src/verilog/aval_bval_encoding.cpp b/src/verilog/aval_bval_encoding.cpp index dc8f246bf..23dfc8c91 100644 --- a/src/verilog/aval_bval_encoding.cpp +++ b/src/verilog/aval_bval_encoding.cpp @@ -537,6 +537,25 @@ exprt aval_bval(const shift_exprt &expr) return if_exprt{distance_has_xz, x, combined}; } +exprt aval_bval(const zero_extend_exprt &expr) +{ + PRECONDITION(is_four_valued(expr)); + + auto expr_aval_bval_type = lower_to_aval_bval(expr.type()); + + // zero-extend aval and bval separately! + auto op_aval = aval(expr.op()); + auto op_bval = bval(expr.op()); + + auto aval_ext_width = aval_bval_width(expr_aval_bval_type); + auto ext_type = bv_typet{aval_ext_width}; + + auto aval_extended = zero_extend_exprt{op_aval, ext_type}; + auto bval_extended = zero_extend_exprt{op_bval, ext_type}; + + return combine_aval_bval(aval_extended, bval_extended, expr_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 cb0c179d9..10c93c97d 100644 --- a/src/verilog/aval_bval_encoding.h +++ b/src/verilog/aval_bval_encoding.h @@ -67,6 +67,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 zero extension +exprt aval_bval(const zero_extend_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 b842de7f7..ff9672b6a 100644 --- a/src/verilog/verilog_lowering.cpp +++ b/src/verilog/verilog_lowering.cpp @@ -650,6 +650,20 @@ exprt verilog_lowering(exprt expr) else return expr; } + else if(expr.id() == ID_zero_extend) + { + auto &zero_extend = to_zero_extend_expr(expr); + + if( + is_four_valued(zero_extend.type()) || + is_four_valued(zero_extend.op().type())) + { + // encode into aval/bval + return aval_bval(zero_extend); + } + else + return expr; // leave as is + } else return expr; // leave as is