mirror of https://github.com/YosysHQ/yosys.git
Merge pull request #3813 from povik/ast-simplify-work-vol2
ast/simplify: Remove in_lvalue/in_param simplify() parameters
This commit is contained in:
commit
20024900d9
|
@ -229,6 +229,10 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
|||
id2ast = NULL;
|
||||
basic_prep = false;
|
||||
lookahead = false;
|
||||
in_lvalue_from_above = false;
|
||||
in_param_from_above = false;
|
||||
in_lvalue = false;
|
||||
in_param = false;
|
||||
|
||||
if (child1)
|
||||
children.push_back(child1);
|
||||
|
@ -238,6 +242,8 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
|
|||
children.push_back(child3);
|
||||
if (child4)
|
||||
children.push_back(child4);
|
||||
|
||||
fixup_hierarchy_flags();
|
||||
}
|
||||
|
||||
// create a (deep recursive) copy of a node
|
||||
|
@ -249,6 +255,10 @@ AstNode *AstNode::clone() const
|
|||
it = it->clone();
|
||||
for (auto &it : that->attributes)
|
||||
it.second = it.second->clone();
|
||||
|
||||
that->set_in_lvalue_flag(false);
|
||||
that->set_in_param_flag(false);
|
||||
that->fixup_hierarchy_flags(); // fixup to set flags on cloned children
|
||||
return that;
|
||||
}
|
||||
|
||||
|
@ -256,10 +266,13 @@ AstNode *AstNode::clone() const
|
|||
void AstNode::cloneInto(AstNode *other) const
|
||||
{
|
||||
AstNode *tmp = clone();
|
||||
tmp->in_lvalue_from_above = other->in_lvalue_from_above;
|
||||
tmp->in_param_from_above = other->in_param_from_above;
|
||||
other->delete_children();
|
||||
*other = *tmp;
|
||||
tmp->children.clear();
|
||||
tmp->attributes.clear();
|
||||
other->fixup_hierarchy_flags();
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
|
@ -351,6 +364,10 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
|
|||
if (is_enum) {
|
||||
fprintf(f, " type=enum");
|
||||
}
|
||||
if (in_lvalue)
|
||||
fprintf(f, " in_lvalue");
|
||||
if (in_param)
|
||||
fprintf(f, " in_param");
|
||||
fprintf(f, "\n");
|
||||
|
||||
for (auto &it : attributes) {
|
||||
|
@ -1061,7 +1078,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
// simplify this module or interface using the current design as context
|
||||
// for lookup up ports and wires within cells
|
||||
set_simplify_design_context(design);
|
||||
while (ast->simplify(!flag_noopt, false, 0, -1, false, false)) { }
|
||||
while (ast->simplify(!flag_noopt, 0, -1, false)) { }
|
||||
set_simplify_design_context(nullptr);
|
||||
|
||||
if (flag_dump_ast2) {
|
||||
|
@ -1091,7 +1108,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
ast->attributes.erase(ID::whitebox);
|
||||
}
|
||||
AstNode *n = ast->attributes.at(ID::lib_whitebox);
|
||||
ast->attributes[ID::whitebox] = n;
|
||||
ast->set_attribute(ID::whitebox, n);
|
||||
ast->attributes.erase(ID::lib_whitebox);
|
||||
}
|
||||
}
|
||||
|
@ -1150,7 +1167,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
|
|||
ast->children.swap(new_children);
|
||||
|
||||
if (ast->attributes.count(ID::blackbox) == 0) {
|
||||
ast->attributes[ID::blackbox] = AstNode::mkconst_int(1, false);
|
||||
ast->set_attribute(ID::blackbox, AstNode::mkconst_int(1, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1298,6 +1315,8 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
|||
flag_pwires = pwires;
|
||||
flag_autowire = autowire;
|
||||
|
||||
ast->fixup_hierarchy_flags(true);
|
||||
|
||||
log_assert(current_ast->type == AST_DESIGN);
|
||||
for (AstNode *child : current_ast->children)
|
||||
{
|
||||
|
@ -1361,7 +1380,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
|
|||
}
|
||||
else if (child->type == AST_PACKAGE) {
|
||||
// process enum/other declarations
|
||||
child->simplify(true, false, 1, -1, false, false);
|
||||
child->simplify(true, 1, -1, false);
|
||||
rename_in_package_stmts(child);
|
||||
design->verilog_packages.push_back(child->clone());
|
||||
current_scope.clear();
|
||||
|
@ -1748,7 +1767,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
|
|||
|
||||
AstNode *new_ast = ast->clone();
|
||||
if (!new_ast->attributes.count(ID::hdlname))
|
||||
new_ast->attributes[ID::hdlname] = AstNode::mkconst_str(stripped_name);
|
||||
new_ast->set_attribute(ID::hdlname, AstNode::mkconst_str(stripped_name));
|
||||
|
||||
para_counter = 0;
|
||||
for (auto child : new_ast->children) {
|
||||
|
@ -1795,6 +1814,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
|
|||
new_ast->children.push_back(defparam);
|
||||
}
|
||||
|
||||
new_ast->fixup_hierarchy_flags(true);
|
||||
(*new_ast_out) = new_ast;
|
||||
return modname;
|
||||
}
|
||||
|
|
|
@ -221,6 +221,13 @@ namespace AST
|
|||
std::string filename;
|
||||
AstSrcLocType location;
|
||||
|
||||
// are we embedded in an lvalue, param?
|
||||
// (see fixup_hierarchy_flags)
|
||||
bool in_lvalue;
|
||||
bool in_param;
|
||||
bool in_lvalue_from_above;
|
||||
bool in_param_from_above;
|
||||
|
||||
// creating and deleting nodes
|
||||
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr);
|
||||
AstNode *clone() const;
|
||||
|
@ -251,7 +258,7 @@ namespace AST
|
|||
|
||||
// simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc.
|
||||
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
|
||||
bool simplify(bool const_fold, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param);
|
||||
bool simplify(bool const_fold, int stage, int width_hint, bool sign_hint);
|
||||
void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
|
||||
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
|
||||
void expand_genblock(const std::string &prefix);
|
||||
|
@ -343,6 +350,24 @@ namespace AST
|
|||
// to evaluate widths of dynamic ranges)
|
||||
AstNode *clone_at_zero();
|
||||
|
||||
void set_attribute(RTLIL::IdString key, AstNode *node)
|
||||
{
|
||||
attributes[key] = node;
|
||||
node->set_in_param_flag(true);
|
||||
}
|
||||
|
||||
// helper to set in_lvalue/in_param flags from the hierarchy context (the actual flag
|
||||
// can be overridden based on the intrinsic properties of this node, i.e. based on its type)
|
||||
void set_in_lvalue_flag(bool flag, bool no_descend = false);
|
||||
void set_in_param_flag(bool flag, bool no_descend = false);
|
||||
|
||||
// fix up the hierarchy flags (in_lvalue/in_param) of this node and its children
|
||||
//
|
||||
// to keep the flags in sync, fixup_hierarchy_flags(true) needs to be called once after
|
||||
// parsing the AST to walk the full tree, then plain fixup_hierarchy_flags() performs
|
||||
// localized fixups after modifying children/attributes of a particular node
|
||||
void fixup_hierarchy_flags(bool force_descend = false);
|
||||
|
||||
// helper to print errors from simplify/genrtlil code
|
||||
[[noreturn]] void input_error(const char *format, ...) const YS_ATTRIBUTE(format(printf, 2, 3));
|
||||
};
|
||||
|
|
|
@ -176,10 +176,11 @@ struct AST_INTERNAL::LookaheadRewriter
|
|||
AstNode *wire = new AstNode(AST_WIRE);
|
||||
for (auto c : node->id2ast->children)
|
||||
wire->children.push_back(c->clone());
|
||||
wire->fixup_hierarchy_flags();
|
||||
wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
|
||||
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);
|
||||
lookaheadids[node->str] = make_pair(node->id2ast, wire);
|
||||
wire->genRTLIL();
|
||||
|
@ -926,7 +927,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
|
||||
} else {
|
||||
if (id_ast->children[0]->type != AST_CONSTANT)
|
||||
while (id_ast->simplify(true, false, 1, -1, false, true)) { }
|
||||
while (id_ast->simplify(true, 1, -1, false)) { }
|
||||
if (id_ast->children[0]->type == AST_CONSTANT)
|
||||
this_width = id_ast->children[0]->bits.size();
|
||||
else
|
||||
|
@ -970,8 +971,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
else if (!range->range_valid) {
|
||||
AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero();
|
||||
AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
|
||||
while (left_at_zero_ast->simplify(true, false, 1, -1, false, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, false, 1, -1, false, false)) { }
|
||||
while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
|
||||
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
|
||||
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
||||
this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
|
||||
|
@ -987,7 +988,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
break;
|
||||
|
||||
case AST_TO_BITS:
|
||||
while (children[0]->simplify(true, false, 1, -1, false, false) == true) { }
|
||||
while (children[0]->simplify(true, 1, -1, false) == true) { }
|
||||
if (children[0]->type != AST_CONSTANT)
|
||||
input_error("Left operand of tobits expression is not constant!\n");
|
||||
children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
|
||||
|
@ -1009,7 +1010,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
break;
|
||||
|
||||
case AST_CAST_SIZE:
|
||||
while (children.at(0)->simplify(true, false, 1, -1, false, false)) { }
|
||||
while (children.at(0)->simplify(true, 1, -1, false)) { }
|
||||
if (children.at(0)->type != AST_CONSTANT)
|
||||
input_error("Static cast with non constant expression!\n");
|
||||
children.at(1)->detectSignWidthWorker(width_hint, sign_hint);
|
||||
|
@ -1031,7 +1032,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
break;
|
||||
|
||||
case AST_REPLICATE:
|
||||
while (children[0]->simplify(true, false, 1, -1, false, true) == true) { }
|
||||
while (children[0]->simplify(true, 1, -1, false) == true) { }
|
||||
if (children[0]->type != AST_CONSTANT)
|
||||
input_error("Left operand of replicate expression is not constant!\n");
|
||||
children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
|
||||
|
@ -1143,7 +1144,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
case AST_PREFIX:
|
||||
// Prefix nodes always resolve to identifiers in generate loops, so we
|
||||
// can simply perform the resolution to determine the sign and width.
|
||||
simplify(true, false, 1, -1, false, false);
|
||||
simplify(true, 1, -1, false);
|
||||
log_assert(type == AST_IDENTIFIER);
|
||||
detectSignWidthWorker(width_hint, sign_hint, found_real);
|
||||
break;
|
||||
|
@ -1151,7 +1152,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
case AST_FCALL:
|
||||
if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
|
||||
if (GetSize(children) == 1) {
|
||||
while (children[0]->simplify(true, false, 1, -1, false, true) == true) { }
|
||||
while (children[0]->simplify(true, 1, -1, false) == true) { }
|
||||
if (children[0]->type != AST_CONSTANT)
|
||||
input_error("System function %s called with non-const argument!\n",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
|
@ -1198,8 +1199,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
log_assert(range->type == AST_RANGE && range->children.size() == 2);
|
||||
AstNode *left = range->children.at(0)->clone();
|
||||
AstNode *right = range->children.at(1)->clone();
|
||||
while (left->simplify(true, false, 1, -1, false, true)) { }
|
||||
while (right->simplify(true, false, 1, -1, false, true)) { }
|
||||
left->set_in_param_flag(true);
|
||||
right->set_in_param_flag(true);
|
||||
while (left->simplify(true, 1, -1, false)) { }
|
||||
while (right->simplify(true, 1, -1, false)) { }
|
||||
if (left->type != AST_CONSTANT || right->type != AST_CONSTANT)
|
||||
input_error("Function %s has non-constant width!",
|
||||
RTLIL::unescape_id(str).c_str());
|
||||
|
@ -1543,8 +1546,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
if (!children[0]->range_valid) {
|
||||
AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero();
|
||||
AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
|
||||
while (left_at_zero_ast->simplify(true, false, 1, -1, false, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, false, 1, -1, false, false)) { }
|
||||
while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
|
||||
while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
|
||||
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
|
||||
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
|
||||
int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
|
||||
|
@ -1552,7 +1555,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
children[0]->children[1]->clone() : children[0]->children[0]->clone());
|
||||
fake_ast->children[0]->delete_children();
|
||||
if (member_node)
|
||||
fake_ast->children[0]->attributes[ID::wiretype] = member_node->clone();
|
||||
fake_ast->children[0]->set_attribute(ID::wiretype, member_node->clone());
|
||||
|
||||
int fake_ast_width = 0;
|
||||
bool fake_ast_sign = true;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue