diff options
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r-- | frontends/ast/simplify.cc | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 0a32e9506..ae2f0caae 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -346,7 +346,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, bool did_something_here = true; if ((type == AST_GENFOR || type == AST_FOR) && i >= 3) break; - if (type == AST_GENIF && i >= 1) + if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1) break; if (type == AST_GENBLOCK) break; @@ -726,7 +726,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // dumpAst(f, "verilog-ast> "); log_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum); } - if (buf->integer != 0) { + if (buf->asBool() != 0) { delete buf; buf = children[1]->clone(); } else { @@ -757,6 +757,82 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, did_something = true; } + // simplify generate-case blocks + if (type == AST_GENCASE && children.size() != 0) + { + AstNode *buf = children[0]->clone(); + while (buf->simplify(true, false, false, stage, width_hint, sign_hint)) { } + if (buf->type != AST_CONSTANT) { + // for (auto f : log_files) + // dumpAst(f, "verilog-ast> "); + log_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum); + } + + bool ref_signed = buf->is_signed; + RTLIL::Const ref_value = buf->bitsAsConst(); + delete buf; + + AstNode *selected_case = NULL; + for (size_t i = 1; i < children.size(); i++) + { + log_assert(children.at(i)->type == AST_COND); + + AstNode *this_genblock = NULL; + for (auto child : children.at(i)->children) { + log_assert(this_genblock == NULL); + if (child->type == AST_GENBLOCK) + this_genblock = child; + } + + for (auto child : children.at(i)->children) + { + if (child->type == AST_DEFAULT) { + if (selected_case == NULL) + selected_case = this_genblock; + continue; + } + if (child->type == AST_GENBLOCK) + continue; + + buf = child->clone(); + while (buf->simplify(true, false, false, stage, width_hint, sign_hint)) { } + if (buf->type != AST_CONSTANT) { + // for (auto f : log_files) + // dumpAst(f, "verilog-ast> "); + log_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum); + } + + if (RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool()) { + selected_case = this_genblock; + i = children.size(); + break; + } + } + } + + if (selected_case != NULL) + { + log_assert(selected_case->type == AST_GENBLOCK); + buf = selected_case->clone(); + + if (!buf->str.empty()) { + std::map<std::string, std::string> name_map; + buf->expand_genblock(std::string(), buf->str + ".", name_map); + } + + for (size_t i = 0; i < buf->children.size(); i++) { + buf->children[i]->simplify(false, false, false, stage, -1, false); + current_ast_mod->children.push_back(buf->children[i]); + } + + buf->children.clear(); + delete buf; + } + + delete_children(); + did_something = true; + } + // replace primitives with assignmens if (type == AST_PRIMITIVE) { |