From a2e69560aba874f2b93094841e79230412f93c3f Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Tue, 8 Aug 2023 12:11:54 +0200 Subject: [PATCH] Optimization of nowrshmsk The stride implification of the generated AST_CASE is generalized to handle variable slices on the form dst[i*stride +: width] = src To avoid optimization issues, the simplification of the non_opt_range AST is reverted, and the removal of multiplication of index by stride is temporarily disabled. --- frontends/ast/simplify.cc | 27 +++++++++++++++++++-------- frontends/verilog/verilog_parser.y | 12 ++++++------ tests/svtypes/struct_dynamic_range.ys | 2 +- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 53ffcc2810c..cdfaaa6c9aa 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2863,18 +2863,29 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin int stride = 1; int div_stride = 1; - // Optimization: Remove multiplication of index by stride for two-dimensional packed arrays and - // variable slices on the form dst[i*w +: w] = src. - if (!source_offset && shift_expr->type == AST_MUL && - ((shift_expr->children[0]->type == AST_CONSTANT && (int)shift_expr->children[0]->integer == result_width) || - (shift_expr->children[1]->type == AST_CONSTANT && (int)shift_expr->children[1]->integer == result_width))) + // Extract (index)*(width) from non_opt_range pattern (@selfsz@((index)*(width)))+(0)). + AstNode *lsb_expr = + shift_expr->type == AST_ADD && shift_expr->children[0]->type == AST_SELFSZ && + shift_expr->children[1]->type == AST_CONSTANT && shift_expr->children[1]->integer == 0 ? + shift_expr->children[0]->children[0] : + shift_expr; + + // Optimization: Extract stride from indexing of two-dimensional packed arrays and + // variable slices on the form dst[i*stride +: width] = src. + if (!source_offset && lsb_expr->type == AST_MUL && + (lsb_expr->children[0]->type == AST_CONSTANT || lsb_expr->children[1]->type == AST_CONSTANT)) { - int var_i = shift_expr->children[0]->type == AST_CONSTANT; - AstNode *tmp = shift_expr->children[var_i]->clone(); - stride = result_width; + int const_i = lsb_expr->children[1]->type == AST_CONSTANT; + stride = (int)lsb_expr->children[const_i]->integer; + + // Remove multiplication of index by stride. + // FIXME: Counterintuitively, this can yield higher resource usage. Disable for now. +#if 0 div_stride = stride; + AstNode *tmp = lsb_expr->children[1 - const_i]->clone(); delete shift_expr; shift_expr = tmp; +#endif } else if (member_node) // Member in packed struct/union { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index ee89aecace9..98bdbf9e5c5 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -884,15 +884,15 @@ non_opt_range: } | '[' expr TOK_POS_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_SELFSZ, $2->clone()); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr, $4), AstNode::mkconst_int(1, true))); - $$->children.push_back($2); + AstNode *expr = new AstNode(AST_SELFSZ, $2); + $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), $4), AstNode::mkconst_int(1, true))); + $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); } | '[' expr TOK_NEG_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_SELFSZ, $2->clone()); - $$->children.push_back($2); - $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr, AstNode::mkconst_int(1, true)), $4)); + AstNode *expr = new AstNode(AST_SELFSZ, $2); + $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); + $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), AstNode::mkconst_int(1, true)), $4)); } | '[' expr ']' { $$ = new AstNode(AST_RANGE); diff --git a/tests/svtypes/struct_dynamic_range.ys b/tests/svtypes/struct_dynamic_range.ys index 3891c2b3a8b..9606e73840c 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 3 t:$mul +select -assert-count 4 t:$mul select -assert-count 2 t:$shift select -assert-count 2 t:$shiftx prep -top top