From 1bdaaaa051d7b2955b02167277fecf18be401531 Mon Sep 17 00:00:00 2001 From: kaituo_crypto Date: Thu, 16 Apr 2026 17:27:23 +0800 Subject: [PATCH] ImportVerilog: fix signedness in ConversionExpression lowering --- lib/Conversion/ImportVerilog/Expressions.cpp | 11 ++++++++- .../ImportVerilog/ImportVerilogInternals.h | 4 ++++ .../ImportVerilog/conversion-signedness.sv | 24 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/Conversion/ImportVerilog/conversion-signedness.sv diff --git a/lib/Conversion/ImportVerilog/Expressions.cpp b/lib/Conversion/ImportVerilog/Expressions.cpp index 6c25fe1dd981..83d5f0f8f465 100644 --- a/lib/Conversion/ImportVerilog/Expressions.cpp +++ b/lib/Conversion/ImportVerilog/Expressions.cpp @@ -969,7 +969,7 @@ struct RvalueExprVisitor : public ExprVisitor { auto type = context.convertType(*expr.type); if (!type) return {}; - return context.convertRvalueExpression(expr.operand(), type); + return context.convertRvalueExpression(expr.operand(), type, expr.type->isSigned()); } // Handle blocking and non-blocking assignments. @@ -2517,6 +2517,15 @@ Value Context::convertRvalueExpression(const slang::ast::Expression &expr, materializeConversion(requiredType, value, expr.type->isSigned(), loc); return value; } +Value Context::convertRvalueExpression(const slang::ast::Expression &expr, + Type requiredType,bool conversionIsSigned) { + auto loc = convertLocation(expr.sourceRange); + auto value = expr.visit(RvalueExprVisitor(*this, loc)); + if (value && requiredType) + value = + materializeConversion(requiredType, value, conversionIsSigned, loc); + return value; +} Value Context::convertLvalueExpression(const slang::ast::Expression &expr) { auto loc = convertLocation(expr.sourceRange); diff --git a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h index c8dcc02032a2..ffd446370321 100644 --- a/lib/Conversion/ImportVerilog/ImportVerilogInternals.h +++ b/lib/Conversion/ImportVerilog/ImportVerilogInternals.h @@ -243,6 +243,10 @@ struct Context { // Convert an expression AST node to MLIR ops. Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType = {}); + // When materializing a conversion, the caller may need to override the + // source expression's signedness with the conversion's own semantics. + Value convertRvalueExpression(const slang::ast::Expression &expr, + Type requiredType,bool conversionIsSigned); Value convertLvalueExpression(const slang::ast::Expression &expr); // Convert an assertion expression AST node to MLIR ops. diff --git a/test/Conversion/ImportVerilog/conversion-signedness.sv b/test/Conversion/ImportVerilog/conversion-signedness.sv new file mode 100644 index 000000000000..0edf969483bd --- /dev/null +++ b/test/Conversion/ImportVerilog/conversion-signedness.sv @@ -0,0 +1,24 @@ +// RUN: circt-verilog --ir-moore %s | FileCheck %s --check-prefix=MOORE +// REQUIRES: slang + +module M( + input logic [7:0] in1, + input logic signed [7:0] in2, + output logic signed [8:0] mux_out +); + logic [7:0] unsigned_src; + logic signed [7:0] signed_src; + + always_comb signed_src = in2 >>> 1; + always_comb unsigned_src = in1 >> 1; + always_comb mux_out = signed_src + unsigned_src; +endmodule + +// MOORE-LABEL: moore.module @M( +// MOORE: moore.procedure always_comb { +// MOORE: %[[SIGNED_READ:.+]] = moore.read %signed_src : +// MOORE: %[[SIGNED_ZEXT:.+]] = moore.zext %[[SIGNED_READ]] : l8 -> l9 +// MOORE-NOT: moore.sext +// MOORE: %[[UNSIGNED_READ:.+]] = moore.read %unsigned_src : +// MOORE: %[[UNSIGNED_ZEXT:.+]] = moore.zext %[[UNSIGNED_READ]] : l8 -> l9 +// MOORE: %[[ADD:.+]] = moore.add %[[SIGNED_ZEXT]], %[[UNSIGNED_ZEXT]] : l9 \ No newline at end of file