From cd9e8741a71502c303c6f25d02bb2259a7dd7ff3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 13 Feb 2014 13:59:13 +0100 Subject: [PATCH] Implemented read_verilog -defer --- frontends/ast/ast.cc | 139 +++++++++++++++----------- frontends/ast/ast.h | 2 +- frontends/verilog/verilog_frontend.cc | 12 ++- passes/hierarchy/hierarchy.cc | 26 +++-- 4 files changed, 111 insertions(+), 68 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 96608ae37..ab2972b2c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -747,14 +747,18 @@ bool AstNode::asBool() } // create a new AstModule from an AST_MODULE AST node -static AstModule* process_module(AstNode *ast) +static AstModule* process_module(AstNode *ast, bool defer) { assert(ast->type == AST_MODULE); - log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str()); + + if (defer) + log("Storing AST representation for module `%s'.\n", ast->str.c_str()); + else + log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str()); current_module = new AstModule; current_module->ast = NULL; - current_module->name = ast->str; + current_module->name = defer ? "$abstract" + ast->str : ast->str; current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); current_ast_mod = ast; @@ -766,61 +770,64 @@ static AstModule* process_module(AstNode *ast) log("--- END OF AST DUMP ---\n"); } - while (ast->simplify(!flag_noopt, false, false, 0, -1, false)) { } + if (!defer) + { + while (ast->simplify(!flag_noopt, false, false, 0, -1, false)) { } - if (flag_dump_ast2) { - log("Dumping verilog AST after simplification:\n"); - ast->dumpAst(NULL, " "); - log("--- END OF AST DUMP ---\n"); - } - - if (flag_dump_vlog) { - log("Dumping verilog AST (as requested by dump_vlog option):\n"); - ast->dumpVlog(NULL, " "); - log("--- END OF AST DUMP ---\n"); - } - - if (flag_lib) { - std::vector new_children; - for (auto child : ast->children) { - if (child->type == AST_WIRE && (child->is_input || child->is_output)) - new_children.push_back(child); - else - delete child; + if (flag_dump_ast2) { + log("Dumping verilog AST after simplification:\n"); + ast->dumpAst(NULL, " "); + log("--- END OF AST DUMP ---\n"); } - ast->children.swap(new_children); - ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); - } - ignoreThisSignalsInInitial = RTLIL::SigSpec(); + if (flag_dump_vlog) { + log("Dumping verilog AST (as requested by dump_vlog option):\n"); + ast->dumpVlog(NULL, " "); + log("--- END OF AST DUMP ---\n"); + } - for (auto &attr : ast->attributes) { - if (attr.second->type != AST_CONSTANT) - log_error("Attribute `%s' with non-constant value at %s:%d!\n", - attr.first.c_str(), ast->filename.c_str(), ast->linenum); - current_module->attributes[attr.first] = attr.second->asAttrConst(); - } - for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; - if (node->type == AST_WIRE || node->type == AST_MEMORY) - node->genRTLIL(); - } - for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; - if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) - node->genRTLIL(); - } + if (flag_lib) { + std::vector new_children; + for (auto child : ast->children) { + if (child->type == AST_WIRE && (child->is_input || child->is_output)) + new_children.push_back(child); + else + delete child; + } + ast->children.swap(new_children); + ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); + } - ignoreThisSignalsInInitial.sort_and_unify(); + ignoreThisSignalsInInitial = RTLIL::SigSpec(); - for (size_t i = 0; i < ast->children.size(); i++) { - AstNode *node = ast->children[i]; - if (node->type == AST_INITIAL) - node->genRTLIL(); + for (auto &attr : ast->attributes) { + if (attr.second->type != AST_CONSTANT) + log_error("Attribute `%s' with non-constant value at %s:%d!\n", + attr.first.c_str(), ast->filename.c_str(), ast->linenum); + current_module->attributes[attr.first] = attr.second->asAttrConst(); + } + for (size_t i = 0; i < ast->children.size(); i++) { + AstNode *node = ast->children[i]; + if (node->type == AST_WIRE || node->type == AST_MEMORY) + node->genRTLIL(); + } + for (size_t i = 0; i < ast->children.size(); i++) { + AstNode *node = ast->children[i]; + if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) + node->genRTLIL(); + } + + ignoreThisSignalsInInitial.sort_and_unify(); + + for (size_t i = 0; i < ast->children.size(); i++) { + AstNode *node = ast->children[i]; + if (node->type == AST_INITIAL) + node->genRTLIL(); + } + + ignoreThisSignalsInInitial = RTLIL::SigSpec(); } - ignoreThisSignalsInInitial = RTLIL::SigSpec(); - current_module->ast = ast_before_simplify; current_module->nolatches = flag_nolatches; current_module->nomem2reg = flag_nomem2reg; @@ -832,7 +839,7 @@ static AstModule* process_module(AstNode *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 dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef) +void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool nolatches, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer) { current_ast = ast; flag_dump_ast1 = dump_ast1; @@ -847,7 +854,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump assert(current_ast->type == AST_DESIGN); for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) { - if (design->modules.count((*it)->str) != 0) { + if (design->modules.count((*it)->str) != 0 && design->modules.count("$abstract" + (*it)->str) != 0) { if (!ignore_redef) log_error("Re-definition of module `%s' at %s:%d!\n", (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); @@ -855,7 +862,10 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); continue; } - design->modules[(*it)->str] = process_module(*it); + if (defer) + design->modules["$abstract" + (*it)->str] = process_module(*it, true); + else + design->modules[(*it)->str] = process_module(*it, false); } } @@ -869,7 +879,12 @@ AstModule::~AstModule() // create a new parametric module (when needed) and return the name of the generated module RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map parameters) { - log_header("Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", name.c_str()); + std::string stripped_name = name; + + if (stripped_name.substr(0, 9) == "$abstract") + stripped_name = stripped_name.substr(9); + + log_header("Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str()); current_ast = NULL; flag_dump_ast1 = false; @@ -885,12 +900,13 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map hash_data; - hash_data.insert(hash_data.end(), name.begin(), name.end()); + hash_data.insert(hash_data.end(), stripped_name.begin(), stripped_name.end()); hash_data.push_back(0); AstNode *new_ast = ast->clone(); int para_counter = 0; + int orig_parameters_n = parameters.size(); for (auto it = new_ast->children.begin(); it != new_ast->children.end(); it++) { AstNode *child = *it; if (child->type != AST_PARAMETER) @@ -917,10 +933,15 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map 0) - log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters.begin()->first.c_str(), name.c_str()); + log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters.begin()->first.c_str(), stripped_name.c_str()); std::string modname; + if (orig_parameters_n == 0) + { + modname = stripped_name; + } + else if (para_info.size() > 60) { unsigned char hash[20]; @@ -933,16 +954,16 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::mapmodules.count(modname) == 0) { new_ast->str = modname; - design->modules[modname] = process_module(new_ast); + design->modules[modname] = process_module(new_ast, false); design->modules[modname]->check(); } else { log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 01702c3cf..8335db096 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -232,7 +232,7 @@ 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 = false, bool dump_ast2 = false, bool dump_vlog = false, bool nolatches = false, bool nomem2reg = false, bool mem2reg = false, bool lib = false, bool noopt = false, bool icells = false, bool ignore_redef = false); + void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1 = false, bool dump_ast2 = false, bool dump_vlog = false, bool nolatches = false, bool nomem2reg = false, bool mem2reg = false, bool lib = false, bool noopt = false, bool icells = false, bool ignore_redef = false, bool defer = true); // parametric modules are supported directly by the AST library // therfore we need our own derivate of RTLIL::Module with overloaded virtual functions diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index c70d6f305..d46dfa6e2 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -106,6 +106,11 @@ struct VerilogFrontend : public Frontend { log(" ignore re-definitions of modules. (the default behavior is to\n"); log(" create an error message.)\n"); log("\n"); + log(" -defer\n"); + log(" only read the abstract syntax tree and defer actual compilation\n"); + log(" to a later 'hierarchy' command. Useful in cases where the default\n"); + log(" parameters of modules yield invalid or not synthesizable code.\n"); + log("\n"); log(" -setattr \n"); log(" set the specified attribute (to the value 1) on all loaded modules\n"); log("\n"); @@ -135,6 +140,7 @@ struct VerilogFrontend : public Frontend { bool flag_noopt = false; bool flag_icells = false; bool flag_ignore_redef = false; + bool flag_defer = false; std::map defines_map; std::list include_dirs; std::list attributes; @@ -199,6 +205,10 @@ struct VerilogFrontend : public Frontend { flag_ignore_redef = true; continue; } + if (arg == "-defer") { + flag_defer = true; + continue; + } if (arg == "-setattr" && argidx+1 < args.size()) { attributes.push_back(RTLIL::escape_id(args[++argidx])); continue; @@ -264,7 +274,7 @@ struct VerilogFrontend : public Frontend { child->attributes[attr] = AST::AstNode::mkconst_int(1, false); } - AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef); + AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer); if (!flag_nopp) fclose(fp); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 50d0e6e47..526d17294 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -145,6 +145,14 @@ static bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool fla if (design->modules.count(cell->type) == 0) { + if (design->modules.count("$abstract" + cell->type)) + { + cell->type = design->modules.at("$abstract" + cell->type)->derive(design, cell->parameters); + cell->parameters.clear(); + did_something = true; + continue; + } + if (cell->type[0] == '$') continue; @@ -210,7 +218,7 @@ static void hierarchy_worker(RTLIL::Design *design, std::set &us } } -static void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib) +static void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib, bool first_pass) { std::set used; hierarchy_worker(design, used, top, 0); @@ -221,6 +229,8 @@ static void hierarchy(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib) del_modules.push_back(it.second); for (auto mod : del_modules) { + if (first_pass && mod->name.substr(0, 9) == "$abstract") + continue; if (!purge_lib && mod->get_bool_attribute("\\blackbox")) continue; log("Removing unused module `%s'.\n", mod->name.c_str()); @@ -362,10 +372,12 @@ struct HierarchyPass : public Pass { if (args[argidx] == "-top") { if (++argidx >= args.size()) log_cmd_error("Option -top requires an additional argument!\n"); - if (args[argidx][0] != '$' && args[argidx][0] != '\\') - top_mod = design->modules.count("\\" + args[argidx]) > 0 ? design->modules["\\" + args[argidx]] : NULL; - else - top_mod = design->modules.count(args[argidx]) > 0 ? design->modules[args[argidx]] : NULL; + top_mod = design->modules.count(RTLIL::escape_id(args[argidx])) ? design->modules.at(RTLIL::escape_id(args[argidx])) : NULL; + if (top_mod == NULL && design->modules.count("$abstract" + RTLIL::escape_id(args[argidx]))) { + std::map empty_parameters; + design->modules.at("$abstract" + RTLIL::escape_id(args[argidx]))->derive(design, empty_parameters); + top_mod = design->modules.count(RTLIL::escape_id(args[argidx])) ? design->modules.at(RTLIL::escape_id(args[argidx])) : NULL; + } if (top_mod == NULL) log_cmd_error("Module `%s' not found!\n", args[argidx].c_str()); continue; @@ -387,7 +399,7 @@ struct HierarchyPass : public Pass { top_mod = mod_it.second; if (top_mod != NULL) - hierarchy(design, top_mod, purge_lib); + hierarchy(design, top_mod, purge_lib, true); bool did_something = true; bool did_something_once = false; @@ -409,7 +421,7 @@ struct HierarchyPass : public Pass { if (top_mod != NULL && did_something_once) { log_header("Re-running hierarchy analysis..\n"); - hierarchy(design, top_mod, purge_lib); + hierarchy(design, top_mod, purge_lib, false); } if (top_mod != NULL) {