From a23b70aef1a5eff392c9dde4b36509e2ccfa1868 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Mon, 7 Aug 2023 21:11:56 +0200 Subject: [PATCH] Correct nowrshmsk corner cases This makes tests/verilog/dynamic_range_lhs.v pass, after ensuring that nowrshmsk is actually tested. --- frontends/ast/simplify.cc | 16 +++++++++++++--- tests/verilog/dynamic_range_lhs.v | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9fba06a0b6d..53ffcc2810c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2893,12 +2893,22 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin } } + // Limit case conditions to possible index range. + int case_width_hint = -1; + bool case_sign_hint = true; + shift_expr->detectSignWidth(case_width_hint, case_sign_hint); + int max_bits = min(case_width_hint, 31 + case_sign_hint); + int max_offset = (1u << (max_bits - case_sign_hint)) - 1; + int min_offset = case_sign_hint ? -(1u << (max_bits - 1)) : 0; + did_something = true; newNode = new AstNode(AST_CASE, shift_expr); - for (int i = 0; i < source_width; i += stride) { + for (int i = (1 - result_width)/stride*stride; i < source_width; i += stride) { int start_bit = source_offset + i; - int end_bit = std::min(start_bit+result_width,source_width) - 1; - AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit/div_stride, true)); + int end_bit = std::min(start_bit + result_width, source_offset + source_width) - 1; + if (start_bit/div_stride < min_offset || start_bit/div_stride > max_offset) + continue; + AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit/div_stride, case_sign_hint, case_width_hint)); AstNode *lvalue = children[0]->clone(); lvalue->delete_children(); if (member_node) diff --git a/tests/verilog/dynamic_range_lhs.v b/tests/verilog/dynamic_range_lhs.v index ae291374db9..56fe3ef3b32 100644 --- a/tests/verilog/dynamic_range_lhs.v +++ b/tests/verilog/dynamic_range_lhs.v @@ -1,6 +1,6 @@ module gate( - output reg [`LEFT:`RIGHT] out_u, out_s, (* nowrshmsk = `ALT *) + output reg [`LEFT:`RIGHT] out_u, out_s, input wire data, input wire [1:0] sel1, sel2 );