Skip to content

Commit

Permalink
Direct substitution of rvalue array slice/element expressions
Browse files Browse the repository at this point in the history
It is only necessary to introduce temporary identifiers for the
AST_CASE/AST_COND assignments generated by (* nordshift *).
  • Loading branch information
daglem committed Aug 11, 2023
1 parent 52b8b88 commit 412d9d7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 35 deletions.
65 changes: 31 additions & 34 deletions frontends/ast/simplify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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;
}

Expand Down
1 change: 0 additions & 1 deletion tests/techmap/shiftx2mux.ys
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 412d9d7

Please sign in to comment.