From 412d9d73da78d1d89709aedb09eab4a34aed15cc Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Fri, 11 Aug 2023 23:14:15 +0200 Subject: [PATCH] Direct substitution of rvalue array slice/element expressions It is only necessary to introduce temporary identifiers for the AST_CASE/AST_COND assignments generated by (* nordshift *). --- frontends/ast/simplify.cc | 65 ++++++++++++++++++------------------- tests/techmap/shiftx2mux.ys | 1 - 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 8f53f9ffa59..bc0d1975b88 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2369,20 +2369,6 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin use_case_method = true; } - AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, node_int(result_width - 1), node_int(0))); - wire->str = stringf("$bitsel$%s$%s:%d$%d", str.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); - if (current_block) - wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); - wire->is_logic = true; - while (wire->simplify(true, false, 1, -1, false, false)) { } - current_ast_mod->children.push_back(wire); - - AstNode *lvalue = new AstNode(AST_IDENTIFIER); - lvalue->str = wire->str; - lvalue->was_checked = true; - - AstNode *assign; - if (use_case_method) { // AST_CASE with an AST_COND for each possible bit slice. @@ -2438,7 +2424,20 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin int max_offset = (1u << (max_bits - case_sign_hint)) - 1; int min_offset = case_sign_hint ? -(1u << (max_bits - 1)) : 0; - assign = new AstNode(AST_CASE, shift_expr); + // New identifier to replace the current rvalue; used as lvalue in AST_COND assignments. + AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, node_int(result_width - 1), node_int(0))); + wire->str = stringf("$bitsel$%s$%s:%d$%d", str.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); + if (current_block) + wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); + wire->is_logic = true; + while (wire->simplify(true, false, 1, -1, false, false)) { } + current_ast_mod->children.push_back(wire); + + AstNode *lvalue = new AstNode(AST_IDENTIFIER); + lvalue->str = wire->str; + lvalue->was_checked = true; + + AstNode *assign = new AstNode(AST_CASE, shift_expr); 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_offset + source_width) - 1; @@ -2454,6 +2453,20 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_EQ, lvalue->clone(), rvalue))); assign->children.push_back(cond); } + + if (current_block) { + size_t assign_idx = 0; + while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child) + assign_idx++; + log_assert(assign_idx < current_block->children.size()); + current_block->children.insert(current_block->children.begin()+assign_idx, assign); + wire->is_reg = true; + } else { + AstNode *proc = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK, assign)); + current_ast_mod->children.push_back(proc); + } + + newNode = lvalue; } else { // Shift to access the indexed bit slice. AstNode *rvalue = clone(); @@ -2471,27 +2484,11 @@ bool AstNode::simplify(bool const_fold, bool in_lvalue, int stage, int width_hin } // Shift rvalue to the right so that the bit slice starts at bit 0. - assign = new AstNode(AST_ASSIGN_EQ, - lvalue->clone(), - new AstNode(AST_SHIFTX, rvalue, shift_expr)); - } - - if (current_block) { - size_t assign_idx = 0; - while (assign_idx < current_block->children.size() && current_block->children[assign_idx] != current_block_child) - assign_idx++; - log_assert(assign_idx < current_block->children.size()); - current_block->children.insert(current_block->children.begin()+assign_idx, assign); - wire->is_reg = true; - } else { - if (!use_case_method) { - assign = new AstNode(AST_BLOCK, assign); - } - AstNode *proc = new AstNode(AST_ALWAYS, assign); - current_ast_mod->children.push_back(proc); + newNode = new AstNode(AST_CAST_SIZE, + mkconst_int(result_width, true), + new AstNode(AST_SHIFTX, rvalue, shift_expr)); } - newNode = lvalue; goto apply_newNode; } diff --git a/tests/techmap/shiftx2mux.ys b/tests/techmap/shiftx2mux.ys index 4a59322e357..68068129730 100644 --- a/tests/techmap/shiftx2mux.ys +++ b/tests/techmap/shiftx2mux.ys @@ -104,7 +104,6 @@ wire [7:0] AA = {1'bx, A}; assign Y = AA[B*2 +: 2]; endmodule EOT -proc opt wreduce equiv_opt -assert techmap