mirror of https://github.com/YosysHQ/yosys.git
Assign from rvalue via temporary register in nowrshmsk CASE
Avoid repeating complex rvalue expressions for each condition.
This commit is contained in:
parent
dbec704b49
commit
1a2b4759e8
|
@ -850,6 +850,25 @@ 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;
|
||||
|
||||
return ident;
|
||||
}
|
||||
|
||||
bool AstNode::bits_only_01() const
|
||||
{
|
||||
for (auto bit : bits)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -2932,8 +2932,18 @@ 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;
|
||||
|
||||
// A temporary register holds 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);
|
||||
AstNode *rvalue = mktemp_logic("$bitselwrite$rvalue$", current_ast_mod, true, rvalue_width - 1, 0, rvalue_sign);
|
||||
AstNode *caseNode = new AstNode(AST_CASE, shift_expr);
|
||||
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;
|
||||
|
@ -2951,8 +2961,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
|
||||
|
|
Loading…
Reference in New Issue