diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 64191cd7ebf..98dc5015af9 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2875,12 +2875,23 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin { // big case block + // Optimization for the common case of a two-dimensional packed array - + // remove multiplication of index by stride. + int div_stride = 1; + if (!source_offset && shift_expr->type == AST_MUL && shift_expr->children[1]->type == AST_CONSTANT && (int)shift_expr->children[1]->integer == stride) + { + AstNode *tmp = shift_expr->children[0]->clone(); + delete shift_expr; + shift_expr = tmp; + div_stride = stride; + } + did_something = true; newNode = new AstNode(AST_CASE, shift_expr); for (int i = 0; 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, true)); + AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit/div_stride, true)); AstNode *lvalue = children[0]->clone(); lvalue->delete_children(); if (member_node) @@ -2893,7 +2904,7 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin } else { - // mask and shift operations, disabled for now + // mask and shift operations AstNode *wire_mask = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); wire_mask->str = stringf("$bitselwrite$mask$%s:%d$%d", RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); diff --git a/tests/svtypes/struct_dynamic_range.ys b/tests/svtypes/struct_dynamic_range.ys index 9606e73840c..3891c2b3a8b 100644 --- a/tests/svtypes/struct_dynamic_range.ys +++ b/tests/svtypes/struct_dynamic_range.ys @@ -1,5 +1,5 @@ read_verilog -sv struct_dynamic_range.sv -select -assert-count 4 t:$mul +select -assert-count 3 t:$mul select -assert-count 2 t:$shift select -assert-count 2 t:$shiftx prep -top top