mirror of https://github.com/YosysHQ/yosys.git
265 lines
9.5 KiB
C++
265 lines
9.5 KiB
C++
/*
|
|
* yosys -- Yosys Open SYnthesis Suite
|
|
*
|
|
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
|
* Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
|
|
*
|
|
* 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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <set>
|
|
|
|
#ifndef _WIN32
|
|
# include <unistd.h>
|
|
#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 <module>]\n");
|
|
log(" hierarchy -generate <cell-types> <port-decls>\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 <directory>\n");
|
|
log(" search for files named <module_name>.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 <module>\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}[@<num>]:<portname>\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 <num> specifies\n");
|
|
log("the position of the port in the parameter list (needed when instantiated\n");
|
|
log("using positional arguments). When <num> is not specified, the <portname> 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<std::string> 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<std::string> 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<std::string, std::string> 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
|