From b1a8e73a609d3065f1caf7a230529443b54295bc Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Wed, 3 Mar 2021 14:36:19 -0500 Subject: [PATCH] sv: fix some edge cases for unbased unsized literals - Fix explicit size cast of unbased unsized literals - Fix unbased unsized literal bound directly to port - Output `is_unsized` flag in `dumpAst` --- frontends/ast/ast.cc | 2 ++ frontends/ast/simplify.cc | 22 +++++++++++++++++- tests/verilog/unbased_unsized.sv | 40 ++++++++++++++++++++++++++++++++ tests/verilog/unbased_unsized.ys | 7 ++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/verilog/unbased_unsized.sv create mode 100644 tests/verilog/unbased_unsized.ys diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 57552d86c..88e6aa1c9 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -317,6 +317,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) const fprintf(f, " reg"); if (is_signed) fprintf(f, " signed"); + if (is_unsized) + fprintf(f, " unsized"); if (basic_prep) fprintf(f, " basic_prep"); if (lookahead) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 5c4dd290f..e7f897b3c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -915,6 +915,22 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } } + if (type == AST_ARGUMENT) + { + if (children.size() == 1 && children[0]->type == AST_CONSTANT) + { + // HACK: For port bindings using unbased unsized literals, mark them + // signed so they sign-extend. The hierarchy will still incorrectly + // generate a warning complaining about resizing the expression. + // This also doesn't handle the complex of something like a ternary + // expression bound to a port, where the actual size of the port is + // needed to resolve the expression correctly. + AstNode *arg = children[0]; + if (arg->is_unsized) + arg->is_signed = true; + } + } + int backup_width_hint = width_hint; bool backup_sign_hint = sign_hint; @@ -3773,7 +3789,11 @@ replace_fcall_later:; case AST_CAST_SIZE: if (children.at(0)->type == AST_CONSTANT && children.at(1)->type == AST_CONSTANT) { int width = children[0]->bitsAsConst().as_int(); - RTLIL::Const val = children[1]->bitsAsConst(width); + RTLIL::Const val; + if (children[1]->is_unsized) + val = children[1]->bitsAsUnsizedConst(width); + else + val = children[1]->bitsAsConst(width); newNode = mkconst_bits(val.bits, children[1]->is_signed); } break; diff --git a/tests/verilog/unbased_unsized.sv b/tests/verilog/unbased_unsized.sv new file mode 100644 index 000000000..1d0c5a72c --- /dev/null +++ b/tests/verilog/unbased_unsized.sv @@ -0,0 +1,40 @@ +module pass_through( + input [63:0] inp, + output [63:0] out +); + assign out = inp; +endmodule + +module top; + logic [63:0] + o01, o02, o03, o04, + o05, o06, o07, o08, + o09, o10, o11, o12, + o13, o14, o15, o16; + assign o01 = '0; + assign o02 = '1; + assign o03 = 'x; + assign o04 = 'z; + assign o05 = 3'('0); + assign o06 = 3'('1); + assign o07 = 3'('x); + assign o08 = 3'('z); + pass_through pt09('0, o09); + pass_through pt10('1, o10); + pass_through pt11('x, o11); + pass_through pt12('z, o12); + always @* begin + assert (o01 === {64 {1'b0}}); + assert (o02 === {64 {1'b1}}); + assert (o03 === {64 {1'bx}}); + assert (o04 === {64 {1'bz}}); + assert (o05 === {61'b0, 3'b000}); + assert (o06 === {61'b0, 3'b111}); + assert (o07 === {61'b0, 3'bxxx}); + assert (o08 === {61'b0, 3'bzzz}); + assert (o09 === {64 {1'b0}}); + assert (o10 === {64 {1'b1}}); + assert (o11 === {64 {1'bx}}); + assert (o12 === {64 {1'bz}}); + end +endmodule diff --git a/tests/verilog/unbased_unsized.ys b/tests/verilog/unbased_unsized.ys new file mode 100644 index 000000000..e1bc99c64 --- /dev/null +++ b/tests/verilog/unbased_unsized.ys @@ -0,0 +1,7 @@ +read_verilog -sv unbased_unsized.sv +hierarchy +proc +flatten +opt -full +select -module top +sat -verify -seq 1 -tempinduct -prove-asserts -show-all -- 2.30.2