diff options
Diffstat (limited to 'frontends/ast')
-rw-r--r-- | frontends/ast/ast.cc | 88 | ||||
-rw-r--r-- | frontends/ast/ast.h | 4 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 51 |
3 files changed, 133 insertions, 10 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index d48996167..9f88b08c1 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -46,7 +46,7 @@ namespace AST { // instantiate global variables (private API) namespace AST_INTERNAL { bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit; - bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; + bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_autowire; AstNode *current_ast, *current_ast_mod; std::map<std::string, AstNode*> current_scope; const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL; @@ -942,6 +942,20 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast if (!defer) { + bool blackbox_module = flag_lib; + + if (!blackbox_module && !flag_noblackbox) { + blackbox_module = true; + for (auto child : ast->children) { + if (child->type == AST_WIRE && (child->is_input || child->is_output)) + continue; + if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) + continue; + blackbox_module = false; + break; + } + } + while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { } if (flag_dump_ast2) { @@ -956,7 +970,63 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast log("--- END OF AST DUMP ---\n"); } - if (flag_lib) { + if (flag_nowb && ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); + } + + if (ast->attributes.count("\\lib_whitebox")) { + if (!flag_lib || flag_nowb) { + delete ast->attributes.at("\\lib_whitebox"); + ast->attributes.erase("\\lib_whitebox"); + } else { + if (ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); + } + AstNode *n = ast->attributes.at("\\lib_whitebox"); + ast->attributes["\\whitebox"] = n; + ast->attributes.erase("\\lib_whitebox"); + } + } + + if (!blackbox_module && ast->attributes.count("\\blackbox")) { + AstNode *n = ast->attributes.at("\\blackbox"); + if (n->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Got blackbox attribute with non-constant value!\n"); + blackbox_module = n->asBool(); + } + + if (blackbox_module && ast->attributes.count("\\whitebox")) { + AstNode *n = ast->attributes.at("\\whitebox"); + if (n->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Got whitebox attribute with non-constant value!\n"); + blackbox_module = !n->asBool(); + } + + if (ast->attributes.count("\\noblackbox")) { + if (blackbox_module) { + AstNode *n = ast->attributes.at("\\noblackbox"); + if (n->type != AST_CONSTANT) + log_file_error(ast->filename, ast->linenum, "Got noblackbox attribute with non-constant value!\n"); + blackbox_module = !n->asBool(); + } + delete ast->attributes.at("\\noblackbox"); + ast->attributes.erase("\\noblackbox"); + } + + if (blackbox_module) + { + if (ast->attributes.count("\\whitebox")) { + delete ast->attributes.at("\\whitebox"); + ast->attributes.erase("\\whitebox"); + } + + if (ast->attributes.count("\\lib_whitebox")) { + delete ast->attributes.at("\\lib_whitebox"); + ast->attributes.erase("\\lib_whitebox"); + } + std::vector<AstNode*> new_children; for (auto child : ast->children) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) { @@ -969,8 +1039,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast delete child; } } + ast->children.swap(new_children); - ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); + + if (ast->attributes.count("\\blackbox") == 0) { + ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); + } } ignoreThisSignalsInInitial = RTLIL::SigSpec(); @@ -1009,7 +1083,9 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast current_module->nomeminit = flag_nomeminit; current_module->nomem2reg = flag_nomem2reg; current_module->mem2reg = flag_mem2reg; + current_module->noblackbox = flag_noblackbox; current_module->lib = flag_lib; + current_module->nowb = flag_nowb; current_module->noopt = flag_noopt; current_module->icells = flag_icells; current_module->autowire = flag_autowire; @@ -1026,7 +1102,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast // create AstModule instances for all modules in the AST tree and add them to 'design' void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, - bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) + bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) { current_ast = ast; flag_dump_ast1 = dump_ast1; @@ -1039,7 +1115,9 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump flag_nomeminit = nomeminit; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_noblackbox = noblackbox; flag_lib = lib; + flag_nowb = nowb; flag_noopt = noopt; flag_icells = icells; flag_autowire = autowire; @@ -1373,7 +1451,9 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString flag_nomeminit = nomeminit; flag_nomem2reg = nomem2reg; flag_mem2reg = mem2reg; + flag_noblackbox = noblackbox; flag_lib = lib; + flag_nowb = nowb; flag_noopt = noopt; flag_icells = icells; flag_autowire = autowire; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index ddd59d4be..281cbe086 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -283,13 +283,13 @@ namespace AST // process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit, - bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire); + bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire); // parametric modules are supported directly by the AST library // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions struct AstModule : RTLIL::Module { AstNode *ast; - bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; + bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, autowire; ~AstModule() YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 63b71b800..4d4b9dfe1 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1030,7 +1030,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n"); if (type == AST_REPEAT) - log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n"); + { + AstNode *count = children[0]; + AstNode *body = children[1]; + + // eval count expression + while (count->simplify(true, false, false, stage, 32, true, false)) { } + + if (count->type != AST_CONSTANT) + log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n"); + + // convert to a block with the body repeated n times + type = AST_BLOCK; + children.clear(); + for (int i = 0; i < count->bitsAsConst().as_int(); i++) + children.insert(children.begin(), body->clone()); + + delete count; + delete body; + did_something = true; + } // unroll for loops and generate-for blocks if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0) @@ -1066,7 +1085,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // eval 1st expression AstNode *varbuf = init_ast->children[1]->clone(); - while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } + { + int expr_width_hint = -1; + bool expr_sign_hint = true; + varbuf->detectSignWidth(expr_width_hint, expr_sign_hint); + while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } + } if (varbuf->type != AST_CONSTANT) log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n"); @@ -1088,7 +1112,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, { // eval 2nd expression AstNode *buf = while_ast->clone(); - while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } + { + int expr_width_hint = -1; + bool expr_sign_hint = true; + buf->detectSignWidth(expr_width_hint, expr_sign_hint); + while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { } + } if (buf->type != AST_CONSTANT) log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n"); @@ -1129,7 +1158,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, // eval 3rd expression buf = next_ast->children[1]->clone(); - while (buf->simplify(true, false, false, stage, 32, true, false)) { } + { + int expr_width_hint = -1; + bool expr_sign_hint = true; + buf->detectSignWidth(expr_width_hint, expr_sign_hint); + while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { } + } if (buf->type != AST_CONSTANT) log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n"); @@ -1138,6 +1172,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, varbuf->children[0] = buf; } +#if 0 + if (type == AST_FOR) { + AstNode *buf = next_ast->clone(); + delete buf->children[1]; + buf->children[1] = varbuf->children[0]->clone(); + current_block->children.insert(current_block->children.begin() + current_block_idx++, buf); + } +#endif + current_scope[varbuf->str] = backup_scope_varbuf; delete varbuf; delete_children(); |