From edf8d4e82539b3713a8352e6307cddc0152f1fb1 Mon Sep 17 00:00:00 2001 From: Dag Lem Date: Mon, 13 Nov 2023 14:08:50 +0100 Subject: [PATCH] Adapt nordshift to changes in simplify() FIXME: tests/simple/partsel.v doesn't pass. It is currently not possible to use AST_SHIFTX to generate the exact RTLIL $shiftx previously generated in genrtlil.c. genrtlil.c uses an intermediate "fake_ast" to trick binop2rtlil into generating RTLIL with different width for the result (Y) and sign for the shift value (B). --- frontends/ast/simplify.cc | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 675882713d4..b08cd13b739 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2333,28 +2333,22 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin member_node->range_left - member_node->range_right + 1 : id2ast->range_left - id2ast->range_right + 1; int source_offset = id2ast->range_right; - int result_width = 1; - AstNode *shift_expr = NULL; AstNode *range = children[0]; + int result_width; + if (!try_determine_range_width(range, result_width)) + input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); + AstNode *shift_expr = result_width == 1 ? range->children[0]->clone() : range->children[1]->clone(); - if (range->children.size() == 1) { - shift_expr = range->children[0]->clone(); - } else { - shift_expr = range->children[1]->clone(); - if (!try_determine_range_width(range, result_width)) - input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); - } - - int shift_expr_width_hint = -1; - bool shift_expr_sign_hint = true; + int shift_expr_width_hint; + bool shift_expr_sign_hint; shift_expr->detectSignWidth(shift_expr_width_hint, shift_expr_sign_hint); bool use_case_method = false; if (id2ast->attributes.count(ID::nordshift)) { AstNode *node = id2ast->attributes.at(ID::nordshift); - while (node->simplify(true, false, stage, -1, false, false)) { } + while (node->simplify(true, stage, -1, false)) { } if (node->type != AST_CONSTANT) input_error("Non-constant value for `nordshift' attribute on `%s'!\n", id2ast->str.c_str()); if (node->asAttrConst().as_bool()) @@ -2367,7 +2361,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin int stride = 1; int div_stride = 1; - // Extract (index)*(width) from non_opt_range pattern (@selfsz@((index)*(width)))+(0)). + // 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 ? @@ -2417,9 +2411,9 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin 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->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); wire->is_logic = true; - while (wire->simplify(true, false, 1, -1, false, false)) { } + while (wire->simplify(true, 1, -1, false)) { } current_ast_mod->children.push_back(wire); AstNode *lvalue = new AstNode(AST_IDENTIFIER); @@ -2436,7 +2430,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin AstNode *rvalue = clone(); rvalue->delete_children(); if (member_node) - rvalue->attributes[ID::wiretype] = member_node->clone(); + rvalue->set_attribute(ID::wiretype, member_node->clone()); rvalue->children.push_back(new AstNode(AST_RANGE, node_int(end_bit), node_int(start_bit))); cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_EQ, lvalue->clone(), rvalue))); @@ -2461,7 +2455,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin AstNode *rvalue = clone(); rvalue->delete_children(); if (member_node) - rvalue->attributes[ID::wiretype] = member_node->clone(); + rvalue->set_attribute(ID::wiretype, member_node->clone()); if (!shift_expr_sign_hint && (source_offset || id2ast->range_swapped)) { // convert to signed while preserving the sign and value @@ -2470,6 +2464,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin node_int(shift_expr_width_hint + 1), shift_expr)); } + if (source_offset) { // offset the shift amount by the lower bound of the dimension shift_expr = new AstNode(AST_SUB, shift_expr, node_int(source_offset));