Skip to content

Commit

Permalink
Assign from rvalue via temporary register in nowrshmsk CASE
Browse files Browse the repository at this point in the history
Avoid repeating complex rvalue expressions for each condition.
  • Loading branch information
daglem committed Dec 9, 2023
1 parent 9aa6604 commit 09026cc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
20 changes: 20 additions & 0 deletions frontends/ast/ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,26 @@ AstNode *AstNode::mkconst_str(const std::string &str)
return node;
}

// create a temporary register
AstNode *AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed)
{
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true)));
wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
if (nosync)
wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
wire->is_signed = is_signed;
wire->is_logic = true;
mod->children.push_back(wire);
while (wire->simplify(true, 1, -1, false)) { }

AstNode *ident = new AstNode(AST_IDENTIFIER);
ident->str = wire->str;
ident->id2ast = wire;
ident->was_checked = true;

return ident;
}

bool AstNode::bits_only_01() const
{
for (auto bit : bits)
Expand Down
3 changes: 3 additions & 0 deletions frontends/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ namespace AST
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
static AstNode *mkconst_str(const std::string &str);

// helper function to create an AST node for a temporary register
AstNode *mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed);

// helper function for creating sign-extended const objects
RTLIL::Const bitsAsConst(int width, bool is_signed);
RTLIL::Const bitsAsConst(int width = -1);
Expand Down
22 changes: 19 additions & 3 deletions frontends/ast/simplify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2930,8 +2930,24 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
long long max_offset = (1ll << (max_width - case_sign_hint)) - 1;
long long min_offset = case_sign_hint ? -(1ll << (max_width - 1)) : 0;

AstNode *caseNode = new AstNode(AST_CASE, shift_expr);
AstNode *rvalue;
if (children[1]->type == AST_CONSTANT || (children[1]->type == AST_IDENTIFIER && children[1]->id2ast->type == AST_WIRE)) {
rvalue = children[1];
newNode = caseNode;
} else {
// Temporary register holding the result of the (possibly complex) rvalue expression,
// avoiding repetition in each AST_COND below.
int rvalue_width;
bool rvalue_sign;
children[1]->detectSignWidth(rvalue_width, rvalue_sign);
rvalue = mktemp_logic("$bitselwrite$rvalue$", current_ast_mod, true, rvalue_width - 1, 0, rvalue_sign);
newNode = new AstNode(AST_BLOCK,
new AstNode(AST_ASSIGN_EQ, rvalue, children[1]->clone()),
caseNode);
}

did_something = true;
newNode = new AstNode(AST_CASE, shift_expr);
for (int i = 1 - result_width; i < wire_width; i++) {
// Out of range indexes are handled in genrtlil.cc
int start_bit = wire_offset + i;
Expand All @@ -2949,8 +2965,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
lvalue->set_attribute(ID::wiretype, member_node->clone());
lvalue->children.push_back(new AstNode(AST_RANGE,
mkconst_int(end_bit, true), mkconst_int(start_bit, true)));
cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone())));
newNode->children.push_back(cond);
cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, rvalue->clone())));
caseNode->children.push_back(cond);
}
} else {
// mask and shift operations
Expand Down

0 comments on commit 09026cc

Please sign in to comment.