aboutsummaryrefslogtreecommitdiffstats
path: root/passes/cmds
diff options
context:
space:
mode:
Diffstat (limited to 'passes/cmds')
-rw-r--r--passes/cmds/Makefile.inc2
-rw-r--r--passes/cmds/add.cc2
-rw-r--r--passes/cmds/autoname.cc28
-rw-r--r--passes/cmds/blackbox.cc5
-rw-r--r--passes/cmds/bugpoint.cc153
-rw-r--r--passes/cmds/check.cc87
-rw-r--r--passes/cmds/chformal.cc2
-rw-r--r--passes/cmds/chtype.cc2
-rw-r--r--passes/cmds/clean_zerowidth.cc210
-rw-r--r--passes/cmds/connect.cc30
-rw-r--r--passes/cmds/connwrappers.cc2
-rw-r--r--passes/cmds/copy.cc2
-rw-r--r--passes/cmds/cover.cc2
-rw-r--r--passes/cmds/delete.cc14
-rw-r--r--passes/cmds/design.cc2
-rw-r--r--passes/cmds/edgetypes.cc2
-rw-r--r--passes/cmds/exec.cc2
-rw-r--r--passes/cmds/logcmd.cc2
-rw-r--r--passes/cmds/logger.cc11
-rw-r--r--passes/cmds/ltp.cc2
-rw-r--r--passes/cmds/plugin.cc8
-rw-r--r--passes/cmds/portlist.cc2
-rw-r--r--passes/cmds/qwp.cc2
-rw-r--r--passes/cmds/rename.cc6
-rw-r--r--passes/cmds/scatter.cc2
-rw-r--r--passes/cmds/scc.cc79
-rw-r--r--passes/cmds/scratchpad.cc4
-rw-r--r--passes/cmds/select.cc2
-rw-r--r--passes/cmds/setattr.cc2
-rw-r--r--passes/cmds/setundef.cc2
-rw-r--r--passes/cmds/show.cc32
-rw-r--r--passes/cmds/splice.cc4
-rw-r--r--passes/cmds/splitnets.cc2
-rw-r--r--passes/cmds/sta.cc312
-rw-r--r--passes/cmds/stat.cc10
-rw-r--r--passes/cmds/tee.cc2
-rw-r--r--passes/cmds/torder.cc4
-rw-r--r--passes/cmds/trace.cc2
-rw-r--r--passes/cmds/write_file.cc2
39 files changed, 909 insertions, 132 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 5ec2fb6ad..16a38b511 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -41,3 +41,5 @@ endif
OBJS += passes/cmds/scratchpad.o
OBJS += passes/cmds/logger.o
OBJS += passes/cmds/printattrs.o
+OBJS += passes/cmds/sta.o
+OBJS += passes/cmds/clean_zerowidth.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index a2f4a9100..c09517254 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc
index 28d4012c4..6019c6153 100644
--- a/passes/cmds/autoname.cc
+++ b/passes/cmds/autoname.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -22,25 +22,20 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-int autoname_worker(Module *module)
+int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
{
dict<Cell*, pair<int, IdString>> proposed_cell_names;
dict<Wire*, pair<int, IdString>> proposed_wire_names;
- dict<Wire*, int> wire_score;
int best_score = -1;
- for (auto cell : module->selected_cells())
- for (auto &conn : cell->connections())
- for (auto bit : conn.second)
- if (bit.wire != nullptr)
- wire_score[bit.wire]++;
-
for (auto cell : module->selected_cells()) {
if (cell->name[0] == '$') {
for (auto &conn : cell->connections()) {
- string suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
+ string suffix;
for (auto bit : conn.second)
if (bit.wire != nullptr && bit.wire->name[0] != '$') {
+ if (suffix.empty())
+ suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
IdString new_name(bit.wire->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
@@ -54,9 +49,11 @@ int autoname_worker(Module *module)
}
} else {
for (auto &conn : cell->connections()) {
- string suffix = stringf("_%s", log_id(conn.first));
+ string suffix;
for (auto bit : conn.second)
if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) {
+ if (suffix.empty())
+ suffix = stringf("_%s", log_id(conn.first));
IdString new_name(cell->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
@@ -118,10 +115,17 @@ struct AutonamePass : public Pass {
for (auto module : design->selected_modules())
{
+ dict<Wire*, int> wire_score;
+ for (auto cell : module->selected_cells())
+ for (auto &conn : cell->connections())
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr)
+ wire_score[bit.wire]++;
+
int count = 0, iter = 0;
while (1) {
iter++;
- int n = autoname_worker(module);
+ int n = autoname_worker(module, wire_score);
if (!n) break;
count += n;
}
diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc
index 08a635514..43670efaf 100644
--- a/passes/cmds/blackbox.cc
+++ b/passes/cmds/blackbox.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -46,10 +46,11 @@ struct BlackboxPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto module : design->selected_whole_modules_warn())
+ for (auto module : design->selected_whole_modules_warn(true))
{
module->makeblackbox();
module->set_bool_attribute(ID::blackbox);
+ module->set_bool_attribute(ID::whitebox, false);
}
}
} BlackboxPass;
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index 98d42aa83..7b621504d 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -18,10 +18,10 @@
*/
#include "kernel/yosys.h"
-#include "backends/ilang/ilang_backend.h"
+#include "backends/rtlil/rtlil_backend.h"
USING_YOSYS_NAMESPACE
-using namespace ILANG_BACKEND;
+using namespace RTLIL_BACKEND;
PRIVATE_NAMESPACE_BEGIN
struct BugpointPass : public Pass {
@@ -30,7 +30,7 @@ struct BugpointPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" bugpoint [options] -script <filename>\n");
+ log(" bugpoint [options] [-script <filename> | -command \"<command>\"]\n");
log("\n");
log("This command minimizes the current design that is known to crash Yosys with the\n");
log("given script into a smaller testcase. It does this by removing an arbitrary part\n");
@@ -38,14 +38,16 @@ struct BugpointPass : public Pass {
log("and the same script, repeating these steps while it can find a smaller design that\n");
log("still causes a crash. Once this command finishes, it replaces the current design\n");
log("with the smallest testcase it was able to produce.\n");
+ log("In order to save the reduced testcase you must write this out to a file with\n");
+ log("another command after `bugpoint` like `write_rtlil` or `write_verilog`.\n");
log("\n");
- log(" -script <filename>\n");
- log(" use this script to crash Yosys. required.\n");
+ log(" -script <filename> | -command \"<command>\"\n");
+ log(" use this script file or command to crash Yosys. required.\n");
log("\n");
log(" -yosys <filename>\n");
log(" use this Yosys binary. if not specified, `yosys` is used.\n");
log("\n");
- log(" -grep <string>\n");
+ log(" -grep \"<string>\"\n");
log(" only consider crashes that place this string in the log file.\n");
log("\n");
log(" -fast\n");
@@ -77,23 +79,30 @@ struct BugpointPass : public Pass {
log(" -connections\n");
log(" try to reconnect ports to 'x.\n");
log("\n");
+ log(" -processes\n");
+ log(" try to remove processes. processes with a (* bugpoint_keep *) attribute\n");
+ log(" will be skipped.\n");
+ log("\n");
log(" -assigns\n");
log(" try to remove process assigns from cases.\n");
log("\n");
log(" -updates\n");
log(" try to remove process updates from syncs.\n");
log("\n");
+ log(" -runner \"<prefix>\"\n");
+ log(" child process wrapping command, e.g., \"timeout 30\", or valgrind.\n");
+ log("\n");
}
- bool run_yosys(RTLIL::Design *design, string yosys_cmd, string script)
+ bool run_yosys(RTLIL::Design *design, string runner, string yosys_cmd, string yosys_arg)
{
design->sort();
std::ofstream f("bugpoint-case.il");
- ILANG_BACKEND::dump_design(f, design, /*only_selected=*/false, /*flag_m=*/true, /*flag_n=*/false);
+ RTLIL_BACKEND::dump_design(f, design, /*only_selected=*/false, /*flag_m=*/true, /*flag_n=*/false);
f.close();
- string yosys_cmdline = stringf("%s -qq -L bugpoint-case.log -s %s bugpoint-case.il", yosys_cmd.c_str(), script.c_str());
+ string yosys_cmdline = stringf("%s %s -qq -L bugpoint-case.log %s bugpoint-case.il", runner.c_str(), yosys_cmd.c_str(), yosys_arg.c_str());
return run_command(yosys_cmdline) == 0;
}
@@ -102,6 +111,9 @@ struct BugpointPass : public Pass {
if (grep.empty())
return true;
+ if (grep.size() > 2 && grep.front() == '"' && grep.back() == '"')
+ grep = grep.substr(1, grep.size() - 2);
+
std::ifstream f("bugpoint-case.log");
while (!f.eof())
{
@@ -129,7 +141,7 @@ struct BugpointPass : public Pass {
return design_copy;
}
- RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool assigns, bool updates)
+ RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool processes, bool assigns, bool updates, bool wires)
{
RTLIL::Design *design_copy = new RTLIL::Design;
for (auto module : design->modules())
@@ -194,7 +206,6 @@ struct BugpointPass : public Pass {
if (mod->get_blackbox_attribute())
continue;
-
Cell *removed_cell = nullptr;
for (auto cell : mod->cells())
{
@@ -257,6 +268,32 @@ struct BugpointPass : public Pass {
}
}
}
+ if (processes)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ RTLIL::Process *removed_process = nullptr;
+ for (auto process : mod->processes)
+ {
+ if (process.second->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
+ if (index++ == seed)
+ {
+ log_header(design, "Trying to remove process %s.%s.\n", log_id(mod), log_id(process.first));
+ removed_process = process.second;
+ break;
+ }
+ }
+ if (removed_process) {
+ mod->remove(removed_process);
+ return design_copy;
+ }
+ }
+ }
if (assigns)
{
for (auto mod : design_copy->modules())
@@ -306,8 +343,54 @@ struct BugpointPass : public Pass {
return design_copy;
}
}
+ int i = 0;
+ for (auto it = sy->mem_write_actions.begin(); it != sy->mem_write_actions.end(); ++it, ++i)
+ {
+ if (index++ == seed)
+ {
+ log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), log_id(it->memid), log_signal(it->address), log_signal(it->data), log_signal(it->enable), log_id(mod), log_id(pr.first));
+ sy->mem_write_actions.erase(it);
+ // Remove the bit for removed action from other actions' priority masks.
+ for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) {
+ auto &mask = it2->priority_mask;
+ if (GetSize(mask) > i) {
+ mask.bits.erase(mask.bits.begin() + i);
+ }
+ }
+ return design_copy;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (wires)
+ {
+ for (auto mod : design_copy->modules())
+ {
+ if (mod->get_blackbox_attribute())
+ continue;
+
+ Wire *removed_wire = nullptr;
+ for (auto wire : mod->wires())
+ {
+ if (wire->get_bool_attribute(ID::bugpoint_keep))
+ continue;
+
+ if (wire->name.begins_with("$delete_wire") || wire->name.begins_with("$auto$bugpoint"))
+ continue;
+
+ if (index++ == seed)
+ {
+ log_header(design, "Trying to remove wire %s.%s.\n", log_id(mod), log_id(wire));
+ removed_wire = wire;
+ break;
}
}
+ if (removed_wire) {
+ mod->remove({removed_wire});
+ return design_copy;
+ }
}
}
return nullptr;
@@ -315,9 +398,9 @@ struct BugpointPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
- string yosys_cmd = "yosys", script, grep;
+ string yosys_cmd = "yosys", yosys_arg, grep, runner;
bool fast = false, clean = false;
- bool modules = false, ports = false, cells = false, connections = false, assigns = false, updates = false, has_part = false;
+ bool modules = false, ports = false, cells = false, connections = false, processes = false, assigns = false, updates = false, wires = false, has_part = false;
log_header(design, "Executing BUGPOINT pass (minimize testcases).\n");
log_push();
@@ -330,7 +413,15 @@ struct BugpointPass : public Pass {
continue;
}
if (args[argidx] == "-script" && argidx + 1 < args.size()) {
- script = args[++argidx];
+ if (!yosys_arg.empty())
+ log_cmd_error("A -script or -command option can be only provided once!\n");
+ yosys_arg = stringf("-s %s", args[++argidx].c_str());
+ continue;
+ }
+ if (args[argidx] == "-command" && argidx + 1 < args.size()) {
+ if (!yosys_arg.empty())
+ log_cmd_error("A -script or -command option can be only provided once!\n");
+ yosys_arg = stringf("-p %s", args[++argidx].c_str());
continue;
}
if (args[argidx] == "-grep" && argidx + 1 < args.size()) {
@@ -365,6 +456,11 @@ struct BugpointPass : public Pass {
has_part = true;
continue;
}
+ if (args[argidx] == "-processes") {
+ processes = true;
+ has_part = true;
+ continue;
+ }
if (args[argidx] == "-assigns") {
assigns = true;
has_part = true;
@@ -375,12 +471,25 @@ struct BugpointPass : public Pass {
has_part = true;
continue;
}
+ if (args[argidx] == "-wires") {
+ wires = true;
+ has_part = true;
+ continue;
+ }
+ if (args[argidx] == "-runner" && argidx + 1 < args.size()) {
+ runner = args[++argidx];
+ if (runner.size() && runner.at(0) == '"') {
+ log_assert(runner.back() == '"');
+ runner = runner.substr(1, runner.size() - 2);
+ }
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
- if (script.empty())
- log_cmd_error("Missing -script option.\n");
+ if (yosys_arg.empty())
+ log_cmd_error("Missing -script or -command option.\n");
if (!has_part)
{
@@ -388,16 +497,18 @@ struct BugpointPass : public Pass {
ports = true;
cells = true;
connections = true;
+ processes = true;
assigns = true;
updates = true;
+ wires = true;
}
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
RTLIL::Design *crashing_design = clean_design(design, clean);
- if (run_yosys(crashing_design, yosys_cmd, script))
- log_cmd_error("The provided script file and Yosys binary do not crash on this design!\n");
+ if (run_yosys(crashing_design, runner, yosys_cmd, yosys_arg))
+ log_cmd_error("The provided script file or command and Yosys binary do not crash on this design!\n");
if (!check_logfile(grep))
log_cmd_error("The provided grep string is not found in the log file!\n");
@@ -405,7 +516,7 @@ struct BugpointPass : public Pass {
bool found_something = false, stage2 = false;
while (true)
{
- if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections, assigns, updates))
+ if (RTLIL::Design *simplified = simplify_something(crashing_design, seed, stage2, modules, ports, cells, connections, processes, assigns, updates, wires))
{
simplified = clean_design(simplified, fast, /*do_delete=*/true);
@@ -413,12 +524,12 @@ struct BugpointPass : public Pass {
if (clean)
{
RTLIL::Design *testcase = clean_design(simplified);
- crashes = !run_yosys(testcase, yosys_cmd, script);
+ crashes = !run_yosys(testcase, runner, yosys_cmd, yosys_arg);
delete testcase;
}
else
{
- crashes = !run_yosys(simplified, yosys_cmd, script);
+ crashes = !run_yosys(simplified, runner, yosys_cmd, yosys_arg);
}
if (crashes && check_logfile(grep))
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index a8b5362b3..ee0f0a58f 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -35,30 +35,28 @@ struct CheckPass : public Pass {
log("\n");
log("This pass identifies the following problems in the current design:\n");
log("\n");
- log(" - combinatorial loops\n");
- log("\n");
- log(" - two or more conflicting drivers for one wire\n");
- log("\n");
- log(" - used wires that do not have a driver\n");
+ log(" - combinatorial loops\n");
+ log(" - two or more conflicting drivers for one wire\n");
+ log(" - used wires that do not have a driver\n");
log("\n");
log("Options:\n");
log("\n");
- log(" -noinit\n");
- log(" Also check for wires which have the 'init' attribute set.\n");
+ log(" -noinit\n");
+ log(" also check for wires which have the 'init' attribute set\n");
log("\n");
- log(" -initdrv\n");
- log(" Also check for wires that have the 'init' attribute set and are not\n");
- log(" driven by an FF cell type.\n");
+ log(" -initdrv\n");
+ log(" also check for wires that have the 'init' attribute set and are not\n");
+ log(" driven by an FF cell type\n");
log("\n");
- log(" -mapped\n");
- log(" Also check for internal cells that have not been mapped to cells of the\n");
- log(" target architecture.\n");
+ log(" -mapped\n");
+ log(" also check for internal cells that have not been mapped to cells of the\n");
+ log(" target architecture\n");
log("\n");
- log(" -allow-tbuf\n");
- log(" Modify the -mapped behavior to still allow $_TBUF_ cells.\n");
+ log(" -allow-tbuf\n");
+ log(" modify the -mapped behavior to still allow $_TBUF_ cells\n");
log("\n");
- log(" -assert\n");
- log(" Produce a runtime error if any problems are found in the current design.\n");
+ log(" -assert\n");
+ log(" produce a runtime error if any problems are found in the current design\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -100,10 +98,7 @@ struct CheckPass : public Pass {
for (auto module : design->selected_whole_modules_warn())
{
- if (module->has_processes_warn())
- continue;
-
- log("checking module %s..\n", log_id(module));
+ log("Checking module %s...\n", log_id(module));
SigMap sigmap(module);
dict<SigBit, vector<string>> wire_drivers;
@@ -111,6 +106,52 @@ struct CheckPass : public Pass {
pool<SigBit> used_wires;
TopoSort<string> topo;
+ for (auto &proc_it : module->processes)
+ {
+ std::vector<RTLIL::CaseRule*> all_cases = {&proc_it.second->root_case};
+ for (size_t i = 0; i < all_cases.size(); i++) {
+ for (auto action : all_cases[i]->actions) {
+ for (auto bit : sigmap(action.first))
+ if (bit.wire) {
+ wire_drivers[bit].push_back(
+ stringf("action %s <= %s (case rule) in process %s",
+ log_signal(action.first), log_signal(action.second), log_id(proc_it.first)));
+ }
+ for (auto bit : sigmap(action.second))
+ if (bit.wire) used_wires.insert(bit);
+ }
+ for (auto switch_ : all_cases[i]->switches) {
+ for (auto case_ : switch_->cases) {
+ all_cases.push_back(case_);
+ for (auto compare : case_->compare)
+ for (auto bit : sigmap(compare))
+ if (bit.wire) used_wires.insert(bit);
+ }
+ }
+ }
+ for (auto &sync : proc_it.second->syncs) {
+ for (auto bit : sigmap(sync->signal))
+ if (bit.wire) used_wires.insert(bit);
+ for (auto action : sync->actions) {
+ for (auto bit : sigmap(action.first))
+ if (bit.wire)
+ wire_drivers[bit].push_back(
+ stringf("action %s <= %s (sync rule) in process %s",
+ log_signal(action.first), log_signal(action.second), log_id(proc_it.first)));
+ for (auto bit : sigmap(action.second))
+ if (bit.wire) used_wires.insert(bit);
+ }
+ for (auto memwr : sync->mem_write_actions) {
+ for (auto bit : sigmap(memwr.address))
+ if (bit.wire) used_wires.insert(bit);
+ for (auto bit : sigmap(memwr.data))
+ if (bit.wire) used_wires.insert(bit);
+ for (auto bit : sigmap(memwr.enable))
+ if (bit.wire) used_wires.insert(bit);
+ }
+ }
+ }
+
for (auto cell : module->cells())
{
if (mapped && cell->type.begins_with("$") && design->module(cell->type) == nullptr) {
@@ -216,7 +257,7 @@ struct CheckPass : public Pass {
}
}
- log("found and reported %d problems.\n", counter);
+ log("Found and reported %d problems.\n", counter);
if (assert_mode && counter > 0)
log_error("Found %d problems in 'check -assert'.\n", counter);
diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc
index a1b3fbef7..d813a449c 100644
--- a/passes/cmds/chformal.cc
+++ b/passes/cmds/chformal.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc
index b894f334c..6f9ca9a45 100644
--- a/passes/cmds/chtype.cc
+++ b/passes/cmds/chtype.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/clean_zerowidth.cc b/passes/cmds/clean_zerowidth.cc
new file mode 100644
index 000000000..bac6b1521
--- /dev/null
+++ b/passes/cmds/clean_zerowidth.cc
@@ -0,0 +1,210 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Koƛcielnicka <mwk@0x04.net>
+ *
+ * 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 "kernel/celltypes.h"
+#include "kernel/mem.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct CleanZeroWidthPass : public Pass {
+ CleanZeroWidthPass() : Pass("clean_zerowidth", "clean zero-width connections from the design") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" clean_zerowidth [selection]\n");
+ log("\n");
+ log("Fixes the selected cells and processes to contain no zero-width connections.\n");
+ log("Depending on the cell type, this may be implemented by removing the connection,\n");
+ log("widening it to 1-bit, or removing the cell altogether.\n");
+ log("\n");
+ }
+
+ void clean_case(RTLIL::CaseRule *cs)
+ {
+ std::vector<SigSig> new_actions;
+ for (auto &action : cs->actions)
+ if (GetSize(action.first) != 0)
+ new_actions.push_back(action);
+ std::swap(new_actions, cs->actions);
+ for (auto sw : cs->switches)
+ for (auto scs : sw->cases)
+ clean_case(scs);
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ CellTypes ct;
+ ct.setup();
+
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (!ct.cell_known(cell->type)) {
+ // User-defined cell: just prune zero-width connections.
+ for (auto it: cell->connections()) {
+ if (GetSize(it.second) == 0) {
+ cell->unsetPort(it.first);
+ }
+ }
+ } else if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ // Coarse FF cells: remove if WIDTH == 0 (no outputs).
+ // This will also trigger on fine cells, so use the Q port
+ // width instead of actual WIDTH parameter.
+ if (GetSize(cell->getPort(ID::Q)) == 0) {
+ module->remove(cell);
+ }
+ } else if (cell->type.in(ID($pmux), ID($bmux), ID($demux))) {
+ // Remove altogether if WIDTH is 0, replace with
+ // a connection if S_WIDTH is 0.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ module->remove(cell);
+ }
+ if (cell->getParam(ID::S_WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
+ module->remove(cell);
+ }
+ } else if (cell->type == ID($concat)) {
+ // If a concat has a zero-width input: replace with direct
+ // connection to the other input.
+ if (cell->getParam(ID::A_WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::B));
+ module->remove(cell);
+ } else if (cell->getParam(ID::B_WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
+ module->remove(cell);
+ }
+ } else if (cell->type == ID($fsm)) {
+ // TODO: not supported
+ } else if (cell->is_mem_cell()) {
+ // Skip — will be handled below.
+ } else if (cell->type == ID($lut)) {
+ // Zero-width LUT is just a const driver.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getParam(ID::LUT)[0]);
+ module->remove(cell);
+ }
+ } else if (cell->type == ID($sop)) {
+ // Zero-width SOP is just a const driver.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ // The value is 1 iff DEPTH is non-0.
+ bool val = cell->getParam(ID::DEPTH).as_int() != 0;
+ module->connect(cell->getPort(ID::Y), val);
+ module->remove(cell);
+ }
+ } else if (cell->hasParam(ID::WIDTH)) {
+ // For cells with WIDTH parameter: remove if zero.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ module->remove(cell);
+ }
+ } else if (cell->hasParam(ID::Y_WIDTH)) {
+ // For most operators: remove if Y width is 0, expand
+ // A and B to 1-bit if their width is 0.
+ if (cell->getParam(ID::Y_WIDTH).as_int() == 0) {
+ module->remove(cell);
+ } else if (cell->type == ID($macc)) {
+ // TODO: fixing zero-width A and B not supported.
+ } else {
+ if (cell->getParam(ID::A_WIDTH).as_int() == 0) {
+ cell->setPort(ID::A, State::S0);
+ cell->setParam(ID::A_WIDTH, 1);
+ }
+ if (cell->hasParam(ID::B_WIDTH) && cell->getParam(ID::B_WIDTH).as_int() == 0) {
+ cell->setPort(ID::B, State::S0);
+ cell->setParam(ID::B_WIDTH, 1);
+ }
+ }
+ }
+ }
+
+ // NOTE: Zero-width switch signals are left alone for processes, as there
+ // is no simple way of cleaning them up.
+ for (auto &it: module->processes) {
+ if (!design->selected(module, it.second))
+ continue;
+ clean_case(&it.second->root_case);
+ for (auto sync : it.second->syncs) {
+ std::vector<int> swizzle;
+ std::vector<RTLIL::MemWriteAction> new_memwr_actions;
+ for (int i = 0; i < GetSize(sync->mem_write_actions); i++) {
+ auto &memwr = sync->mem_write_actions[i];
+ if (GetSize(memwr.data) == 0)
+ continue;
+ if (GetSize(memwr.address) == 0)
+ memwr.address = State::S0;
+ Const priority_mask;
+ for (auto x : swizzle) {
+ priority_mask.bits.push_back(memwr.priority_mask.bits[x]);
+ }
+ memwr.priority_mask = priority_mask;
+ swizzle.push_back(i);
+ new_memwr_actions.push_back(memwr);
+ }
+ std::swap(new_memwr_actions, sync->mem_write_actions);
+ std::vector<SigSig> new_actions;
+ for (auto &action : sync->actions)
+ if (GetSize(action.first) != 0)
+ new_actions.push_back(action);
+ std::swap(new_actions, sync->actions);
+ }
+ }
+
+ for (auto &mem : Mem::get_selected_memories(module)) {
+ if (mem.width == 0) {
+ mem.remove();
+ continue;
+ }
+ for (auto &init : mem.inits) {
+ if (GetSize(init.addr) == 0) {
+ init.addr = State::S0;
+ }
+ }
+ for (auto &port : mem.rd_ports) {
+ if (GetSize(port.addr) == 0) {
+ port.addr = State::S0;
+ }
+ }
+ for (auto &port : mem.wr_ports) {
+ if (GetSize(port.addr) == 0) {
+ port.addr = State::S0;
+ }
+ }
+ mem.emit();
+ }
+
+ std::vector<SigSig> new_conns;
+ for (auto &conn : module->connections())
+ if (GetSize(conn.first) != 0)
+ new_conns.push_back(conn);
+ module->new_connections(new_conns);
+ }
+ }
+} CleanZeroWidthPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index 0cc6cbe52..1bd52aab2 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -60,7 +60,7 @@ struct ConnectPass : public Pass {
log("Unconnect all existing drivers for the specified expression.\n");
log("\n");
log("\n");
- log(" connect [-nomap] -port <cell> <port> <expr>\n");
+ log(" connect [-nomap] [-assert] -port <cell> <port> <expr>\n");
log("\n");
log("Connect the specified cell port to the specified cell port.\n");
log("\n");
@@ -72,6 +72,9 @@ struct ConnectPass : public Pass {
log("The connect command operates in one module only. Either only one module must\n");
log("be selected or an active module must be set using the 'cd' command.\n");
log("\n");
+ log("The -assert option verifies that the connection already exists, instead of\n");
+ log("making it.\n");
+ log("\n");
log("This command does not operate on module with processes.\n");
log("\n");
}
@@ -88,7 +91,7 @@ struct ConnectPass : public Pass {
if (!module->processes.empty())
log_cmd_error("Found processes in selected module.\n");
- bool flag_nounset = false, flag_nomap = false;
+ bool flag_nounset = false, flag_nomap = false, flag_assert = false;
std::string set_lhs, set_rhs, unset_expr;
std::string port_cell, port_port, port_expr;
@@ -104,6 +107,10 @@ struct ConnectPass : public Pass {
flag_nomap = true;
continue;
}
+ if (arg == "-assert") {
+ flag_assert = true;
+ continue;
+ }
if (arg == "-set" && argidx+2 < args.size()) {
set_lhs = args[++argidx];
set_rhs = args[++argidx];
@@ -126,7 +133,7 @@ struct ConnectPass : public Pass {
if (!flag_nomap)
for (auto &it : module->connections()) {
std::vector<RTLIL::SigBit> lhs = it.first.to_sigbit_vector();
- std::vector<RTLIL::SigBit> rhs = it.first.to_sigbit_vector();
+ std::vector<RTLIL::SigBit> rhs = it.second.to_sigbit_vector();
for (size_t i = 0; i < lhs.size(); i++)
if (rhs[i].wire != nullptr)
sigmap.add(lhs[i], rhs[i]);
@@ -137,6 +144,9 @@ struct ConnectPass : public Pass {
if (!unset_expr.empty() || !port_cell.empty())
log_cmd_error("Can't use -set together with -unset and/or -port.\n");
+ if (flag_assert)
+ log_cmd_error("The -assert option is only supported with -port.\n");
+
RTLIL::SigSpec sig_lhs, sig_rhs;
if (!RTLIL::SigSpec::parse_sel(sig_lhs, design, module, set_lhs))
log_cmd_error("Failed to parse set lhs expression `%s'.\n", set_lhs.c_str());
@@ -157,6 +167,9 @@ struct ConnectPass : public Pass {
if (!port_cell.empty() || flag_nounset)
log_cmd_error("Can't use -unset together with -port and/or -nounset.\n");
+ if (flag_assert)
+ log_cmd_error("The -assert option is only supported with -port.\n");
+
RTLIL::SigSpec sig;
if (!RTLIL::SigSpec::parse_sel(sig, design, module, unset_expr))
log_cmd_error("Failed to parse unset expression `%s'.\n", unset_expr.c_str());
@@ -177,7 +190,14 @@ struct ConnectPass : public Pass {
if (!RTLIL::SigSpec::parse_sel(sig, design, module, port_expr))
log_cmd_error("Failed to parse port expression `%s'.\n", port_expr.c_str());
- module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
+ if (!flag_assert) {
+ module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
+ } else {
+ SigSpec cur = module->cell(RTLIL::escape_id(port_cell))->getPort(RTLIL::escape_id(port_port));
+ if (sigmap(sig) != sigmap(cur)) {
+ log_cmd_error("Expected connection not present: expected %s, found %s.\n", log_signal(sig), log_signal(cur));
+ }
+ }
}
else
log_cmd_error("Expected -set, -unset, or -port.\n");
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index 9235dda2b..dbe23ccf1 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index c351065f3..e3fb3a0e6 100644
--- a/passes/cmds/copy.cc
+++ b/passes/cmds/copy.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 0867e3b4f..1db3e2ca0 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index 684fa37b0..e341f29d6 100644
--- a/passes/cmds/delete.cc
+++ b/passes/cmds/delete.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -90,7 +90,7 @@ struct DeletePass : public Pass {
pool<RTLIL::Wire*> delete_wires;
pool<RTLIL::Cell*> delete_cells;
- pool<RTLIL::IdString> delete_procs;
+ pool<RTLIL::Process*> delete_procs;
pool<RTLIL::IdString> delete_mems;
for (auto wire : module->selected_wires())
@@ -103,14 +103,14 @@ struct DeletePass : public Pass {
for (auto cell : module->cells()) {
if (design->selected(module, cell))
delete_cells.insert(cell);
- if (cell->type.in(ID($memrd), ID($memwr)) &&
+ if (cell->has_memid() &&
delete_mems.count(cell->parameters.at(ID::MEMID).decode_string()) != 0)
delete_cells.insert(cell);
}
for (auto &it : module->processes)
if (design->selected(module, it.second))
- delete_procs.insert(it.first);
+ delete_procs.insert(it.second);
for (auto &it : delete_mems) {
delete module->memories.at(it);
@@ -120,10 +120,8 @@ struct DeletePass : public Pass {
for (auto &it : delete_cells)
module->remove(it);
- for (auto &it : delete_procs) {
- delete module->processes.at(it);
- module->processes.erase(it);
- }
+ for (auto &it : delete_procs)
+ module->remove(it);
module->remove(delete_wires);
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index 2d7ba1fef..169f7cc4a 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc
index 37c420400..5b53f50cc 100644
--- a/passes/cmds/edgetypes.cc
+++ b/passes/cmds/edgetypes.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc
index 951fa53fc..f00629a02 100644
--- a/passes/cmds/exec.cc
+++ b/passes/cmds/exec.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 - 2020 Claire Wolf <claire@symbioticeda.com>
+ * Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc
index 12c43ecec..f1702400d 100644
--- a/passes/cmds/logcmd.cc
+++ b/passes/cmds/logcmd.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc
index 6a9ed6036..ec92f1d01 100644
--- a/passes/cmds/logger.cc
+++ b/passes/cmds/logger.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2020 Miodrag Milanovic <clifford@clifford.at>
+ * Copyright (C) 2020 Miodrag Milanovic <micko@yosyshq.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
@@ -64,6 +64,11 @@ struct LoggerPass : public Pass {
log(" -expect-no-warnings\n");
log(" gives error in case there is at least one warning that is not expected.\n");
log("\n");
+ log(" -check-expected\n");
+ log(" verifies that the patterns previously set up by -expect have actually\n");
+ log(" been met, then clears the expected log list. If this is not called\n");
+ log(" manually, the check will happen at yosys exist time instead.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design * design) override
@@ -176,6 +181,10 @@ struct LoggerPass : public Pass {
log_expect_no_warnings = true;
continue;
}
+ if (args[argidx] == "-check-expected") {
+ log_check_expected();
+ continue;
+ }
break;
}
extra_args(args, argidx, design, false);
diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc
index 39ec432c2..22bdaab44 100644
--- a/passes/cmds/ltp.cc
+++ b/passes/cmds/ltp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index 3ed19497d..3a1ae2850 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.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
@@ -93,7 +93,11 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
#else
void load_plugin(std::string, std::vector<std::string>)
{
- log_error("This version of yosys is built without plugin support.\n");
+ log_error(
+ "\n This version of Yosys cannot load plugins at runtime.\n"
+ " Some plugins may have been included at build time.\n"
+ " Use option `-H' to see the available built-in and plugin commands.\n"
+ );
}
#endif
diff --git a/passes/cmds/portlist.cc b/passes/cmds/portlist.cc
index 97f4bfd99..03048422d 100644
--- a/passes/cmds/portlist.cc
+++ b/passes/cmds/portlist.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index cf0f6d0de..2da612441 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 6326b4b15..1d08fc514 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -290,11 +290,11 @@ struct RenamePass : public Pass {
dict<RTLIL::Cell *, IdString> new_cell_names;
for (auto wire : module->selected_wires())
- if (wire->name[0] == '\\' && wire->port_id == 0)
+ if (wire->name.isPublic() && wire->port_id == 0)
new_wire_names[wire] = NEW_ID;
for (auto cell : module->selected_cells())
- if (cell->name[0] == '\\')
+ if (cell->name.isPublic())
new_cell_names[cell] = NEW_ID;
for (auto &it : new_wire_names)
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index a70dd3086..017600a46 100644
--- a/passes/cmds/scatter.cc
+++ b/passes/cmds/scatter.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index 8e7f3f990..81881832c 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -37,7 +37,7 @@ struct SccWorker
RTLIL::Design *design;
RTLIL::Module *module;
SigMap sigmap;
- CellTypes ct;
+ CellTypes ct, specifyCells;
std::set<RTLIL::Cell*> workQueue;
std::map<RTLIL::Cell*, std::set<RTLIL::Cell*>> cellToNextCell;
@@ -100,7 +100,7 @@ struct SccWorker
}
}
- SccWorker(RTLIL::Design *design, RTLIL::Module *module, bool nofeedbackMode, bool allCellTypes, int maxDepth) :
+ SccWorker(RTLIL::Design *design, RTLIL::Module *module, bool nofeedbackMode, bool allCellTypes, bool specifyMode, int maxDepth) :
design(design), module(module), sigmap(module)
{
if (module->processes.size() > 0) {
@@ -115,6 +115,18 @@ struct SccWorker
ct.setup_stdcells();
}
+ // Discover boxes with specify rules in them, for special handling.
+ if (specifyMode) {
+ for (auto mod : design->modules())
+ if (mod->get_blackbox_attribute(false))
+ for (auto cell : mod->cells())
+ if (cell->type == ID($specify2))
+ {
+ specifyCells.setup_module(mod);
+ break;
+ }
+ }
+
SigPool selectedSignals;
SigSet<RTLIL::Cell*> sigToNextCells;
@@ -129,29 +141,52 @@ struct SccWorker
if (!design->selected(module, cell))
continue;
- if (!allCellTypes && !ct.cell_known(cell->type))
+ if (!allCellTypes && !ct.cell_known(cell->type) && !specifyCells.cell_known(cell->type))
continue;
workQueue.insert(cell);
RTLIL::SigSpec inputSignals, outputSignals;
- for (auto &conn : cell->connections())
- {
- bool isInput = true, isOutput = true;
+ if (specifyCells.cell_known(cell->type)) {
+ // Use specify rules of the type `(X => Y) = NN` to look for asynchronous paths in boxes.
+ for (auto subcell : design->module(cell->type)->cells())
+ {
+ if (subcell->type != ID($specify2))
+ continue;
- if (ct.cell_known(cell->type)) {
- isInput = ct.cell_input(cell->type, conn.first);
- isOutput = ct.cell_output(cell->type, conn.first);
+ for (auto bit : subcell->getPort(ID::SRC))
+ {
+ if (!bit.wire || !cell->hasPort(bit.wire->name))
+ continue;
+ inputSignals.append(sigmap(cell->getPort(bit.wire->name)));
+ }
+
+ for (auto bit : subcell->getPort(ID::DST))
+ {
+ if (!bit.wire || !cell->hasPort(bit.wire->name))
+ continue;
+ outputSignals.append(sigmap(cell->getPort(bit.wire->name)));
+ }
}
+ } else {
+ for (auto &conn : cell->connections())
+ {
+ bool isInput = true, isOutput = true;
+
+ if (ct.cell_known(cell->type)) {
+ isInput = ct.cell_input(cell->type, conn.first);
+ isOutput = ct.cell_output(cell->type, conn.first);
+ }
- RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
- sig.sort_and_unify();
+ RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
+ sig.sort_and_unify();
- if (isInput)
- inputSignals.append(sig);
- if (isOutput)
- outputSignals.append(sig);
+ if (isInput)
+ inputSignals.append(sig);
+ if (isOutput)
+ outputSignals.append(sig);
+ }
}
inputSignals.sort_and_unify();
@@ -228,7 +263,7 @@ struct SccPass : public Pass {
log("design.\n");
log("\n");
log(" -expect <num>\n");
- log(" expect to find exactly <num> SSCs. A different number of SSCs will\n");
+ log(" expect to find exactly <num> SCCs. A different number of SCCs will\n");
log(" produce an error.\n");
log("\n");
log(" -max_depth <num>\n");
@@ -254,6 +289,9 @@ struct SccPass : public Pass {
log(" replace the current selection with a selection of all cells and wires\n");
log(" that are part of a found logic loop\n");
log("\n");
+ log(" -specify\n");
+ log(" examine specify rules to detect logic loops in whitebox/blackbox cells\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
@@ -261,6 +299,7 @@ struct SccPass : public Pass {
bool allCellTypes = false;
bool selectMode = false;
bool nofeedbackMode = false;
+ bool specifyMode = false;
int maxDepth = -1;
int expect = -1;
@@ -293,6 +332,10 @@ struct SccPass : public Pass {
selectMode = true;
continue;
}
+ if (args[argidx] == "-specify") {
+ specifyMode = true;
+ continue;
+ }
break;
}
int origSelectPos = design->selection_stack.size() - 1;
@@ -303,7 +346,7 @@ struct SccPass : public Pass {
for (auto mod : design->selected_modules())
{
- SccWorker worker(design, mod, nofeedbackMode, allCellTypes, maxDepth);
+ SccWorker worker(design, mod, nofeedbackMode, allCellTypes, specifyMode, maxDepth);
if (!setAttr.empty())
{
diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc
index 9369f5312..015eb97e7 100644
--- a/passes/cmds/scratchpad.cc
+++ b/passes/cmds/scratchpad.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * 2019 Nina Engelhardt <nak@symbioticeda.com>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * 2019 N. Engelhardt <nak@yosyshq.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
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index b4f3994a2..bb7b78cfe 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 3a94209d4..710fa9ab4 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index cf8d76619..a078b0b1c 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index cbed08a3f..8f9824f9b 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -239,6 +239,19 @@ struct ShowWorker
int idx = single_idx_count++;
for (int rep, i = int(sig.chunks().size())-1; i >= 0; i -= rep) {
const RTLIL::SigChunk &c = sig.chunks().at(i);
+ int cl, cr;
+ if (c.wire) {
+ if (c.wire->upto) {
+ cr = c.wire->start_offset + (c.wire->width - c.offset - 1);
+ cl = cr - (c.width - 1);
+ } else {
+ cr = c.wire->start_offset + c.offset;
+ cl = cr + c.width - 1;
+ }
+ } else {
+ cl = c.offset + c.width - 1;
+ cr = c.offset;
+ }
if (!driver && c.wire == nullptr) {
RTLIL::State s1 = c.data.front();
for (auto s2 : c.data)
@@ -254,7 +267,7 @@ struct ShowWorker
std::string repinfo = rep > 1 ? stringf("%dx ", rep) : "";
if (driver) {
log_assert(!net.empty());
- label_string += stringf("<s%d> %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), c.offset+c.width-1, c.offset);
+ label_string += stringf("<s%d> %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), cl, cr);
net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i));
net_conn_map[net].bits = rep*c.width;
net_conn_map[net].color = nextColor(c, net_conn_map[net].color);
@@ -268,7 +281,7 @@ struct ShowWorker
c.data.front() == State::Sz ? 'Z' : '?',
pos, pos-rep*c.width+1);
} else {
- label_string += stringf("<s%d> %s%d:%d - %d:%d |", i, repinfo.c_str(), c.offset+c.width-1, c.offset, pos, pos-rep*c.width+1);
+ label_string += stringf("<s%d> %s%d:%d - %d:%d |", i, repinfo.c_str(), cl, cr, pos, pos-rep*c.width+1);
net_conn_map[net].out.insert(stringf("x%d:s%d", idx, i));
net_conn_map[net].bits = rep*c.width;
net_conn_map[net].color = nextColor(c, net_conn_map[net].color);
@@ -339,6 +352,11 @@ struct ShowWorker
{
input_signals.insert(obj->signal);
collect_proc_signals(obj->actions, input_signals, output_signals);
+ for (auto it : obj->mem_write_actions) {
+ input_signals.insert(it.address);
+ input_signals.insert(it.data);
+ input_signals.insert(it.enable);
+ }
}
void collect_proc_signals(RTLIL::Process *obj, std::set<RTLIL::SigSpec> &input_signals, std::set<RTLIL::SigSpec> &output_signals)
@@ -368,7 +386,7 @@ struct ShowWorker
const char *shape = "diamond";
if (wire->port_input || wire->port_output)
shape = "octagon";
- if (wire->name[0] == '\\') {
+ if (wire->name.isPublic()) {
fprintf(f, "n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n",
id2num(wire->name), shape, findLabel(wire->name.str()),
nextColor(RTLIL::SigSpec(wire), "color=\"black\"").c_str());
@@ -605,7 +623,7 @@ struct ShowPass : public Pass {
log(" generate a .dot file, or other <format> strings such as 'svg' or 'ps'\n");
log(" to generate files in other formats (this calls the 'dot' command).\n");
log("\n");
- log(" -lib <verilog_or_ilang_file>\n");
+ log(" -lib <verilog_or_rtlil_file>\n");
log(" Use the specified library file for determining whether cell ports are\n");
log(" inputs or outputs. This option can be used multiple times to specify\n");
log(" more than one library.\n");
@@ -648,7 +666,7 @@ struct ShowPass : public Pass {
log(" (including inout ports) are on the right side.\n");
log("\n");
log(" -pause\n");
- log(" wait for the use to press enter to before returning\n");
+ log(" wait for the user to press enter to before returning\n");
log("\n");
log(" -enum\n");
log(" enumerate objects with internal ($-prefixed) names\n");
@@ -811,7 +829,7 @@ struct ShowPass : public Pass {
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
- Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "ilang" : "verilog"));
+ Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : "verilog"));
libs.push_back(lib);
}
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 20627d601..4ad0d2b25 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -211,7 +211,7 @@ struct SpliceWorker
std::vector<Wire*> mod_wires = module->wires();
for (auto wire : mod_wires)
- if ((!no_outputs && wire->port_output) || (do_wires && wire->name[0] == '\\')) {
+ if ((!no_outputs && wire->port_output) || (do_wires && wire->name.isPublic())) {
if (!design->selected(module, wire))
continue;
RTLIL::SigSpec sig = sigmap(wire);
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index fff8a0d3e..927cefca3 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc
new file mode 100644
index 000000000..13e1ee13c
--- /dev/null
+++ b/passes/cmds/sta.cc
@@ -0,0 +1,312 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * (C) 2019 Eddie Hung <eddie@fpgeh.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 "kernel/sigtools.h"
+#include "kernel/timinginfo.h"
+#include <deque>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct StaWorker
+{
+ Design *design;
+ Module *module;
+ SigMap sigmap;
+
+ struct t_data {
+ Cell* driver;
+ IdString dst_port, src_port;
+ vector<tuple<SigBit,int,IdString>> fanouts;
+ SigBit backtrack;
+ t_data() : driver(nullptr) {}
+ };
+ dict<SigBit, t_data> data;
+ std::deque<SigBit> queue;
+ struct t_endpoint {
+ Cell *sink;
+ IdString port;
+ int required;
+ t_endpoint() : sink(nullptr), required(0) {}
+ };
+ dict<SigBit, t_endpoint> endpoints;
+
+ int maxarrival;
+ SigBit maxbit;
+
+ pool<SigBit> driven;
+
+ StaWorker(RTLIL::Module *module) : design(module->design), module(module), sigmap(module), maxarrival(0)
+ {
+ TimingInfo timing;
+
+ for (auto cell : module->cells())
+ {
+ Module *inst_module = design->module(cell->type);
+ if (!inst_module) {
+ log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type));
+ continue;
+ }
+
+ if (!inst_module->get_blackbox_attribute()) {
+ log_warning("Cell type '%s' is not a black- nor white-box! Ignoring.\n", log_id(cell->type));
+ continue;
+ }
+
+ IdString derived_type = inst_module->derive(design, cell->parameters);
+ inst_module = design->module(derived_type);
+ log_assert(inst_module);
+
+ if (!timing.count(derived_type)) {
+ auto &t = timing.setup_module(inst_module);
+ if (t.has_inputs && t.comb.empty() && t.arrival.empty() && t.required.empty())
+ log_warning("Module '%s' has no timing arcs!\n", log_id(cell->type));
+ }
+
+ auto &t = timing.at(derived_type);
+ if (t.comb.empty() && t.arrival.empty() && t.required.empty())
+ continue;
+
+ pool<std::pair<SigBit,TimingInfo::NameBit>> src_bits, dst_bits;
+
+ for (auto &conn : cell->connections()) {
+ auto rhs = sigmap(conn.second);
+ for (auto i = 0; i < GetSize(rhs); i++) {
+ const auto &bit = rhs[i];
+ if (!bit.wire)
+ continue;
+ TimingInfo::NameBit namebit(conn.first,i);
+ if (cell->input(conn.first)) {
+ src_bits.insert(std::make_pair(bit,namebit));
+
+ auto it = t.required.find(namebit);
+ if (it == t.required.end())
+ continue;
+ auto r = endpoints.insert(bit);
+ if (r.second || r.first->second.required < it->second.first) {
+ r.first->second.sink = cell;
+ r.first->second.port = conn.first;
+ r.first->second.required = it->second.first;
+ }
+ }
+ if (cell->output(conn.first)) {
+ dst_bits.insert(std::make_pair(bit,namebit));
+ auto &d = data[bit];
+ d.driver = cell;
+ d.dst_port = conn.first;
+ driven.insert(bit);
+
+ auto it = t.arrival.find(namebit);
+ if (it == t.arrival.end())
+ continue;
+ const auto &s = it->second.second;
+ if (cell->hasPort(s.name)) {
+ auto s_bit = sigmap(cell->getPort(s.name)[s.offset]);
+ if (s_bit.wire)
+ data[s_bit].fanouts.emplace_back(bit,it->second.first,s.name);
+ }
+ }
+ }
+ }
+
+ for (const auto &s : src_bits)
+ for (const auto &d : dst_bits) {
+ auto it = t.comb.find(TimingInfo::BitBit(s.second,d.second));
+ if (it == t.comb.end())
+ continue;
+ data[s.first].fanouts.emplace_back(d.first,it->second,s.second.name);
+ }
+ }
+
+ for (auto port_name : module->ports) {
+ auto wire = module->wire(port_name);
+ if (wire->port_input) {
+ for (const auto &b : sigmap(wire)) {
+ queue.emplace_back(b);
+ driven.insert(b);
+ }
+ // All primary inputs to arrive at time zero
+ wire->set_intvec_attribute(ID::sta_arrival, std::vector<int>(GetSize(wire), 0));
+ }
+ if (wire->port_output)
+ for (const auto &b : sigmap(wire))
+ if (b.wire)
+ endpoints.insert(b);
+ }
+ }
+
+ void run()
+ {
+ while (!queue.empty()) {
+ auto b = queue.front();
+ queue.pop_front();
+ auto it = data.find(b);
+ if (it == data.end())
+ continue;
+ const auto& src_arrivals = b.wire->get_intvec_attribute(ID::sta_arrival);
+ log_assert(GetSize(src_arrivals) == GetSize(b.wire));
+ auto src_arrival = src_arrivals[b.offset];
+ for (const auto &d : it->second.fanouts) {
+ const auto &dst_bit = std::get<0>(d);
+ auto dst_arrivals = dst_bit.wire->get_intvec_attribute(ID::sta_arrival);
+ if (dst_arrivals.empty())
+ dst_arrivals = std::vector<int>(GetSize(dst_bit.wire), -1);
+ else
+ log_assert(GetSize(dst_arrivals) == GetSize(dst_bit.wire));
+ auto &dst_arrival = dst_arrivals[dst_bit.offset];
+ auto new_arrival = src_arrival + std::get<1>(d);
+ if (dst_arrival < new_arrival) {
+ auto dst_wire = dst_bit.wire;
+ dst_arrival = std::max(dst_arrival, new_arrival);
+ dst_wire->set_intvec_attribute(ID::sta_arrival, dst_arrivals);
+ queue.emplace_back(dst_bit);
+
+ data[dst_bit].backtrack = b;
+ data[dst_bit].src_port = std::get<2>(d);
+
+ auto it = endpoints.find(dst_bit);
+ if (it != endpoints.end())
+ new_arrival += it->second.required;
+ if (new_arrival > maxarrival && driven.count(b)) {
+ maxarrival = new_arrival;
+ maxbit = dst_bit;
+ }
+ }
+ }
+ }
+
+ auto b = maxbit;
+ if (b == SigBit()) {
+ log("No timing paths found.\n");
+ return;
+ }
+
+ log("Latest arrival time in '%s' is %d:\n", log_id(module), maxarrival);
+ auto it = endpoints.find(maxbit);
+ if (it != endpoints.end() && it->second.sink)
+ log(" %6d %s (%s.%s)\n", maxarrival, log_id(it->second.sink), log_id(it->second.sink->type), log_id(it->second.port));
+ else {
+ log(" %6d (%s)\n", maxarrival, b.wire->port_output ? "<primary output>" : "<unknown>");
+ if (!b.wire->port_output)
+ log_warning("Critical-path does not terminate in a recognised endpoint.\n");
+ }
+ auto jt = data.find(b);
+ while (jt != data.end()) {
+ int arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset];
+ if (jt->second.driver) {
+ log(" %s\n", log_signal(b));
+ log(" %6d %s (%s.%s->%s)\n", arrival, log_id(jt->second.driver), log_id(jt->second.driver->type), log_id(jt->second.src_port), log_id(jt->second.dst_port));
+ }
+ else if (b.wire->port_input)
+ log(" %6d %s (%s)\n", arrival, log_signal(b), "<primary input>");
+ else
+ log_abort();
+ b = jt->second.backtrack;
+ jt = data.find(b);
+ }
+
+ std::map<int, unsigned> arrival_histogram;
+ for (const auto &i : endpoints) {
+ const auto &b = i.first;
+ if (!driven.count(b))
+ continue;
+
+ if (!b.wire->attributes.count(ID::sta_arrival)) {
+ log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b));
+ continue;
+ }
+
+ auto arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset];
+ if (arrival < 0) {
+ log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b));
+ continue;
+ }
+ arrival += i.second.required;
+ arrival_histogram[arrival]++;
+ }
+ // Adapted from https://github.com/YosysHQ/nextpnr/blob/affb12cc27ebf409eade062c4c59bb98569d8147/common/timing.cc#L946-L969
+ if (arrival_histogram.size() > 0) {
+ unsigned num_bins = 20;
+ unsigned bar_width = 60;
+ auto min_arrival = arrival_histogram.begin()->first;
+ auto max_arrival = arrival_histogram.rbegin()->first;
+ auto bin_size = std::max<unsigned>(1, ceil((max_arrival - min_arrival + 1) / float(num_bins)));
+ std::vector<unsigned> bins(num_bins);
+ unsigned max_freq = 0;
+ for (const auto &i : arrival_histogram) {
+ auto &bin = bins[(i.first - min_arrival) / bin_size];
+ bin += i.second;
+ max_freq = std::max(max_freq, bin);
+ }
+ bar_width = std::min(bar_width, max_freq);
+
+ log("\n");
+ log("Arrival histogram:\n");
+ log(" legend: * represents %d endpoint(s)\n", max_freq / bar_width);
+ log(" + represents [1,%d) endpoint(s)\n", max_freq / bar_width);
+ for (int i = num_bins-1; i >= 0; --i)
+ log("(%6d, %6d] |%s%c\n", min_arrival + bin_size * (i + 1), min_arrival + bin_size * i,
+ std::string(bins[i] * bar_width / max_freq, '*').c_str(),
+ (bins[i] * bar_width) % max_freq > 0 ? '+' : ' ');
+ }
+ }
+};
+
+struct StaPass : public Pass {
+ StaPass() : Pass("sta", "perform static timing analysis") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" sta [options] [selection]\n");
+ log("\n");
+ log("This command performs static timing analysis on the design. (Only considers\n");
+ log("paths within a single module, so the design must be flattened.)\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing STA pass (static timing analysis).\n");
+
+ /*
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-TODO") {
+ continue;
+ }
+ break;
+ }
+ */
+
+ extra_args(args, 1, design);
+
+ for (Module *module : design->selected_modules())
+ {
+ if (module->has_processes_warn())
+ continue;
+
+ StaWorker worker(module);
+ worker.run();
+ }
+ }
+} StaPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index ed51fdc24..fffdda48e 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -81,7 +81,7 @@ struct statdata_t
for (auto wire : mod->selected_wires())
{
- if (wire->name[0] == '\\') {
+ if (wire->name.isPublic()) {
num_pub_wires++;
num_pub_wire_bits += wire->width;
}
@@ -117,10 +117,14 @@ struct statdata_t
}
else if (cell_type.in(ID($mux), ID($pmux)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)));
+ else if (cell_type == ID($bmux))
+ cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S)));
+ else if (cell_type == ID($demux))
+ cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S)));
else if (cell_type.in(
ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre),
ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce),
- ID($dlatch), ID($adlatch), ID($dlatchsr)))
+ ID($aldff), ID($aldffe), ID($dlatch), ID($adlatch), ID($dlatchsr)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q)));
}
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index 60689fc82..7a1f4a36b 100644
--- a/passes/cmds/tee.cc
+++ b/passes/cmds/tee.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc
index 30e76081e..1620c0bca 100644
--- a/passes/cmds/torder.cc
+++ b/passes/cmds/torder.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -83,7 +83,7 @@ struct TorderPass : public Pass {
if (!noautostop && yosys_celltypes.cell_known(cell->type)) {
if (conn.first.in(ID::Q, ID::CTRL_OUT, ID::RD_DATA))
continue;
- if (cell->type == ID($memrd) && conn.first == ID::DATA)
+ if (cell->type.in(ID($memrd), ID($memrd_v2)) && conn.first == ID::DATA)
continue;
}
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index 10742c370..400542776 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index 3d898a5ef..ea9b3f556 100644
--- a/passes/cmds/write_file.cc
+++ b/passes/cmds/write_file.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any