/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Claire Xenia Wolf * Copyright (C) 2018 Ruben Undheim * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include "kernel/yosys.h" #include "passes/hierarchy/util/interfaces.h" #include "passes/hierarchy/util/misc.h" #include "passes/hierarchy/util/clean.h" #include "passes/hierarchy/util/top.h" #include "passes/hierarchy/util/positionals.h" #include "passes/hierarchy/util/verilog.h" #include "passes/hierarchy/util/generate.h" #include #include #include #ifndef _WIN32 # include #endif USING_YOSYS_NAMESPACE using namespace Hierarchy; PRIVATE_NAMESPACE_BEGIN struct HierarchyPass : public Pass { HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" hierarchy [-check] [-top ]\n"); log(" hierarchy -generate \n"); log("\n"); log("In parametric designs, a module might exists in several variations with\n"); log("different parameter values. This pass looks at all modules in the current\n"); log("design and re-runs the language frontends for the parametric modules as\n"); log("needed. It also resolves assignments to wired logic data types (wand/wor),\n"); log("resolves positional module parameters, unrolls array instances, and more.\n"); log("\n"); log(" -check\n"); log(" also check the design hierarchy. this generates an error when\n"); log(" an unknown module is used as cell type.\n"); log("\n"); log(" -simcheck\n"); log(" like -check, but also throw an error if blackbox modules are\n"); log(" instantiated, and throw an error if the design has no top module.\n"); log("\n"); log(" -smtcheck\n"); log(" like -simcheck, but allow smtlib2_module modules.\n"); log("\n"); log(" -purge_lib\n"); log(" by default the hierarchy command will not remove library (blackbox)\n"); log(" modules. use this option to also remove unused blackbox modules.\n"); log("\n"); log(" -libdir \n"); log(" search for files named .v in the specified directory\n"); log(" for unknown modules and automatically run read_verilog for each\n"); log(" unknown module.\n"); log("\n"); log(" -keep_positionals\n"); log(" per default this pass also converts positional arguments in cells\n"); log(" to arguments using port names. This option disables this behavior.\n"); log("\n"); log(" -keep_portwidths\n"); log(" per default this pass adjusts the port width on cells that are\n"); log(" module instances when the width does not match the module port. This\n"); log(" option disables this behavior.\n"); log("\n"); log(" -nodefaults\n"); log(" do not resolve input port default values\n"); log("\n"); log(" -nokeep_prints\n"); log(" per default this pass sets the \"keep\" attribute on all modules\n"); log(" that directly or indirectly display text on the terminal.\n"); log(" This option disables this behavior.\n"); log("\n"); log(" -nokeep_asserts\n"); log(" per default this pass sets the \"keep\" attribute on all modules\n"); log(" that directly or indirectly contain one or more formal properties.\n"); log(" This option disables this behavior.\n"); log("\n"); log(" -top \n"); log(" use the specified top module to build the design hierarchy. Modules\n"); log(" outside this tree (unused modules) are removed.\n"); log("\n"); log(" when the -top option is used, the 'top' attribute will be set on the\n"); log(" specified top module. otherwise a module with the 'top' attribute set\n"); log(" will implicitly be used as top module, if such a module exists.\n"); log("\n"); log(" -auto-top\n"); log(" automatically determine the top of the design hierarchy and mark it.\n"); log("\n"); log(" -chparam name value \n"); log(" elaborate the top module using this parameter value. Modules on which\n"); log(" this parameter does not exist may cause a warning message to be output.\n"); log(" This option can be specified multiple times to override multiple\n"); log(" parameters. String values must be passed in double quotes (\").\n"); log("\n"); log("In -generate mode this pass generates blackbox modules for the given cell\n"); log("types (wildcards supported). For this the design is searched for cells that\n"); log("match the given types and then the given port declarations are used to\n"); log("determine the direction of the ports. The syntax for a port declaration is:\n"); log("\n"); log(" {i|o|io}[@]:\n"); log("\n"); log("Input ports are specified with the 'i' prefix, output ports with the 'o'\n"); log("prefix and inout ports with the 'io' prefix. The optional specifies\n"); log("the position of the port in the parameter list (needed when instantiated\n"); log("using positional arguments). When is not specified, the can\n"); log("also contain wildcard characters.\n"); log("\n"); log("This pass ignores the current selection and always operates on all modules\n"); log("in the current design.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { log_header(design, "Executing HIERARCHY pass (managing design hierarchy).\n"); bool flag_check = false; bool flag_simcheck = false; bool flag_smtcheck = false; bool purge_lib = false; std::string top_mod_name_to_load = ""; std::vector libdirs; bool auto_top_mode = false; bool generate_mode = false; bool keep_positionals = false; bool keep_portwidths = false; bool nodefaults = false; bool nokeep_prints = false; bool nokeep_asserts = false; Generator generator; std::map parameters; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-generate" && !flag_check && !flag_simcheck && !flag_smtcheck) { generate_mode = true; log("Entering generate mode.\n"); while (++argidx < args.size()) { generator.parse_arg(args[argidx].c_str()); } continue; } if (args[argidx] == "-check") { flag_check = true; continue; } if (args[argidx] == "-simcheck") { flag_simcheck = true; continue; } if (args[argidx] == "-smtcheck") { flag_smtcheck = true; continue; } if (args[argidx] == "-purge_lib") { purge_lib = true; continue; } if (args[argidx] == "-keep_positionals") { keep_positionals = true; continue; } if (args[argidx] == "-keep_portwidths") { keep_portwidths = true; continue; } if (args[argidx] == "-nodefaults") { nodefaults = true; continue; } if (args[argidx] == "-nokeep_prints") { nokeep_prints = true; continue; } if (args[argidx] == "-nokeep_asserts") { nokeep_asserts = true; continue; } if (args[argidx] == "-libdir" && argidx+1 < args.size()) { libdirs.push_back(args[++argidx]); continue; } if (args[argidx] == "-top") { if (++argidx >= args.size()) log_cmd_error("Option -top requires an additional argument!\n"); top_mod_name_to_load = args[argidx]; continue; } if (args[argidx] == "-auto-top") { auto_top_mode = true; continue; } if (args[argidx] == "-chparam" && argidx+2 < args.size()) { const std::string &key = args[++argidx]; const std::string &value = args[++argidx]; auto r = parameters.emplace(key, value); if (!r.second) { log_warning("-chparam %s already specified: overwriting.\n", key); r.first->second = value; } continue; } break; } extra_args(args, argidx, design, false); if (generate_mode) return generator.generate(design); log_push(); TopModulePrepare top {design, parameters}; Module* top_mod = top.load_top(top_mod_name_to_load, auto_top_mode); if ((flag_simcheck || flag_smtcheck) && top_mod == nullptr) log_error("Design has no top module.\n"); expand_all_interfaces(design, top_mod, flag_check, flag_simcheck, flag_smtcheck, libdirs); if (top_mod != NULL) { log_header(design, "Analyzing design hierarchy..\n"); clean(design, top_mod, purge_lib); } if (top_mod != NULL) ensure_unique_top_attribute(top_mod, design); set_keeps(design, !nokeep_prints, !nokeep_asserts); if (flag_simcheck || flag_smtcheck) { check_supported_formal(design); } resolve_verilog(design, nodefaults, keep_positionals, keep_portwidths, top.is_from_verific); log_pop(); } } HierarchyPass; PRIVATE_NAMESPACE_END