Skip to content

Commit

Permalink
Adapt nordshift to changes in simplify()
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
daglem committed Nov 13, 2023
1 parent 09d4821 commit edf8d4e
Showing 1 changed file with 13 additions and 18 deletions.
31 changes: 13 additions & 18 deletions frontends/ast/simplify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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 ?
Expand Down Expand Up @@ -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);
Expand All @@ -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)));
Expand All @@ -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
Expand All @@ -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));
Expand Down

0 comments on commit edf8d4e

Please sign in to comment.