aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/cmds/bugpoint.cc28
-rw-r--r--passes/cmds/check.cc45
-rw-r--r--passes/cmds/connect.cc26
-rw-r--r--passes/cmds/connwrappers.cc22
-rw-r--r--passes/cmds/copy.cc4
-rw-r--r--passes/cmds/delete.cc43
-rw-r--r--passes/cmds/design.cc39
-rw-r--r--passes/cmds/rename.cc222
-rw-r--r--passes/cmds/scatter.cc28
-rw-r--r--passes/cmds/select.cc25
-rw-r--r--passes/cmds/setattr.cc36
-rw-r--r--passes/cmds/setundef.cc49
-rw-r--r--passes/cmds/show.cc94
-rw-r--r--passes/cmds/splice.cc32
-rw-r--r--passes/cmds/splitnets.cc3
-rw-r--r--passes/cmds/stat.cc46
-rw-r--r--passes/hierarchy/submod.cc45
-rw-r--r--passes/memory/memory_bram.cc48
-rw-r--r--passes/memory/memory_collect.cc9
-rw-r--r--passes/memory/memory_map.cc119
-rw-r--r--passes/memory/memory_unpack.cc13
-rw-r--r--passes/opt/opt_clean.cc6
-rw-r--r--passes/opt/opt_expr.cc181
-rw-r--r--passes/opt/opt_merge.cc4
-rw-r--r--passes/sat/Makefile.inc1
-rw-r--r--passes/sat/qbfsat.cc550
-rw-r--r--passes/techmap/Makefile.inc7
-rw-r--r--passes/techmap/abc.cc10
-rw-r--r--passes/techmap/abc9.cc4
-rw-r--r--passes/techmap/abc9_exe.cc12
-rw-r--r--passes/techmap/abc9_ops.cc3
-rw-r--r--passes/techmap/dffinit.cc8
-rw-r--r--passes/techmap/dfflibmap.cc54
-rw-r--r--passes/techmap/dffsr2dff.cc213
-rw-r--r--passes/techmap/extract.cc79
-rw-r--r--passes/techmap/hilomap.cc8
-rw-r--r--passes/techmap/techmap.cc2
-rw-r--r--passes/techmap/zinit.cc72
-rw-r--r--passes/tests/test_autotb.cc20
39 files changed, 1382 insertions, 828 deletions
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index ed427693d..ad6a07fa0 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -114,8 +114,8 @@ struct BugpointPass : public Pass {
return design;
RTLIL::Design *design_copy = new RTLIL::Design;
- for (auto &it : design->modules_)
- design_copy->add(it.second->clone());
+ for (auto module : design->modules())
+ design_copy->add(module->clone());
Pass::call(design_copy, "proc_clean -quiet");
Pass::call(design_copy, "clean -purge");
@@ -127,21 +127,21 @@ struct BugpointPass : public Pass {
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 *design_copy = new RTLIL::Design;
- for (auto &it : design->modules_)
- design_copy->add(it.second->clone());
+ for (auto module : design->modules())
+ design_copy->add(module->clone());
int index = 0;
if (modules)
{
- for (auto &it : design_copy->modules_)
+ for (auto module : design_copy->modules())
{
- if (it.second->get_blackbox_attribute())
+ if (module->get_blackbox_attribute())
continue;
if (index++ == seed)
{
- log("Trying to remove module %s.\n", it.first.c_str());
- design_copy->remove(it.second);
+ log("Trying to remove module %s.\n", module->name.c_str());
+ design_copy->remove(module);
return design_copy;
}
}
@@ -178,12 +178,12 @@ struct BugpointPass : public Pass {
if (mod->get_blackbox_attribute())
continue;
- for (auto &it : mod->cells_)
+ for (auto cell : mod->cells())
{
if (index++ == seed)
{
- log("Trying to remove cell %s.%s.\n", mod->name.c_str(), it.first.c_str());
- mod->remove(it.second);
+ log("Trying to remove cell %s.%s.\n", mod->name.c_str(), cell->name.c_str());
+ mod->remove(cell);
return design_copy;
}
}
@@ -285,7 +285,7 @@ struct BugpointPass : public Pass {
}
}
}
- return NULL;
+ return nullptr;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -433,8 +433,8 @@ struct BugpointPass : public Pass {
{
Pass::call(design, "design -reset");
crashing_design = clean_design(crashing_design, clean, /*do_delete=*/true);
- for (auto &it : crashing_design->modules_)
- design->add(it.second->clone());
+ for (auto module : crashing_design->modules())
+ design->add(module->clone());
delete crashing_design;
}
}
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index 63703b848..ba29e6f4b 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -98,49 +98,6 @@ struct CheckPass : public Pass {
log_header(design, "Executing CHECK pass (checking for obvious problems).\n");
- pool<IdString> fftypes;
- fftypes.insert(ID($sr));
- fftypes.insert(ID($ff));
- fftypes.insert(ID($dff));
- fftypes.insert(ID($dffe));
- fftypes.insert(ID($dffsr));
- fftypes.insert(ID($adff));
- fftypes.insert(ID($dlatch));
- fftypes.insert(ID($dlatchsr));
- fftypes.insert(ID($_DFFE_NN_));
- fftypes.insert(ID($_DFFE_NP_));
- fftypes.insert(ID($_DFFE_PN_));
- fftypes.insert(ID($_DFFE_PP_));
- fftypes.insert(ID($_DFFSR_NNN_));
- fftypes.insert(ID($_DFFSR_NNP_));
- fftypes.insert(ID($_DFFSR_NPN_));
- fftypes.insert(ID($_DFFSR_NPP_));
- fftypes.insert(ID($_DFFSR_PNN_));
- fftypes.insert(ID($_DFFSR_PNP_));
- fftypes.insert(ID($_DFFSR_PPN_));
- fftypes.insert(ID($_DFFSR_PPP_));
- fftypes.insert(ID($_DFF_NN0_));
- fftypes.insert(ID($_DFF_NN1_));
- fftypes.insert(ID($_DFF_NP0_));
- fftypes.insert(ID($_DFF_NP1_));
- fftypes.insert(ID($_DFF_N_));
- fftypes.insert(ID($_DFF_PN0_));
- fftypes.insert(ID($_DFF_PN1_));
- fftypes.insert(ID($_DFF_PP0_));
- fftypes.insert(ID($_DFF_PP1_));
- fftypes.insert(ID($_DFF_P_));
- fftypes.insert(ID($_DLATCHSR_NNN_));
- fftypes.insert(ID($_DLATCHSR_NNP_));
- fftypes.insert(ID($_DLATCHSR_NPN_));
- fftypes.insert(ID($_DLATCHSR_NPP_));
- fftypes.insert(ID($_DLATCHSR_PNN_));
- fftypes.insert(ID($_DLATCHSR_PNP_));
- fftypes.insert(ID($_DLATCHSR_PPN_));
- fftypes.insert(ID($_DLATCHSR_PPP_));
- fftypes.insert(ID($_DLATCH_N_));
- fftypes.insert(ID($_DLATCH_P_));
- fftypes.insert(ID($_FF_));
-
for (auto module : design->selected_whole_modules_warn())
{
if (module->has_processes_warn())
@@ -242,7 +199,7 @@ struct CheckPass : public Pass {
{
for (auto cell : module->cells())
{
- if (fftypes.count(cell->type) == 0)
+ if (RTLIL::builtin_ff_cell_types().count(cell->type) == 0)
continue;
for (auto bit : sigmap(cell->getPort(ID::Q)))
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index f93bada27..0b0868dfb 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -32,9 +32,9 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap &
RTLIL::Wire *dummy_wire = module->addWire(NEW_ID, sig.size());
- for (auto &it : module->cells_)
- for (auto &port : it.second->connections_)
- if (ct.cell_output(it.second->type, port.first))
+ for (auto cell : module->cells())
+ for (auto &port : cell->connections_)
+ if (ct.cell_output(cell->type, port.first))
sigmap(port.second).replace(sig, dummy_wire, &port.second);
for (auto &conn : module->connections_)
@@ -77,15 +77,13 @@ struct ConnectPass : public Pass {
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- RTLIL::Module *module = NULL;
- for (auto &it : design->modules_) {
- if (!design->selected(it.second))
- continue;
- if (module != NULL)
- log_cmd_error("Multiple modules selected: %s, %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.first));
- module = it.second;
+ RTLIL::Module *module = nullptr;
+ for (auto mod : design->selected_modules()) {
+ if (module != nullptr)
+ log_cmd_error("Multiple modules selected: %s, %s\n", log_id(module->name), log_id(mod->name));
+ module = mod;
}
- if (module == NULL)
+ if (module == nullptr)
log_cmd_error("No modules selected.\n");
if (!module->processes.empty())
log_cmd_error("Found processes in selected module.\n");
@@ -130,7 +128,7 @@ struct ConnectPass : public Pass {
std::vector<RTLIL::SigBit> lhs = it.first.to_sigbit_vector();
std::vector<RTLIL::SigBit> rhs = it.first.to_sigbit_vector();
for (size_t i = 0; i < lhs.size(); i++)
- if (rhs[i].wire != NULL)
+ if (rhs[i].wire != nullptr)
sigmap.add(lhs[i], rhs[i]);
}
@@ -172,14 +170,14 @@ struct ConnectPass : public Pass {
if (flag_nounset)
log_cmd_error("Can't use -port together with -nounset.\n");
- if (module->cells_.count(RTLIL::escape_id(port_cell)) == 0)
+ if (module->cell(RTLIL::escape_id(port_cell)) == nullptr)
log_cmd_error("Can't find cell %s.\n", port_cell.c_str());
RTLIL::SigSpec sig;
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->cells_.at(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
+ module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
}
else
log_cmd_error("Expected -set, -unset, or -port.\n");
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index 5a15cbbaf..6ae7c9304 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -65,15 +65,13 @@ struct ConnwrappersWorker
decls[key] = decl;
}
- void work(RTLIL::Design *design, RTLIL::Module *module)
+ void work(RTLIL::Module *module)
{
std::map<RTLIL::SigBit, std::pair<bool, RTLIL::SigSpec>> extend_map;
SigMap sigmap(module);
- for (auto &it : module->cells_)
+ for (auto cell : module->cells())
{
- RTLIL::Cell *cell = it.second;
-
if (!decl_celltypes.count(cell->type))
continue;
@@ -105,13 +103,8 @@ struct ConnwrappersWorker
}
}
- for (auto &it : module->cells_)
+ for (auto cell : module->selected_cells())
{
- RTLIL::Cell *cell = it.second;
-
- if (!design->selected(module, cell))
- continue;
-
for (auto &conn : cell->connections_)
{
std::vector<RTLIL::SigBit> sigbits = sigmap(conn.second).to_sigbit_vector();
@@ -141,8 +134,8 @@ struct ConnwrappersWorker
}
if (old_sig.size())
- log("Connected extended bits of %s.%s:%s: %s -> %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name),
- RTLIL::id2cstr(conn.first), log_signal(old_sig), log_signal(conn.second));
+ log("Connected extended bits of %s.%s:%s: %s -> %s\n", log_id(module->name), log_id(cell->name),
+ log_id(conn.first), log_signal(old_sig), log_signal(conn.second));
}
}
}
@@ -200,9 +193,8 @@ struct ConnwrappersPass : public Pass {
log_header(design, "Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n");
- for (auto &mod_it : design->modules_)
- if (design->selected(mod_it.second))
- worker.work(design, mod_it.second);
+ for (auto module : design->selected_modules())
+ worker.work(module);
}
} ConnwrappersPass;
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index acd2dba52..99f1f69cf 100644
--- a/passes/cmds/copy.cc
+++ b/passes/cmds/copy.cc
@@ -44,10 +44,10 @@ struct CopyPass : public Pass {
std::string src_name = RTLIL::escape_id(args[1]);
std::string trg_name = RTLIL::escape_id(args[2]);
- if (design->modules_.count(src_name) == 0)
+ if (design->module(src_name) == nullptr)
log_cmd_error("Can't find source module %s.\n", src_name.c_str());
- if (design->modules_.count(trg_name) != 0)
+ if (design->module(trg_name) != nullptr)
log_cmd_error("Target module name %s already exists.\n", trg_name.c_str());
RTLIL::Module *new_mod = design->module(src_name)->clone();
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index 125bc96ca..b124e3b0f 100644
--- a/passes/cmds/delete.cc
+++ b/passes/cmds/delete.cc
@@ -65,27 +65,24 @@ struct DeletePass : public Pass {
}
extra_args(args, argidx, design);
- std::vector<RTLIL::IdString> delete_mods;
-
- for (auto &mod_it : design->modules_)
+ std::vector<RTLIL::Module *> delete_mods;
+ for (auto module : design->modules())
{
- if (design->selected_whole_module(mod_it.first) && !flag_input && !flag_output) {
- delete_mods.push_back(mod_it.first);
+ if (design->selected_whole_module(module->name) && !flag_input && !flag_output) {
+ delete_mods.push_back(module);
continue;
}
- if (!design->selected_module(mod_it.first))
+ if (!design->selected_module(module->name))
continue;
- RTLIL::Module *module = mod_it.second;
-
if (flag_input || flag_output) {
- for (auto &it : module->wires_)
- if (design->selected(module, it.second)) {
+ for (auto wire : module->wires())
+ if (design->selected(module, wire)) {
if (flag_input)
- it.second->port_input = false;
+ wire->port_input = false;
if (flag_output)
- it.second->port_output = false;
+ wire->port_output = false;
}
module->fixup_ports();
continue;
@@ -96,20 +93,19 @@ struct DeletePass : public Pass {
pool<RTLIL::IdString> delete_procs;
pool<RTLIL::IdString> delete_mems;
- for (auto &it : module->wires_)
- if (design->selected(module, it.second))
- delete_wires.insert(it.second);
+ for (auto wire : module->selected_wires())
+ delete_wires.insert(wire);
for (auto &it : module->memories)
if (design->selected(module, it.second))
delete_mems.insert(it.first);
- for (auto &it : module->cells_) {
- if (design->selected(module, it.second))
- delete_cells.insert(it.second);
- if (it.second->type.in(ID($memrd), ID($memwr)) &&
- delete_mems.count(it.second->parameters.at(ID::MEMID).decode_string()) != 0)
- delete_cells.insert(it.second);
+ for (auto cell : module->cells()) {
+ if (design->selected(module, cell))
+ delete_cells.insert(cell);
+ if (cell->type.in(ID($memrd), ID($memwr)) &&
+ delete_mems.count(cell->parameters.at(ID::MEMID).decode_string()) != 0)
+ delete_cells.insert(cell);
}
for (auto &it : module->processes)
@@ -134,9 +130,8 @@ struct DeletePass : public Pass {
module->fixup_ports();
}
- for (auto &it : delete_mods) {
- delete design->modules_.at(it);
- design->modules_.erase(it);
+ for (auto mod : delete_mods) {
+ design->remove(mod);
}
}
} DeletePass;
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index 4fd43329f..cfe97067d 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -60,6 +60,11 @@ struct DesignPass : public Pass {
log("Push the current design to the stack and then clear the current design.\n");
log("\n");
log("\n");
+ log(" design -push-copy\n");
+ log("\n");
+ log("Push the current design to the stack without clearing the current design.\n");
+ log("\n");
+ log("\n");
log(" design -pop\n");
log("\n");
log("Reset the current design and pop the last design from the stack.\n");
@@ -94,6 +99,11 @@ struct DesignPass : public Pass {
log("The Verilog front-end remembers defined macros and top-level declarations\n");
log("between calls to 'read_verilog'. This command resets this memory.\n");
log("\n");
+ log(" design -delete <name>\n");
+ log("\n");
+ log("Delete the design previously saved under the given name.\n");
+ log("\n");
+
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
@@ -101,10 +111,11 @@ struct DesignPass : public Pass {
bool reset_mode = false;
bool reset_vlog_mode = false;
bool push_mode = false;
+ bool push_copy_mode = false;
bool pop_mode = false;
bool import_mode = false;
RTLIL::Design *copy_from_design = NULL, *copy_to_design = NULL;
- std::string save_name, load_name, as_name;
+ std::string save_name, load_name, as_name, delete_name;
std::vector<RTLIL::Module*> copy_src_modules;
size_t argidx;
@@ -126,6 +137,11 @@ struct DesignPass : public Pass {
push_mode = true;
continue;
}
+ if (!got_mode && args[argidx] == "-push-copy") {
+ got_mode = true;
+ push_copy_mode = true;
+ continue;
+ }
if (!got_mode && args[argidx] == "-pop") {
got_mode = true;
pop_mode = true;
@@ -179,6 +195,13 @@ struct DesignPass : public Pass {
as_name = args[++argidx];
continue;
}
+ if (!got_mode && args[argidx] == "-delete" && argidx+1 < args.size()) {
+ got_mode = true;
+ delete_name = args[++argidx];
+ if (saved_designs.count(delete_name) == 0)
+ log_cmd_error("No saved design '%s' found!\n", delete_name.c_str());
+ continue;
+ }
break;
}
@@ -307,7 +330,7 @@ struct DesignPass : public Pass {
}
}
- if (!save_name.empty() || push_mode)
+ if (!save_name.empty() || push_mode || push_copy_mode)
{
RTLIL::Design *design_copy = new RTLIL::Design;
@@ -321,7 +344,7 @@ struct DesignPass : public Pass {
if (saved_designs.count(save_name))
delete saved_designs.at(save_name);
- if (push_mode)
+ if (push_mode || push_copy_mode)
pushed_designs.push_back(design_copy);
else
saved_designs[save_name] = design_copy;
@@ -329,7 +352,7 @@ struct DesignPass : public Pass {
if (reset_mode || !load_name.empty() || push_mode || pop_mode)
{
- for (auto mod : design->modules())
+ for (auto mod : design->modules().to_vector())
design->remove(mod);
design->selection_stack.clear();
@@ -368,6 +391,14 @@ struct DesignPass : public Pass {
pushed_designs.pop_back();
}
}
+
+ if (!delete_name.empty())
+ {
+ auto it = saved_designs.find(delete_name);
+ log_assert(it != saved_designs.end());
+ delete it->second;
+ saved_designs.erase(it);
+ }
}
} DesignPass;
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 9b1830b7b..7d6d84d42 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -32,27 +32,27 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
if (module->count_id(to_name))
log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name.c_str(), module->name.c_str());
- for (auto &it : module->wires_)
- if (it.first == from_name) {
- Wire *w = it.second;
- log("Renaming wire %s to %s in module %s.\n", log_id(w), log_id(to_name), log_id(module));
- module->rename(w, to_name);
- if (w->port_id || flag_output) {
- if (flag_output)
- w->port_output = true;
- module->fixup_ports();
- }
- return;
- }
+ RTLIL::Wire *wire_to_rename = module->wire(from_name);
+ RTLIL::Cell *cell_to_rename = module->cell(from_name);
- for (auto &it : module->cells_)
- if (it.first == from_name) {
+ if (wire_to_rename != nullptr) {
+ log("Renaming wire %s to %s in module %s.\n", log_id(wire_to_rename), log_id(to_name), log_id(module));
+ module->rename(wire_to_rename, to_name);
+ if (wire_to_rename->port_id || flag_output) {
if (flag_output)
- log_cmd_error("Called with -output but the specified object is a cell.\n");
- log("Renaming cell %s to %s in module %s.\n", log_id(it.second), log_id(to_name), log_id(module));
- module->rename(it.second, to_name);
- return;
+ wire_to_rename->port_output = true;
+ module->fixup_ports();
}
+ return;
+ }
+
+ if (cell_to_rename != nullptr) {
+ if (flag_output)
+ log_cmd_error("Called with -output but the specified object is a cell.\n");
+ log("Renaming cell %s to %s in module %s.\n", log_id(cell_to_rename), log_id(to_name), log_id(module));
+ module->rename(cell_to_rename, to_name);
+ return;
+ }
log_cmd_error("Object `%s' not found!\n", from_name.c_str());
}
@@ -66,26 +66,26 @@ static std::string derive_name_from_src(const std::string &src, int counter)
return stringf("\\%s$%d", src_base.c_str(), counter);
}
-static IdString derive_name_from_wire(const RTLIL::Cell &cell)
+static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell)
{
// Find output
const SigSpec *output = nullptr;
int num_outputs = 0;
- for (auto &connection : cell.connections()) {
- if (cell.output(connection.first)) {
+ for (auto &connection : cell->connections()) {
+ if (cell->output(connection.first)) {
output = &connection.second;
num_outputs++;
}
}
if (num_outputs != 1) // Skip cells thad drive multiple outputs
- return cell.name;
+ return cell->name;
std::string name = "";
for (auto &chunk : output->chunks()) {
// Skip cells that drive privately named wires
if (!chunk.wire || chunk.wire->name.str()[0] == '$')
- return cell.name;
+ return cell->name;
if (name != "")
name += "$";
@@ -99,7 +99,7 @@ static IdString derive_name_from_wire(const RTLIL::Cell &cell)
}
}
- return name + cell.type.str();
+ return name + cell->type.str();
}
struct RenamePass : public Pass {
@@ -210,30 +210,25 @@ struct RenamePass : public Pass {
{
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
+ for (auto module : design->selected_modules())
{
int counter = 0;
+ dict<RTLIL::Wire *, IdString> new_wire_names;
+ dict<RTLIL::Cell *, IdString> new_cell_names;
+
+ for (auto wire : module->selected_wires())
+ if (wire->name[0] == '$')
+ new_wire_names.emplace(wire, derive_name_from_src(wire->get_src_attribute(), counter++));
+
+ for (auto cell : module->selected_cells())
+ if (cell->name[0] == '$')
+ new_cell_names.emplace(cell, derive_name_from_src(cell->get_src_attribute(), counter++));
- RTLIL::Module *module = mod.second;
- if (!design->selected(module))
- continue;
-
- dict<RTLIL::IdString, RTLIL::Wire*> new_wires;
- for (auto &it : module->wires_) {
- if (it.first[0] == '$' && design->selected(module, it.second))
- it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
- new_wires[it.second->name] = it.second;
- }
- module->wires_.swap(new_wires);
- module->fixup_ports();
-
- dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
- for (auto &it : module->cells_) {
- if (it.first[0] == '$' && design->selected(module, it.second))
- it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
- new_cells[it.second->name] = it.second;
- }
- module->cells_.swap(new_cells);
+ for (auto &it : new_wire_names)
+ module->rename(it.first, it.second);
+
+ for (auto &it : new_cell_names)
+ module->rename(it.first, it.second);
}
}
else
@@ -241,19 +236,13 @@ struct RenamePass : public Pass {
{
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
- {
- RTLIL::Module *module = mod.second;
- if (!design->selected(module))
- continue;
-
- dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
- for (auto &it : module->cells_) {
- if (it.first[0] == '$' && design->selected(module, it.second))
- it.second->name = derive_name_from_wire(*it.second);
- new_cells[it.second->name] = it.second;
- }
- module->cells_.swap(new_cells);
+ for (auto module : design->selected_modules()) {
+ dict<RTLIL::Cell *, IdString> new_cell_names;
+ for (auto cell : module->selected_cells())
+ if (cell->name[0] == '$')
+ new_cell_names[cell] = derive_name_from_cell_output_wire(cell);
+ for (auto &it : new_cell_names)
+ module->rename(it.first, it.second);
}
}
else
@@ -261,32 +250,33 @@ struct RenamePass : public Pass {
{
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
+ for (auto module : design->selected_modules())
{
int counter = 0;
+ dict<RTLIL::Wire *, IdString> new_wire_names;
+ dict<RTLIL::Cell *, IdString> new_cell_names;
+
+ for (auto wire : module->selected_wires())
+ if (wire->name[0] == '$') {
+ RTLIL::IdString buf;
+ do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
+ while (module->wire(buf) != nullptr);
+ new_wire_names[wire] = buf;
+ }
+
+ for (auto cell : module->selected_cells())
+ if (cell->name[0] == '$') {
+ RTLIL::IdString buf;
+ do buf = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
+ while (module->cell(buf) != nullptr);
+ new_cell_names[cell] = buf;
+ }
- RTLIL::Module *module = mod.second;
- if (!design->selected(module))
- continue;
-
- dict<RTLIL::IdString, RTLIL::Wire*> new_wires;
- for (auto &it : module->wires_) {
- if (it.first[0] == '$' && design->selected(module, it.second))
- do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
- while (module->count_id(it.second->name) > 0);
- new_wires[it.second->name] = it.second;
- }
- module->wires_.swap(new_wires);
- module->fixup_ports();
-
- dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
- for (auto &it : module->cells_) {
- if (it.first[0] == '$' && design->selected(module, it.second))
- do it.second->name = stringf("\\%s%d%s", pattern_prefix.c_str(), counter++, pattern_suffix.c_str());
- while (module->count_id(it.second->name) > 0);
- new_cells[it.second->name] = it.second;
- }
- module->cells_.swap(new_cells);
+ for (auto &it : new_wire_names)
+ module->rename(it.first, it.second);
+
+ for (auto &it : new_cell_names)
+ module->rename(it.first, it.second);
}
}
else
@@ -294,30 +284,24 @@ struct RenamePass : public Pass {
{
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
+ for (auto module : design->selected_modules())
{
- RTLIL::Module *module = mod.second;
- if (!design->selected(module))
- continue;
-
- dict<RTLIL::IdString, RTLIL::Wire*> new_wires;
- for (auto &it : module->wires_) {
- if (design->selected(module, it.second))
- if (it.first[0] == '\\' && it.second->port_id == 0)
- it.second->name = NEW_ID;
- new_wires[it.second->name] = it.second;
- }
- module->wires_.swap(new_wires);
- module->fixup_ports();
-
- dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
- for (auto &it : module->cells_) {
- if (design->selected(module, it.second))
- if (it.first[0] == '\\')
- it.second->name = NEW_ID;
- new_cells[it.second->name] = it.second;
- }
- module->cells_.swap(new_cells);
+ dict<RTLIL::Wire *, IdString> new_wire_names;
+ dict<RTLIL::Cell *, IdString> new_cell_names;
+
+ for (auto wire : module->selected_wires())
+ if (wire->name[0] == '\\' && wire->port_id == 0)
+ new_wire_names[wire] = NEW_ID;
+
+ for (auto cell : module->selected_cells())
+ if (cell->name[0] == '\\')
+ new_cell_names[cell] = NEW_ID;
+
+ for (auto &it : new_wire_names)
+ module->rename(it.first, it.second);
+
+ for (auto &it : new_cell_names)
+ module->rename(it.first, it.second);
}
}
else
@@ -329,7 +313,7 @@ struct RenamePass : public Pass {
IdString new_name = RTLIL::escape_id(args[argidx]);
RTLIL::Module *module = design->top_module();
- if (module == NULL)
+ if (module == nullptr)
log_cmd_error("No top module found!\n");
log("Renaming module %s to %s.\n", log_id(module), log_id(new_name));
@@ -345,27 +329,27 @@ struct RenamePass : public Pass {
if (!design->selected_active_module.empty())
{
- if (design->modules_.count(design->selected_active_module) > 0)
- rename_in_module(design->modules_.at(design->selected_active_module), from_name, to_name, flag_output);
+ if (design->module(design->selected_active_module) != nullptr)
+ rename_in_module(design->module(design->selected_active_module), from_name, to_name, flag_output);
}
else
{
if (flag_output)
log_cmd_error("Mode -output requires that there is an active module selected.\n");
- for (auto &mod : design->modules_) {
- if (mod.first == from_name || RTLIL::unescape_id(mod.first) == from_name) {
- to_name = RTLIL::escape_id(to_name);
- log("Renaming module %s to %s.\n", mod.first.c_str(), to_name.c_str());
- RTLIL::Module *module = mod.second;
- design->modules_.erase(module->name);
- module->name = to_name;
- design->modules_[module->name] = module;
- goto rename_ok;
+
+ RTLIL::Module *module_to_rename = nullptr;
+ for (auto module : design->modules())
+ if (module->name == from_name || RTLIL::unescape_id(module->name) == from_name) {
+ module_to_rename = module;
+ break;
}
- }
- log_cmd_error("Object `%s' not found!\n", from_name.c_str());
- rename_ok:;
+ if (module_to_rename != nullptr) {
+ to_name = RTLIL::escape_id(to_name);
+ log("Renaming module %s to %s.\n", module_to_rename->name.c_str(), to_name.c_str());
+ design->rename(module_to_rename, to_name);
+ } else
+ log_cmd_error("Object `%s' not found!\n", from_name.c_str());
}
}
}
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index 7123ba9fb..a5ef95f02 100644
--- a/passes/cmds/scatter.cc
+++ b/passes/cmds/scatter.cc
@@ -46,25 +46,19 @@ struct ScatterPass : public Pass {
CellTypes ct(design);
extra_args(args, 1, design);
- for (auto &mod_it : design->modules_)
+ for (auto module : design->selected_modules())
{
- if (!design->selected(mod_it.second))
- continue;
-
- for (auto &c : mod_it.second->cells_)
- for (auto &p : c.second->connections_)
- {
- RTLIL::Wire *wire = mod_it.second->addWire(NEW_ID, p.second.size());
-
- if (ct.cell_output(c.second->type, p.first)) {
- RTLIL::SigSig sigsig(p.second, wire);
- mod_it.second->connect(sigsig);
- } else {
- RTLIL::SigSig sigsig(wire, p.second);
- mod_it.second->connect(sigsig);
+ for (auto cell : module->cells()) {
+ dict<RTLIL::IdString, RTLIL::SigSig> new_connections;
+ for (auto conn : cell->connections())
+ new_connections.emplace(conn.first, RTLIL::SigSig(conn.second, module->addWire(NEW_ID, GetSize(conn.second))));
+ for (auto &it : new_connections) {
+ if (ct.cell_output(cell->type, it.first))
+ module->connect(RTLIL::SigSig(it.second.first, it.second.second));
+ else
+ module->connect(RTLIL::SigSig(it.second.second, it.second.first));
+ cell->setPort(it.first, it.second.second);
}
-
- p.second = wire;
}
}
}
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index b64b077e4..c04ff438a 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -1007,6 +1007,7 @@ struct SelectPass : public Pass {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" select [ -add | -del | -set <name> ] {-read <filename> | <selection>}\n");
+ log(" select [ -unset <name> ]\n");
log(" select [ <assert_option> ] {-read <filename> | <selection>}\n");
log(" select [ -list | -write <filename> | -count | -clear ]\n");
log(" select -module <modname>\n");
@@ -1029,6 +1030,10 @@ struct SelectPass : public Pass {
log(" under the given name (see @<name> below). to save the current selection,\n");
log(" use \"select -set <name> %%\"\n");
log("\n");
+ log(" -unset <name>\n");
+ log(" do not modify the current selection. instead remove a previously saved\n");
+ log(" selection under the given name (see @<name> below).");
+ log("\n");
log(" -assert-none\n");
log(" do not modify the current selection. instead assert that the given\n");
log(" selection is empty. i.e. produce an error if any object matching the\n");
@@ -1238,7 +1243,7 @@ struct SelectPass : public Pass {
int assert_max = -1;
int assert_min = -1;
std::string write_file, read_file;
- std::string set_name, sel_str;
+ std::string set_name, unset_name, sel_str;
work_stack.clear();
@@ -1310,6 +1315,10 @@ struct SelectPass : public Pass {
set_name = RTLIL::escape_id(args[++argidx]);
continue;
}
+ if (arg == "-unset" && argidx+1 < args.size()) {
+ unset_name = RTLIL::escape_id(args[++argidx]);
+ continue;
+ }
if (arg.size() > 0 && arg[0] == '-')
log_cmd_error("Unknown option %s.\n", arg.c_str());
bool disable_empty_warning = count_mode || assert_none || assert_any || (assert_count != -1) || (assert_max != -1) || (assert_min != -1);
@@ -1358,8 +1367,11 @@ struct SelectPass : public Pass {
if ((list_mode || !write_file.empty() || count_mode) && (add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
log_cmd_error("Options -list, -write and -count can not be combined with -add, -del, -assert-none, -assert-any, assert-count, -assert-max, or -assert-min.\n");
- if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
- log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n");
+ if (!set_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || !unset_name.empty() || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
+ log_cmd_error("Option -set can not be combined with -list, -write, -count, -add, -del, -unset, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n");
+
+ if (!unset_name.empty() && (list_mode || !write_file.empty() || count_mode || add_mode || !set_name.empty() || del_mode || assert_none || assert_any || assert_count >= 0 || assert_max >= 0 || assert_min >= 0))
+ log_cmd_error("Option -unset can not be combined with -list, -write, -count, -add, -del, -set, -assert-none, -assert-any, -assert-count, -assert-max, or -assert-min.\n");
if (work_stack.size() == 0 && got_module) {
RTLIL::Selection sel;
@@ -1527,6 +1539,13 @@ struct SelectPass : public Pass {
return;
}
+ if (!unset_name.empty())
+ {
+ if (!design->selection_vars.erase(unset_name))
+ log_error("Selection '%s' does not exist!\n", unset_name.c_str());
+ return;
+ }
+
if (work_stack.size() == 0) {
RTLIL::Selection &sel = design->selection_stack.back();
if (sel.full_selection)
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 08abb94cb..515f5a4ef 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -38,7 +38,7 @@ struct setunset_t
value = RTLIL::Const(set_value.substr(1, GetSize(set_value)-2));
} else {
RTLIL::SigSpec sig_value;
- if (!RTLIL::SigSpec::parse(sig_value, NULL, set_value))
+ if (!RTLIL::SigSpec::parse(sig_value, nullptr, set_value))
log_cmd_error("Can't decode value '%s'!\n", set_value.c_str());
value = sig_value.as_const();
}
@@ -96,10 +96,8 @@ struct SetattrPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
+ for (auto module : design->modules())
{
- RTLIL::Module *module = mod.second;
-
if (flag_mod) {
if (design->selected_whole_module(module->name))
do_setunset(module->attributes, setunset_list);
@@ -109,17 +107,17 @@ struct SetattrPass : public Pass {
if (!design->selected(module))
continue;
- for (auto &it : module->wires_)
- if (design->selected(module, it.second))
- do_setunset(it.second->attributes, setunset_list);
+ for (auto wire : module->wires())
+ if (design->selected(module, wire))
+ do_setunset(wire->attributes, setunset_list);
for (auto &it : module->memories)
if (design->selected(module, it.second))
do_setunset(it.second->attributes, setunset_list);
- for (auto &it : module->cells_)
- if (design->selected(module, it.second))
- do_setunset(it.second->attributes, setunset_list);
+ for (auto cell : module->cells())
+ if (design->selected(module, cell))
+ do_setunset(cell->attributes, setunset_list);
for (auto &it : module->processes)
if (design->selected(module, it.second))
@@ -208,19 +206,13 @@ struct SetparamPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &mod : design->modules_)
+ for (auto module : design->selected_modules())
{
- RTLIL::Module *module = mod.second;
-
- if (!design->selected(module))
- continue;
-
- for (auto &it : module->cells_)
- if (design->selected(module, it.second)) {
- if (!new_cell_type.empty())
- it.second->type = new_cell_type;
- do_setunset(it.second->parameters, setunset_list);
- }
+ for (auto cell : module->selected_cells()) {
+ if (!new_cell_type.empty())
+ cell->type = new_cell_type;
+ do_setunset(cell->parameters, setunset_list);
+ }
}
}
} SetparamPass;
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 5afd40923..8d973869e 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -149,7 +149,7 @@ struct SetundefPass : public Pass {
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- bool got_value = false;
+ int got_value = 0;
bool undriven_mode = false;
bool expose_mode = false;
bool init_mode = false;
@@ -170,31 +170,31 @@ struct SetundefPass : public Pass {
continue;
}
if (args[argidx] == "-zero") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ZERO;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-one") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ONE;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-anyseq") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ANYSEQ;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-anyconst") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_ANYCONST;
worker.next_bit_state = 0;
continue;
}
if (args[argidx] == "-undef") {
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_UNDEF;
worker.next_bit_state = 0;
continue;
@@ -207,8 +207,8 @@ struct SetundefPass : public Pass {
params_mode = true;
continue;
}
- if (args[argidx] == "-random" && !got_value && argidx+1 < args.size()) {
- got_value = true;
+ if (args[argidx] == "-random" && argidx+1 < args.size()) {
+ got_value++;
worker.next_bit_mode = MODE_RANDOM;
worker.next_bit_state = atoi(args[++argidx].c_str()) + 1;
for (int i = 0; i < 10; i++)
@@ -221,7 +221,7 @@ struct SetundefPass : public Pass {
if (!got_value && expose_mode) {
log("Using default as -undef with -expose.\n");
- got_value = true;
+ got_value++;
worker.next_bit_mode = MODE_UNDEF;
worker.next_bit_state = 0;
}
@@ -229,7 +229,9 @@ struct SetundefPass : public Pass {
if (expose_mode && !undriven_mode)
log_cmd_error("Option -expose must be used with option -undriven.\n");
if (!got_value)
- log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, or -random <seed> must be specified.\n");
+ log_cmd_error("One of the options -zero, -one, -anyseq, -anyconst, -random <seed>, or -expose must be specified.\n");
+ else if (got_value > 1)
+ log_cmd_error("Only one of the options -zero, -one, -anyseq, -anyconst, or -random <seed> can be specified.\n");
if (init_mode && (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST))
log_cmd_error("The options -init and -anyseq / -anyconst are exclusive.\n");
@@ -359,34 +361,9 @@ struct SetundefPass : public Pass {
pool<SigBit> ffbits;
pool<Wire*> initwires;
- pool<IdString> fftypes;
- fftypes.insert(ID($dff));
- fftypes.insert(ID($dffe));
- fftypes.insert(ID($dffsr));
- fftypes.insert(ID($adff));
-
- std::vector<char> list_np = {'N', 'P'}, list_01 = {'0', '1'};
-
- for (auto c1 : list_np)
- fftypes.insert(stringf("$_DFF_%c_", c1));
-
- for (auto c1 : list_np)
- for (auto c2 : list_np)
- fftypes.insert(stringf("$_DFFE_%c%c_", c1, c2));
-
- for (auto c1 : list_np)
- for (auto c2 : list_np)
- for (auto c3 : list_01)
- fftypes.insert(stringf("$_DFF_%c%c%c_", c1, c2, c3));
-
- for (auto c1 : list_np)
- for (auto c2 : list_np)
- for (auto c3 : list_np)
- fftypes.insert(stringf("$_DFFSR_%c%c%c_", c1, c2, c3));
-
for (auto cell : module->cells())
{
- if (!fftypes.count(cell->type))
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
continue;
for (auto bit : sigmap(cell->getPort(ID::Q)))
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index c0e07b6e1..155ed0fcd 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -41,8 +41,6 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-using RTLIL::id2cstr;
-
#undef CLUSTER_CELLS_AND_PORTBOXES
struct ShowWorker
@@ -101,7 +99,7 @@ struct ShowWorker
{
sig.sort_and_unify();
for (auto &c : sig.chunks()) {
- if (c.wire != NULL)
+ if (c.wire != nullptr)
for (auto &s : color_selections)
if (s.second.selected_members.count(module->name) > 0 && s.second.selected_members.at(module->name).count(c.wire->name) > 0)
return stringf("color=\"%s\"", s.first.c_str());
@@ -218,7 +216,7 @@ struct ShowWorker
if (sig.is_chunk()) {
const RTLIL::SigChunk &c = sig.as_chunk();
- if (c.wire != NULL && design->selected_member(module->name, c.wire->name)) {
+ if (c.wire != nullptr && design->selected_member(module->name, c.wire->name)) {
if (!range_check || c.wire->width == c.width)
return stringf("n%d", id2num(c.wire->name));
} else {
@@ -230,7 +228,7 @@ struct ShowWorker
return std::string();
}
- std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = NULL)
+ std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = nullptr)
{
std::string code;
std::string net = gen_signode_simple(sig);
@@ -287,7 +285,7 @@ struct ShowWorker
else
code += stringf("x%d:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", idx, port.c_str(), nextColor(sig).c_str(), widthLabel(sig.size()).c_str());
}
- if (node != NULL)
+ if (node != nullptr)
*node = stringf("x%d", idx);
}
else
@@ -300,7 +298,7 @@ struct ShowWorker
net_conn_map[net].bits = sig.size();
net_conn_map[net].color = nextColor(sig, net_conn_map[net].color);
}
- if (node != NULL)
+ if (node != nullptr)
*node = net;
}
return code;
@@ -366,22 +364,20 @@ struct ShowWorker
std::set<std::string> all_sources, all_sinks;
std::map<std::string, std::string> wires_on_demand;
- for (auto &it : module->wires_) {
- if (!design->selected_member(module->name, it.first))
- continue;
+ for (auto wire : module->selected_wires()) {
const char *shape = "diamond";
- if (it.second->port_input || it.second->port_output)
+ if (wire->port_input || wire->port_output)
shape = "octagon";
- if (it.first[0] == '\\') {
+ if (wire->name[0] == '\\') {
fprintf(f, "n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n",
- id2num(it.first), shape, findLabel(it.first.str()),
- nextColor(RTLIL::SigSpec(it.second), "color=\"black\"").c_str());
- if (it.second->port_input)
- all_sources.insert(stringf("n%d", id2num(it.first)));
- else if (it.second->port_output)
- all_sinks.insert(stringf("n%d", id2num(it.first)));
+ id2num(wire->name), shape, findLabel(wire->name.str()),
+ nextColor(RTLIL::SigSpec(wire), "color=\"black\"").c_str());
+ if (wire->port_input)
+ all_sources.insert(stringf("n%d", id2num(wire->name)));
+ else if (wire->port_output)
+ all_sinks.insert(stringf("n%d", id2num(wire->name)));
} else {
- wires_on_demand[stringf("n%d", id2num(it.first))] = it.first.str();
+ wires_on_demand[stringf("n%d", id2num(wire->name))] = wire->name.str();
}
}
@@ -398,15 +394,12 @@ struct ShowWorker
fprintf(f, "}\n");
}
- for (auto &it : module->cells_)
+ for (auto cell : module->selected_cells())
{
- if (!design->selected_member(module->name, it.first))
- continue;
-
std::vector<RTLIL::IdString> in_ports, out_ports;
- for (auto &conn : it.second->connections()) {
- if (!ct.cell_output(it.second->type, conn.first))
+ for (auto &conn : cell->connections()) {
+ if (!ct.cell_output(cell->type, conn.first))
in_ports.push_back(conn.first);
else
out_ports.push_back(conn.first);
@@ -419,12 +412,12 @@ struct ShowWorker
for (auto &p : in_ports)
label_string += stringf("<p%d> %s%s|", id2num(p), escape(p.str()),
- genSignedLabels && it.second->hasParam(p.str() + "_SIGNED") &&
- it.second->getParam(p.str() + "_SIGNED").as_bool() ? "*" : "");
+ genSignedLabels && cell->hasParam(p.str() + "_SIGNED") &&
+ cell->getParam(p.str() + "_SIGNED").as_bool() ? "*" : "");
if (label_string[label_string.size()-1] == '|')
label_string = label_string.substr(0, label_string.size()-1);
- label_string += stringf("}|%s\\n%s|{", findLabel(it.first.str()), escape(it.second->type.str()));
+ label_string += stringf("}|%s\\n%s|{", findLabel(cell->name.str()), escape(cell->type.str()));
for (auto &p : out_ports)
label_string += stringf("<p%d> %s|", id2num(p), escape(p.str()));
@@ -434,19 +427,19 @@ struct ShowWorker
label_string += "}}";
std::string code;
- for (auto &conn : it.second->connections()) {
- code += gen_portbox(stringf("c%d:p%d", id2num(it.first), id2num(conn.first)),
- conn.second, ct.cell_output(it.second->type, conn.first));
+ for (auto &conn : cell->connections()) {
+ code += gen_portbox(stringf("c%d:p%d", id2num(cell->name), id2num(conn.first)),
+ conn.second, ct.cell_output(cell->type, conn.first));
}
#ifdef CLUSTER_CELLS_AND_PORTBOXES
if (!code.empty())
fprintf(f, "subgraph cluster_c%d {\nc%d [ shape=record, label=\"%s\"%s ];\n%s}\n",
- id2num(it.first), id2num(it.first), label_string.c_str(), findColor(it.first), code.c_str());
+ id2num(cell->name), id2num(cell->name), label_string.c_str(), findColor(cell->name), code.c_str());
else
#endif
fprintf(f, "c%d [ shape=record, label=\"%s\"%s ];\n%s",
- id2num(it.first), label_string.c_str(), findColor(it.first.str()), code.c_str());
+ id2num(cell->name), label_string.c_str(), findColor(cell->name.str()), code.c_str());
}
for (auto &it : module->processes)
@@ -491,12 +484,12 @@ struct ShowWorker
{
bool found_lhs_wire = false;
for (auto &c : conn.first.chunks()) {
- if (c.wire == NULL || design->selected_member(module->name, c.wire->name))
+ if (c.wire == nullptr || design->selected_member(module->name, c.wire->name))
found_lhs_wire = true;
}
bool found_rhs_wire = false;
for (auto &c : conn.second.chunks()) {
- if (c.wire == NULL || design->selected_member(module->name, c.wire->name))
+ if (c.wire == nullptr || design->selected_member(module->name, c.wire->name))
found_rhs_wire = true;
}
if (!found_lhs_wire || !found_rhs_wire)
@@ -572,23 +565,21 @@ struct ShowWorker
design->optimize();
page_counter = 0;
- for (auto &mod_it : design->modules_)
+ for (auto mod : design->selected_modules())
{
- module = mod_it.second;
- if (!design->selected_module(module->name))
- continue;
+ module = mod;
if (design->selected_whole_module(module->name)) {
if (module->get_blackbox_attribute()) {
- // log("Skipping blackbox module %s.\n", id2cstr(module->name));
+ // log("Skipping blackbox module %s.\n", log_id(module->name));
continue;
} else
- if (module->cells_.empty() && module->connections().empty() && module->processes.empty()) {
- log("Skipping empty module %s.\n", id2cstr(module->name));
+ if (module->cells().size() == 0 && module->connections().empty() && module->processes.empty()) {
+ log("Skipping empty module %s.\n", log_id(module->name));
continue;
} else
- log("Dumping module %s to page %d.\n", id2cstr(module->name), ++page_counter);
+ log("Dumping module %s to page %d.\n", log_id(module->name), ++page_counter);
} else
- log("Dumping selected parts of module %s to page %d.\n", id2cstr(module->name), ++page_counter);
+ log("Dumping selected parts of module %s to page %d.\n", log_id(module->name), ++page_counter);
handle_module();
}
}
@@ -802,13 +793,12 @@ struct ShowPass : public Pass {
if (format != "ps" && format != "dot") {
int modcount = 0;
- for (auto &mod_it : design->modules_) {
- if (mod_it.second->get_blackbox_attribute())
+ for (auto module : design->selected_modules()) {
+ if (module->get_blackbox_attribute())
continue;
- if (mod_it.second->cells_.empty() && mod_it.second->connections().empty())
+ if (module->cells().size() == 0 && module->connections().empty())
continue;
- if (design->selected_module(mod_it.first))
- modcount++;
+ modcount++;
}
if (modcount > 1)
log_cmd_error("For formats different than 'ps' or 'dot' only one module must be selected.\n");
@@ -835,7 +825,7 @@ struct ShowPass : public Pass {
FILE *f = fopen(dot_file.c_str(), "w");
if (custom_prefix)
yosys_output_files.insert(dot_file);
- if (f == NULL) {
+ if (f == nullptr) {
for (auto lib : libs)
delete lib;
log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str());
@@ -889,8 +879,8 @@ struct ShowPass : public Pass {
if (flag_pause) {
#ifdef YOSYS_ENABLE_READLINE
- char *input = NULL;
- while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != NULL) {
+ char *input = nullptr;
+ while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != nullptr) {
if (input[strspn(input, " \t\r\n")] == 0)
break;
char *p = input + strspn(input, " \t\r\n");
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index f99090279..ea9e06979 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -102,7 +102,7 @@ struct SpliceWorker
for (auto &bit : sig.to_sigbit_vector())
{
- if (bit.wire == NULL)
+ if (bit.wire == nullptr)
{
if (last_bit == 0)
chunks.back().append(bit);
@@ -149,23 +149,23 @@ struct SpliceWorker
void run()
{
- log("Splicing signals in module %s:\n", RTLIL::id2cstr(module->name));
+ log("Splicing signals in module %s:\n", log_id(module->name));
driven_bits.push_back(RTLIL::State::Sm);
driven_bits.push_back(RTLIL::State::Sm);
- for (auto &it : module->wires_)
- if (it.second->port_input) {
- RTLIL::SigSpec sig = sigmap(it.second);
+ for (auto wire : module->wires())
+ if (wire->port_input) {
+ RTLIL::SigSpec sig = sigmap(wire);
driven_chunks.insert(sig);
for (auto &bit : sig.to_sigbit_vector())
driven_bits.push_back(bit);
driven_bits.push_back(RTLIL::State::Sm);
}
- for (auto &it : module->cells_)
- for (auto &conn : it.second->connections())
- if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) {
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections())
+ if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) {
RTLIL::SigSpec sig = sigmap(conn.second);
driven_chunks.insert(sig);
for (auto &bit : sig.to_sigbit_vector())
@@ -180,9 +180,8 @@ struct SpliceWorker
SigPool selected_bits;
if (!sel_by_cell)
- for (auto &it : module->wires_)
- if (design->selected(module, it.second))
- selected_bits.add(sigmap(it.second));
+ for (auto wire : module->selected_wires())
+ selected_bits.add(sigmap(wire));
std::vector<Cell*> mod_cells = module->cells();
@@ -343,17 +342,14 @@ struct SplicePass : public Pass {
log_header(design, "Executing SPLICE pass (creating cells for signal splicing).\n");
- for (auto &mod_it : design->modules_)
+ for (auto module : design->selected_modules())
{
- if (!design->selected(mod_it.second))
- continue;
-
- if (mod_it.second->processes.size()) {
- log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str());
+ if (module->processes.size()) {
+ log("Skipping module %s as it contains processes.\n", module->name.c_str());
continue;
}
- SpliceWorker worker(design, mod_it.second);
+ SpliceWorker worker(design, module);
worker.sel_by_cell = sel_by_cell;
worker.sel_by_wire = sel_by_wire;
worker.sel_any_bit = sel_any_bit;
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index bf693e3d4..1e7dedd70 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -141,6 +141,9 @@ struct SplitnetsPass : public Pass {
for (auto module : design->selected_modules())
{
+ if (module->has_processes_warn())
+ continue;
+
SplitnetsWorker worker;
if (flag_ports)
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 758a59661..6c4bc0e5b 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -79,18 +79,15 @@ struct statdata_t
STAT_NUMERIC_MEMBERS
#undef X
- for (auto &it : mod->wires_)
+ for (auto wire : mod->selected_wires())
{
- if (!design->selected(mod, it.second))
- continue;
-
- if (it.first[0] == '\\') {
+ if (wire->name[0] == '\\') {
num_pub_wires++;
- num_pub_wire_bits += it.second->width;
+ num_pub_wire_bits += wire->width;
}
num_wires++;
- num_wire_bits += it.second->width;
+ num_wire_bits += wire->width;
}
for (auto &it : mod->memories) {
@@ -100,12 +97,9 @@ struct statdata_t
num_memory_bits += it.second->width * it.second->size;
}
- for (auto &it : mod->cells_)
+ for (auto cell : mod->selected_cells())
{
- if (!design->selected(mod, it.second))
- continue;
-
- RTLIL::IdString cell_type = it.second->type;
+ RTLIL::IdString cell_type = cell->type;
if (width_mode)
{
@@ -116,15 +110,15 @@ struct statdata_t
ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx),
ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt),
ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow), ID($alu))) {
- int width_a = it.second->hasPort(ID::A) ? GetSize(it.second->getPort(ID::A)) : 0;
- int width_b = it.second->hasPort(ID::B) ? GetSize(it.second->getPort(ID::B)) : 0;
- int width_y = it.second->hasPort(ID::Y) ? GetSize(it.second->getPort(ID::Y)) : 0;
+ int width_a = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : 0;
+ int width_b = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : 0;
+ int width_y = cell->hasPort(ID::Y) ? GetSize(cell->getPort(ID::Y)) : 0;
cell_type = stringf("%s_%d", cell_type.c_str(), max<int>({width_a, width_b, width_y}));
}
else if (cell_type.in(ID($mux), ID($pmux)))
- cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort(ID::Y)));
+ cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)));
else if (cell_type.in(ID($sr), ID($dff), ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr)))
- cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort(ID::Q)));
+ cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q)));
}
if (!cell_area.empty()) {
@@ -157,7 +151,7 @@ struct statdata_t
log(" Number of cells: %6d\n", num_cells);
for (auto &it : num_cells_by_type)
if (it.second)
- log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second);
+ log(" %-26s %6d\n", log_id(it.first), it.second);
if (!unknown_cell_area.empty()) {
log("\n");
@@ -255,7 +249,7 @@ statdata_t hierarchy_worker(std::map<RTLIL::IdString, statdata_t> &mod_stat, RTL
for (auto &it : num_cells_by_type)
if (mod_stat.count(it.first) > 0) {
- log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, RTLIL::id2cstr(it.first), it.second);
+ log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, log_id(it.first), it.second);
mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1) * it.second;
mod_data.num_cells -= it.second;
} else {
@@ -281,7 +275,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil
continue;
LibertyAst *ar = cell->find("area");
- if (ar != NULL && !ar->value.empty())
+ if (ar != nullptr && !ar->value.empty())
cell_area["\\" + cell->args[0]] = atof(ar->value.c_str());
}
}
@@ -319,7 +313,7 @@ struct StatPass : public Pass {
log_header(design, "Printing statistics.\n");
bool width_mode = false;
- RTLIL::Module *top_mod = NULL;
+ RTLIL::Module *top_mod = nullptr;
std::map<RTLIL::IdString, statdata_t> mod_stat;
dict<IdString, double> cell_area;
string techname;
@@ -342,9 +336,9 @@ struct StatPass : public Pass {
continue;
}
if (args[argidx] == "-top" && argidx+1 < args.size()) {
- if (design->modules_.count(RTLIL::escape_id(args[argidx+1])) == 0)
+ if (design->module(RTLIL::escape_id(args[argidx+1])) == nullptr)
log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str());
- top_mod = design->modules_.at(RTLIL::escape_id(args[++argidx]));
+ top_mod = design->module(RTLIL::escape_id(args[++argidx]));
continue;
}
break;
@@ -364,18 +358,18 @@ struct StatPass : public Pass {
mod_stat[mod->name] = data;
log("\n");
- log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
+ log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)");
log("\n");
data.log_data(mod->name, false);
}
- if (top_mod != NULL && GetSize(mod_stat) > 1)
+ if (top_mod != nullptr && GetSize(mod_stat) > 1)
{
log("\n");
log("=== design hierarchy ===\n");
log("\n");
- log(" %-28s %6d\n", RTLIL::id2cstr(top_mod->name), 1);
+ log(" %-28s %6d\n", log_id(top_mod->name), 1);
statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0);
log("\n");
diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc
index f5701acee..2db7cf26b 100644
--- a/passes/hierarchy/submod.cc
+++ b/passes/hierarchy/submod.cc
@@ -51,7 +51,7 @@ struct SubmodWorker
RTLIL::Wire *new_wire;
RTLIL::Const is_int_driven;
bool is_int_used, is_ext_driven, is_ext_used;
- wire_flags_t(RTLIL::Wire* wire) : new_wire(NULL), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { }
+ wire_flags_t(RTLIL::Wire* wire) : new_wire(nullptr), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { }
};
std::map<RTLIL::Wire*, wire_flags_t> wire_flags;
bool flag_found_something;
@@ -75,7 +75,7 @@ struct SubmodWorker
void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used)
{
for (auto &c : sig.chunks())
- if (c.wire != NULL) {
+ if (c.wire != nullptr) {
flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used);
if (set_int_driven)
for (int i = c.offset; i < c.offset+c.width; i++) {
@@ -100,8 +100,7 @@ struct SubmodWorker
flag_signal(conn.second, true, true, true, false, false);
}
}
- for (auto &it : module->cells_) {
- RTLIL::Cell *cell = it.second;
+ for (auto cell : module->cells()) {
if (submod.cells.count(cell) > 0)
continue;
if (ct.cell_known(cell->type)) {
@@ -211,7 +210,7 @@ struct SubmodWorker
RTLIL::Cell *new_cell = new_mod->addCell(cell->name, cell);
for (auto &conn : new_cell->connections_)
for (auto &bit : conn.second)
- if (bit.wire != NULL) {
+ if (bit.wire != nullptr) {
log_assert(wire_flags.count(bit.wire) > 0);
bit.wire = wire_flags.at(bit.wire).new_wire;
}
@@ -274,12 +273,11 @@ struct SubmodWorker
if (opt_name.empty())
{
- for (auto &it : module->wires_)
- it.second->attributes.erase(ID::submod);
+ for (auto wire : module->wires())
+ wire->attributes.erase(ID::submod);
- for (auto &it : module->cells_)
+ for (auto cell : module->cells())
{
- RTLIL::Cell *cell = it.second;
if (cell->attributes.count(ID::submod) == 0 || cell->attributes[ID::submod].bits.size() == 0) {
cell->attributes.erase(ID::submod);
continue;
@@ -291,7 +289,7 @@ struct SubmodWorker
if (submodules.count(submod_str) == 0) {
submodules[submod_str].name = submod_str;
submodules[submod_str].full_name = module->name.str() + "_" + submod_str;
- while (design->modules_.count(submodules[submod_str].full_name) != 0 ||
+ while (design->module(submodules[submod_str].full_name) != nullptr ||
module->count_id(submodules[submod_str].full_name) != 0)
submodules[submod_str].full_name += "_";
}
@@ -301,9 +299,8 @@ struct SubmodWorker
}
else
{
- for (auto &it : module->cells_)
+ for (auto cell : module->cells())
{
- RTLIL::Cell *cell = it.second;
if (!design->selected(module, cell))
continue;
submodules[opt_name].name = opt_name;
@@ -392,12 +389,12 @@ struct SubmodPass : public Pass {
while (did_something) {
did_something = false;
std::vector<RTLIL::IdString> queued_modules;
- for (auto &mod_it : design->modules_)
- if (handled_modules.count(mod_it.first) == 0 && design->selected_whole_module(mod_it.first))
- queued_modules.push_back(mod_it.first);
+ for (auto mod : design->modules())
+ if (handled_modules.count(mod->name) == 0 && design->selected_whole_module(mod->name))
+ queued_modules.push_back(mod->name);
for (auto &modname : queued_modules)
- if (design->modules_.count(modname) != 0) {
- SubmodWorker worker(design, design->modules_[modname], copy_mode, hidden_mode);
+ if (design->module(modname) != nullptr) {
+ SubmodWorker worker(design, design->module(modname), copy_mode, hidden_mode);
handled_modules.insert(modname);
did_something = true;
}
@@ -407,15 +404,13 @@ struct SubmodPass : public Pass {
}
else
{
- RTLIL::Module *module = NULL;
- for (auto &mod_it : design->modules_) {
- if (!design->selected_module(mod_it.first))
- continue;
- if (module != NULL)
- log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod_it.first.c_str());
- module = mod_it.second;
+ RTLIL::Module *module = nullptr;
+ for (auto mod : design->selected_modules()) {
+ if (module != nullptr)
+ log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod->name.c_str());
+ module = mod;
}
- if (module == NULL)
+ if (module == nullptr)
log("Nothing selected -> do nothing.\n");
else {
Pass::call_on_module(design, module, "opt_clean");
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index 52ee1e99d..0898ec288 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -137,9 +137,26 @@ struct rules_t
vector<vector<std::tuple<bool,IdString,Const>>> attributes;
};
+ bool attr_icase;
dict<IdString, vector<bram_t>> brams;
vector<match_t> matches;
+ std::string map_case(std::string value) const
+ {
+ if (attr_icase) {
+ for (char &c : value)
+ c = tolower(c);
+ }
+ return value;
+ }
+
+ RTLIL::Const map_case(RTLIL::Const value) const
+ {
+ if (value.flags & RTLIL::CONST_FLAG_STRING)
+ return map_case(value.decode_string());
+ return value;
+ }
+
std::ifstream infile;
vector<string> tokens;
vector<string> labels;
@@ -337,7 +354,7 @@ struct rules_t
IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2));
Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1);
- data.attributes.back().emplace_back(exists, key, val);
+ data.attributes.back().emplace_back(exists, key, map_case(val));
}
continue;
}
@@ -351,6 +368,7 @@ struct rules_t
rewrite_filename(filename);
infile.open(filename);
linecount = 0;
+ attr_icase = false;
if (infile.fail())
log_error("Can't open rules file `%s'.\n", filename.c_str());
@@ -360,6 +378,11 @@ struct rules_t
if (!labels.empty())
syntax_error();
+ if (GetSize(tokens) == 2 && tokens[0] == "attr_icase") {
+ attr_icase = atoi(tokens[1].c_str());
+ continue;
+ }
+
if (tokens[0] == "bram") {
parse_bram();
continue;
@@ -843,7 +866,7 @@ grow_read_ports:;
}
else if (!exists)
continue;
- if (it->second != value)
+ if (rules.map_case(it->second) != value)
continue;
found = true;
break;
@@ -855,7 +878,7 @@ grow_read_ports:;
ss << "!";
IdString key = std::get<1>(sums.front());
ss << log_id(key);
- const Const &value = std::get<2>(sums.front());
+ const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\"";
@@ -1079,9 +1102,6 @@ void handle_cell(Cell *cell, const rules_t &rules)
auto &bram = rules.brams.at(match.name).at(vi);
bool or_next_if_better = match.or_next_if_better || vi+1 < GetSize(rules.brams.at(match.name));
- if (failed_brams.count(pair<IdString, int>(bram.name, bram.variant)))
- continue;
-
int avail_rd_ports = 0;
int avail_wr_ports = 0;
for (int j = 0; j < bram.groups; j++) {
@@ -1117,6 +1137,9 @@ void handle_cell(Cell *cell, const rules_t &rules)
int efficiency = (100 * match_properties["bits"]) / (dups * cells * bram.dbits * (1 << bram.abits));
match_properties["efficiency"] = efficiency;
+ if (failed_brams.count(pair<IdString, int>(bram.name, bram.variant)))
+ goto next_match_rule;
+
log(" Metrics for %s: awaste=%d dwaste=%d bwaste=%d waste=%d efficiency=%d\n",
log_id(match.name), awaste, dwaste, bwaste, waste, efficiency);
@@ -1167,7 +1190,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
}
else if (!exists)
continue;
- if (it->second != value)
+ if (rules.map_case(it->second) != value)
continue;
found = true;
break;
@@ -1179,7 +1202,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
ss << "!";
IdString key = std::get<1>(sums.front());
ss << log_id(key);
- const Const &value = std::get<2>(sums.front());
+ const Const &value = rules.map_case(std::get<2>(sums.front()));
if (exists && value != Const(1))
ss << "=\"" << value.decode_string() << "\"";
@@ -1252,8 +1275,13 @@ struct MemoryBramPass : public Pass {
log("The given rules file describes the available resources and how they should be\n");
log("used.\n");
log("\n");
- log("The rules file contains a set of block ram description and a sequence of match\n");
- log("rules. A block ram description looks like this:\n");
+ log("The rules file contains configuration options, a set of block ram description\n");
+ log("and a sequence of match rules.\n");
+ log("\n");
+ log("The option 'attr_icase' configures how attribute values are matched. The value 0\n");
+ log("means case-sensitive, 1 means case-insensitive.\n");
+ log("\n");
+ log("A block ram description looks like this:\n");
log("\n");
log(" bram RAMB1024X32 # name of BRAM cell\n");
log(" init 1 # set to '1' if BRAM can be initialized\n");
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc
index a62dcc2c4..ef8b07811 100644
--- a/passes/memory/memory_collect.cc
+++ b/passes/memory/memory_collect.cc
@@ -60,8 +60,7 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
int addr_bits = 0;
std::vector<Cell*> memcells;
- for (auto &cell_it : module->cells_) {
- Cell *cell = cell_it.second;
+ for (auto cell : module->cells())
if (cell->type.in(ID($memrd), ID($memwr), ID($meminit)) && memory->name == cell->parameters[ID::MEMID].decode_string()) {
SigSpec addr = sigmap(cell->getPort(ID::ADDR));
for (int i = 0; i < GetSize(addr); i++)
@@ -69,7 +68,6 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory)
addr_bits = std::max(addr_bits, i+1);
memcells.push_back(cell);
}
- }
if (memory->start_offset == 0 && addr_bits < 30 && (1 << addr_bits) < memory->size)
memory->size = 1 << addr_bits;
@@ -260,9 +258,8 @@ struct MemoryCollectPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
log_header(design, "Executing MEMORY_COLLECT pass (generating $mem cells).\n");
extra_args(args, 1, design);
- for (auto &mod_it : design->modules_)
- if (design->selected(mod_it.second))
- handle_module(design, mod_it.second);
+ for (auto module : design->selected_modules())
+ handle_module(design, module);
}
} MemoryCollectPass;
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index da0673c8f..9d455f55b 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -28,11 +28,32 @@ PRIVATE_NAMESPACE_BEGIN
struct MemoryMapWorker
{
+ bool attr_icase = false;
+ dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
+
RTLIL::Design *design;
RTLIL::Module *module;
std::map<std::pair<RTLIL::SigSpec, RTLIL::SigSpec>, RTLIL::SigBit> decoder_cache;
+ MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) {}
+
+ std::string map_case(std::string value) const
+ {
+ if (attr_icase) {
+ for (char &c : value)
+ c = tolower(c);
+ }
+ return value;
+ }
+
+ RTLIL::Const map_case(RTLIL::Const value) const
+ {
+ if (value.flags & RTLIL::CONST_FLAG_STRING)
+ return map_case(value.decode_string());
+ return value;
+ }
+
std::string genid(RTLIL::IdString name, std::string token1 = "", int i = -1, std::string token2 = "", int j = -1, std::string token3 = "", int k = -1, std::string token4 = "")
{
std::stringstream sstr;
@@ -98,6 +119,36 @@ struct MemoryMapWorker
return;
}
+ // check if attributes allow us to infer FFRAM for this cell
+ for (const auto &attr : attributes) {
+ if (cell->attributes.count(attr.first)) {
+ const auto &cell_attr = cell->attributes[attr.first];
+ if (attr.second.empty()) {
+ log("Not mapping memory cell %s in module %s (attribute %s is set).\n",
+ cell->name.c_str(), module->name.c_str(), attr.first.c_str());
+ return;
+ }
+
+ bool found = false;
+ for (auto &value : attr.second) {
+ if (map_case(cell_attr) == map_case(value)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (cell_attr.flags & RTLIL::CONST_FLAG_STRING) {
+ log("Not mapping memory cell %s in module %s (attribute %s is set to \"%s\").\n",
+ cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str());
+ } else {
+ log("Not mapping memory cell %s in module %s (attribute %s is set to %d).\n",
+ cell->name.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int());
+ }
+ return;
+ }
+ }
+ }
+
// all write ports must share the same clock
RTLIL::SigSpec clocks = cell->getPort(ID::WR_CLK);
RTLIL::Const clocks_pol = cell->parameters[ID::WR_CLK_POLARITY];
@@ -339,7 +390,7 @@ struct MemoryMapWorker
module->remove(cell);
}
- MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module)
+ void run()
{
std::vector<RTLIL::Cell*> cells;
for (auto cell : module->selected_cells())
@@ -356,17 +407,73 @@ struct MemoryMapPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" memory_map [selection]\n");
+ log(" memory_map [options] [selection]\n");
log("\n");
log("This pass converts multiport memory cells as generated by the memory_collect\n");
log("pass to word-wide DFFs and address decoders.\n");
log("\n");
+ log(" -attr !<name>\n");
+ log(" do not map memories that have attribute <name> set.\n");
+ log("\n");
+ log(" -attr <name>[=<value>]\n");
+ log(" for memories that have attribute <name> set, only map them if its value\n");
+ log(" is a string <value> (if specified), or an integer 1 (otherwise). if this\n");
+ log(" option is specified multiple times, map the memory if the attribute is\n");
+ log(" to any of the values.\n");
+ log("\n");
+ log(" -iattr\n");
+ log(" for -attr, ignore case of <value>.\n");
+ log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool attr_icase = false;
+ dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
+
log_header(design, "Executing MEMORY_MAP pass (converting $mem cells to logic and flip-flops).\n");
- extra_args(args, 1, design);
- for (auto mod : design->selected_modules())
- MemoryMapWorker(design, mod);
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-attr" && argidx + 1 < args.size())
+ {
+ std::string attr_arg = args[++argidx];
+ std::string name;
+ RTLIL::Const value;
+ size_t eq_at = attr_arg.find('=');
+ if (eq_at != std::string::npos) {
+ name = attr_arg.substr(0, eq_at);
+ value = attr_arg.substr(eq_at + 1);
+ } else {
+ name = attr_arg;
+ value = RTLIL::Const(1);
+ }
+ if (attr_arg.size() > 1 && attr_arg[0] == '!') {
+ if (value != RTLIL::Const(1)) {
+ --argidx;
+ break; // we don't support -attr !<name>=<value>
+ }
+ attributes[RTLIL::escape_id(name.substr(1))].clear();
+ } else {
+ attributes[RTLIL::escape_id(name)].push_back(value);
+ }
+ continue;
+ }
+ if (args[argidx] == "-iattr")
+ {
+ attr_icase = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto mod : design->selected_modules()) {
+ MemoryMapWorker worker(design, mod);
+ worker.attr_icase = attr_icase;
+ worker.attributes = attributes;
+ worker.run();
+ }
}
} MemoryMapPass;
diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc
index 9173c791b..8d284edcd 100644
--- a/passes/memory/memory_unpack.cc
+++ b/passes/memory/memory_unpack.cc
@@ -118,11 +118,11 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory)
void handle_module(RTLIL::Design *design, RTLIL::Module *module)
{
std::vector<RTLIL::IdString> memcells;
- for (auto &cell_it : module->cells_)
- if (cell_it.second->type == ID($mem) && design->selected(module, cell_it.second))
- memcells.push_back(cell_it.first);
+ for (auto cell : module->cells())
+ if (cell->type == ID($mem) && design->selected(module, cell))
+ memcells.push_back(cell->name);
for (auto &it : memcells)
- handle_memory(module, module->cells_.at(it));
+ handle_memory(module, module->cell(it));
}
struct MemoryUnpackPass : public Pass {
@@ -140,9 +140,8 @@ struct MemoryUnpackPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE {
log_header(design, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n");
extra_args(args, 1, design);
- for (auto &mod_it : design->modules_)
- if (design->selected(mod_it.second))
- handle_module(design, mod_it.second);
+ for (auto module : design->selected_modules())
+ handle_module(design, module);
}
} MemoryUnpackPass;
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index da3961218..6271376f1 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -406,6 +406,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
if (verbose && del_temp_wires_count)
log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count);
+ if (!del_wires_queue.empty())
+ module->design->scratchpad_set_bool("opt.did_something", true);
+
return !del_wires_queue.empty();
}
@@ -476,6 +479,9 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
next_wire:;
}
+ if (did_something)
+ module->design->scratchpad_set_bool("opt.did_something", true);
+
return did_something;
}
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 1a4dd9239..2b35ace5e 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -717,31 +717,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
RTLIL::SigSpec sig_co = cell->getPort(ID::CO);
- bool sub = (sig_ci == State::S1 && sig_bi == State::S1);
+ if (sig_bi != State::S0 && sig_bi != State::S1)
+ goto skip_fine_alu;
+ if (sig_ci != State::S0 && sig_ci != State::S1)
+ goto skip_fine_alu;
- // If not a subtraction, yet there is a carry or B is inverted
- // then no optimisation is possible as carry will not be constant
- if (!sub && (sig_ci != State::S0 || sig_bi != State::S0))
- goto next_cell;
+ bool bi = sig_bi == State::S1;
+ bool ci = sig_ci == State::S1;
int i;
for (i = 0; i < GetSize(sig_y); i++) {
RTLIL::SigBit b = sig_b.at(i, State::Sx);
RTLIL::SigBit a = sig_a.at(i, State::Sx);
- if (b == State::S0 && a != State::Sx) {
- module->connect(sig_y[i], sig_a[i]);
- module->connect(sig_x[i], sub ? module->Not(NEW_ID, a).as_bit() : a);
- module->connect(sig_co[i], sub ? State::S1 : State::S0);
- }
- else if (sub && b == State::S1 && a == State::S1) {
- module->connect(sig_y[i], State::S0);
- module->connect(sig_x[i], module->Not(NEW_ID, a));
- module->connect(sig_co[i], State::S0);
+ if (b == ((bi ^ ci) ? State::S1 : State::S0) && a != State::Sx) {
+ module->connect(sig_y[i], a);
+ module->connect(sig_x[i], ci ? module->Not(NEW_ID, a).as_bit() : a);
+ module->connect(sig_co[i], ci ? State::S1 : State::S0);
}
- else if (!sub && a == State::S0 && b != State::Sx) {
- module->connect(sig_y[i], b);
- module->connect(sig_x[i], b);
- module->connect(sig_co[i], State::S0);
+ else if (a == (ci ? State::S1 : State::S0) && b != State::Sx) {
+ module->connect(sig_y[i], bi ? module->Not(NEW_ID, b).as_bit() : b);
+ module->connect(sig_x[i], (bi ^ ci) ? module->Not(NEW_ID, b).as_bit() : b);
+ module->connect(sig_co[i], ci ? State::S1 : State::S0);
}
else
break;
@@ -758,6 +754,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
}
+skip_fine_alu:
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr),
ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow)))
@@ -1089,7 +1086,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
// If not a subtraction, yet there is a carry or B is inverted
// then no optimisation is possible as carry will not be constant
if (!sub && (sig_ci != State::S0 || sig_bi != State::S0))
- goto next_cell;
+ goto skip_identity;
}
if (!sub && a.is_fully_const() && a.as_bool() == false)
@@ -1138,9 +1135,24 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
if (cell->type == ID($alu)) {
+ bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
+ bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
+ bool is_signed = a_signed && b_signed;
+ RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID::CI));
int y_width = GetSize(cell->getPort(ID::Y));
- module->connect(cell->getPort(ID::X), RTLIL::Const(State::S0, y_width));
- module->connect(cell->getPort(ID::CO), RTLIL::Const(State::S0, y_width));
+ if (sig_ci == State::S1) {
+ /* sub, b is 0 */
+ RTLIL::SigSpec a = cell->getPort(ID::A);
+ a.extend_u0(y_width, is_signed);
+ module->connect(cell->getPort(ID::X), module->Not(NEW_ID, a));
+ module->connect(cell->getPort(ID::CO), RTLIL::Const(State::S1, y_width));
+ } else {
+ /* add */
+ RTLIL::SigSpec ab = cell->getPort(identity_wrt_a ? ID::A : ID::B);
+ ab.extend_u0(y_width, is_signed);
+ module->connect(cell->getPort(ID::X), ab);
+ module->connect(cell->getPort(ID::CO), RTLIL::Const(State::S0, y_width));
+ }
cell->unsetPort(ID::BI);
cell->unsetPort(ID::CI);
cell->unsetPort(ID::X);
@@ -1163,6 +1175,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
goto next_cell;
}
}
+skip_identity:
if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) &&
cell->getPort(ID::A) == State::S0 && cell->getPort(ID::B) == State::S1) {
@@ -1426,6 +1439,39 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
goto next_cell;
}
}
+
+ sig_a = assign_map(cell->getPort(ID::A));
+ sig_b = assign_map(cell->getPort(ID::B));
+ int a_zeros, b_zeros;
+ for (a_zeros = 0; a_zeros < GetSize(sig_a); a_zeros++)
+ if (sig_a[a_zeros] != RTLIL::State::S0)
+ break;
+ for (b_zeros = 0; b_zeros < GetSize(sig_b); b_zeros++)
+ if (sig_b[b_zeros] != RTLIL::State::S0)
+ break;
+ if (a_zeros || b_zeros) {
+ int y_zeros = a_zeros + b_zeros;
+ cover("opt.opt_expr.mul_low_zeros");
+
+ log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n",
+ a_zeros, b_zeros, cell->name.c_str(), module->name.c_str());
+
+ if (a_zeros) {
+ cell->setPort(ID::A, sig_a.extract_end(a_zeros));
+ cell->parameters[ID::A_WIDTH] = GetSize(sig_a) - a_zeros;
+ }
+ if (b_zeros) {
+ cell->setPort(ID::B, sig_b.extract_end(b_zeros));
+ cell->parameters[ID::B_WIDTH] = GetSize(sig_b) - b_zeros;
+ }
+ cell->setPort(ID::Y, sig_y.extract_end(y_zeros));
+ cell->parameters[ID::Y_WIDTH] = GetSize(sig_y) - y_zeros;
+ module->connect(RTLIL::SigSig(sig_y.extract(0, y_zeros), RTLIL::SigSpec(0, y_zeros)));
+ cell->check();
+
+ did_something = true;
+ goto next_cell;
+ }
}
if (!keepdc && cell->type.in(ID($div), ID($mod)))
@@ -1497,6 +1543,99 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ // Find places in $alu cell where the carry is constant, and split it at these points.
+ if (do_fine && !keepdc && cell->type == ID($alu))
+ {
+ bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
+ bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
+ bool is_signed = a_signed && b_signed;
+
+ RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
+ RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ RTLIL::SigSpec sig_bi = assign_map(cell->getPort(ID::BI));
+ if (GetSize(sig_a) == 0)
+ sig_a = State::S0;
+ if (GetSize(sig_b) == 0)
+ sig_b = State::S0;
+ sig_a.extend_u0(GetSize(sig_y), is_signed);
+ sig_b.extend_u0(GetSize(sig_y), is_signed);
+
+ if (sig_bi != State::S0 && sig_bi != State::S1)
+ goto skip_alu_split;
+
+ std::vector<std::pair<int, State>> split_points;
+
+ for (int i = 0; i < GetSize(sig_y); i++) {
+ SigBit bit_a = sig_a[i];
+ SigBit bit_b = sig_b[i];
+ if (bit_a != State::S0 && bit_a != State::S1)
+ continue;
+ if (bit_b != State::S0 && bit_b != State::S1)
+ continue;
+ if (sig_bi == State::S1) {
+ if (bit_b == State::S0)
+ bit_b = State::S1;
+ else
+ bit_b = State::S0;
+ }
+ if (bit_a != bit_b)
+ continue;
+ split_points.push_back(std::make_pair(i + 1, bit_a.data));
+ }
+
+ if (split_points.empty() || split_points[0].first == GetSize(sig_y))
+ goto skip_alu_split;
+
+ for (auto &p : split_points)
+ log_debug("Splitting $alu cell `%s' in module `%s' at const-carry point %d.\n",
+ cell->name.c_str(), module->name.c_str(), p.first);
+
+ if (split_points.back().first != GetSize(sig_y))
+ split_points.push_back(std::make_pair(GetSize(sig_y), State::Sx));
+
+ RTLIL::SigSpec sig_ci = assign_map(cell->getPort(ID::CI));
+ int prev = 0;
+ RTLIL::SigSpec sig_x = assign_map(cell->getPort(ID::X));
+ RTLIL::SigSpec sig_co = assign_map(cell->getPort(ID::CO));
+
+ for (auto &p : split_points) {
+ int cur = p.first;
+ int sz = cur - prev;
+ bool last = cur == GetSize(sig_y);
+
+ RTLIL::Cell *c = module->addCell(NEW_ID, cell->type);
+ c->setPort(ID::A, sig_a.extract(prev, sz));
+ c->setPort(ID::B, sig_b.extract(prev, sz));
+ c->setPort(ID::BI, sig_bi);
+ c->setPort(ID::CI, sig_ci);
+ c->setPort(ID::Y, sig_y.extract(prev, sz));
+ c->setPort(ID::X, sig_x.extract(prev, sz));
+ RTLIL::SigSpec new_co = sig_co.extract(prev, sz);
+ if (p.second != State::Sx) {
+ module->connect(new_co[sz-1], p.second);
+ RTLIL::Wire *dummy = module->addWire(NEW_ID);
+ new_co[sz-1] = dummy;
+ }
+ c->setPort(ID::CO, new_co);
+ c->parameters[ID::A_WIDTH] = sz;
+ c->parameters[ID::B_WIDTH] = sz;
+ c->parameters[ID::Y_WIDTH] = sz;
+ c->parameters[ID::A_SIGNED] = last ? a_signed : false;
+ c->parameters[ID::B_SIGNED] = last ? b_signed : false;
+
+ prev = p.first;
+ sig_ci = p.second;
+ }
+
+ cover("opt.opt_expr.alu_split");
+ module->remove(cell);
+
+ did_something = true;
+ goto next_cell;
+ }
+skip_alu_split:
+
// remove redundant pairs of bits in ==, ===, !=, and !==
// replace cell with const driver if inputs can't be equal
if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex)))
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index a861bd7a4..d845926fc 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -118,9 +118,7 @@ struct OptMergeWorker
for (auto &it : *conn) {
RTLIL::SigSpec sig;
if (cell->output(it.first)) {
- if (it.first == ID::Q && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") ||
- cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") ||
- cell->type.in(ID($adff), ID($sr), ID($ff), ID($_FF_)))) {
+ if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell->type)) {
// For the 'Q' output of state elements,
// use its (* init *) attribute value
for (const auto &b : dff_init_map(it.second))
diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc
index 4bb4b0edc..a928c57de 100644
--- a/passes/sat/Makefile.inc
+++ b/passes/sat/Makefile.inc
@@ -13,4 +13,5 @@ OBJS += passes/sat/fmcombine.o
OBJS += passes/sat/mutate.o
OBJS += passes/sat/cutpoint.o
OBJS += passes/sat/fminit.o
+OBJS += passes/sat/qbfsat.o
diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc
new file mode 100644
index 000000000..44691425f
--- /dev/null
+++ b/passes/sat/qbfsat.cc
@@ -0,0 +1,550 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Alberto Gonzalez <boqwxp@airmail.cc>
+ *
+ * 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/log.h"
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include <cstdio>
+#include <algorithm>
+
+#if defined(_WIN32)
+# define WIFEXITED(x) 1
+# define WIFSIGNALED(x) 0
+# define WIFSTOPPED(x) 0
+# define WEXITSTATUS(x) ((x) & 0xff)
+# define WTERMSIG(x) SIGTERM
+#else
+# include <sys/wait.h>
+#endif
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct QbfSolutionType {
+ std::vector<std::string> stdout;
+ dict<std::string, std::string> hole_to_value;
+ bool sat;
+ bool unknown; //true if neither 'sat' nor 'unsat'
+ bool success; //true if exit code 0
+
+ QbfSolutionType() : sat(false), unknown(true), success(false) {}
+};
+
+struct QbfSolveOptions {
+ bool specialize, specialize_from_file, write_solution, nocleanup, dump_final_smt2, assume_outputs;
+ bool sat, unsat, show_smtbmc;
+ std::string specialize_soln_file;
+ std::string write_soln_soln_file;
+ std::string dump_final_smt2_file;
+ size_t argidx;
+ QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false),
+ nocleanup(false), dump_final_smt2(false), assume_outputs(false), sat(false), unsat(false),
+ show_smtbmc(false), argidx(0) {};
+};
+
+void recover_solution(QbfSolutionType &sol) {
+ YS_REGEX_TYPE sat_regex = YS_REGEX_COMPILE("Status: PASSED");
+ YS_REGEX_TYPE unsat_regex = YS_REGEX_COMPILE("Solver Error.*model is not available");
+ YS_REGEX_TYPE hole_value_regex = YS_REGEX_COMPILE_WITH_SUBS("Value for anyconst in [a-zA-Z0-9_]* \\(([^:]*:[^\\)]*)\\): (.*)");
+#ifndef NDEBUG
+ YS_REGEX_TYPE hole_loc_regex = YS_REGEX_COMPILE("[^:]*:[0-9]+.[0-9]+-[0-9]+.[0-9]+");
+ YS_REGEX_TYPE hole_val_regex = YS_REGEX_COMPILE("[0-9]+");
+#endif
+ YS_REGEX_MATCH_TYPE m;
+ bool sat_regex_found = false;
+ bool unsat_regex_found = false;
+ dict<std::string, bool> hole_value_recovered;
+ for (const std::string &x : sol.stdout) {
+ if(YS_REGEX_NS::regex_search(x, m, hole_value_regex)) {
+ std::string loc = m[1].str();
+ std::string val = m[2].str();
+#ifndef NDEBUG
+ log_assert(YS_REGEX_NS::regex_search(loc, hole_loc_regex));
+ log_assert(YS_REGEX_NS::regex_search(val, hole_val_regex));
+#endif
+ sol.hole_to_value[loc] = val;
+ }
+ else if (YS_REGEX_NS::regex_search(x, sat_regex))
+ sat_regex_found = true;
+ else if (YS_REGEX_NS::regex_search(x, unsat_regex))
+ unsat_regex_found = true;
+ }
+#ifndef NDEBUG
+ log_assert(!sol.unknown && sol.sat? sat_regex_found : true);
+ log_assert(!sol.unknown && !sol.sat? unsat_regex_found : true);
+#endif
+}
+
+dict<std::string, std::string> get_hole_loc_name_map(RTLIL::Module *module, const QbfSolutionType &sol) {
+ dict<std::string, std::string> hole_loc_to_name;
+ for (auto cell : module->cells()) {
+ std::string cell_src = cell->get_src_attribute();
+ auto pos = sol.hole_to_value.find(cell_src);
+ if (pos != sol.hole_to_value.end()) {
+#ifndef NDEBUG
+ log_assert(cell->type.in("$anyconst", "$anyseq"));
+ log_assert(cell->getPort(ID::Y).is_wire());
+#endif
+ hole_loc_to_name[pos->first] = cell->getPort(ID::Y).as_wire()->name.str();
+ }
+ }
+
+ return hole_loc_to_name;
+}
+
+void write_solution(RTLIL::Module *module, const QbfSolutionType &sol, const std::string &file) {
+ std::ofstream fout(file.c_str());
+ if (!fout)
+ log_cmd_error("could not open solution file for writing.\n");
+
+ dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+ for(auto &x : sol.hole_to_value)
+ fout << hole_loc_to_name[x.first] << "=" << x.second << std::endl;
+}
+
+void specialize_from_file(RTLIL::Module *module, const std::string &file) {
+ YS_REGEX_TYPE hole_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.*)=([01]+)$");
+ YS_REGEX_MATCH_TYPE m;
+ pool<RTLIL::Cell *> anyconsts_to_remove;
+ dict<std::string, std::string> hole_name_to_value;
+ std::ifstream fin(file.c_str());
+ if (!fin)
+ log_cmd_error("could not read solution file.\n");
+
+ std::string buf;
+ while (std::getline(fin, buf)) {
+ log_assert(YS_REGEX_NS::regex_search(buf, m, hole_assn_regex));
+ std::string hole_name = m[1].str();
+ std::string hole_value = m[2].str();
+ hole_name_to_value[hole_name] = hole_value;
+ }
+
+ for (auto cell : module->cells())
+ if (cell->type == "$anyconst") {
+ auto anyconst_port_y = cell->getPort(ID::Y).as_wire();
+ if (anyconst_port_y == nullptr)
+ continue;
+ if (hole_name_to_value.find(anyconst_port_y->name.str()) != hole_name_to_value.end())
+ anyconsts_to_remove.insert(cell);
+ }
+ for (auto cell : anyconsts_to_remove)
+ module->remove(cell);
+
+ for (auto &it : hole_name_to_value) {
+ std::string hole_name = it.first;
+ std::string hole_value = it.second;
+ RTLIL::Wire *wire = module->wire(hole_name);
+#ifndef NDEBUG
+ log_assert(wire != nullptr);
+ log_assert(wire->width > 0 && GetSize(hole_value) == wire->width);
+#endif
+
+ log("Specializing %s from file with %s = %d'b%s.\n", module->name.c_str(), hole_name.c_str(), wire->width, hole_value.c_str());
+ std::vector<RTLIL::SigBit> value_bv;
+ value_bv.reserve(wire->width);
+ for (char c : hole_value)
+ value_bv.emplace_back(c == '1'? RTLIL::S1 : RTLIL::S0);
+ std::reverse(value_bv.begin(), value_bv.end());
+ module->connect(wire, value_bv);
+ }
+}
+
+void specialize(RTLIL::Module *module, const QbfSolutionType &sol) {
+ dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+ pool<RTLIL::Cell *> anyconsts_to_remove;
+ for (auto cell : module->cells())
+ if (cell->type == "$anyconst")
+ if (hole_loc_to_name.find(cell->get_src_attribute()) != hole_loc_to_name.end())
+ anyconsts_to_remove.insert(cell);
+ for (auto cell : anyconsts_to_remove)
+ module->remove(cell);
+ for (auto &it : sol.hole_to_value) {
+ std::string hole_loc = it.first;
+ std::string hole_value = it.second;
+
+#ifndef NDEBUG
+ auto pos = hole_loc_to_name.find(hole_loc);
+ log_assert(pos != hole_loc_to_name.end());
+#endif
+
+ std::string hole_name = hole_loc_to_name[hole_loc];
+ RTLIL::Wire *wire = module->wire(hole_name);
+#ifndef NDEBUG
+ log_assert(wire != nullptr);
+ log_assert(wire->width > 0 && GetSize(hole_value) == wire->width);
+#endif
+
+ log("Specializing %s with %s = %d'b%s.\n", module->name.c_str(), hole_name.c_str(), wire->width, hole_value.c_str());
+ std::vector<RTLIL::SigBit> value_bv;
+ value_bv.reserve(wire->width);
+ for (char c : hole_value)
+ value_bv.emplace_back(c == '1'? RTLIL::S1 : RTLIL::S0);
+ std::reverse(value_bv.begin(), value_bv.end());
+ module->connect(wire, value_bv);
+ }
+}
+
+void dump_model(RTLIL::Module *module, const QbfSolutionType &sol) {
+ log("Satisfiable model:\n");
+ dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+ for (auto &it : sol.hole_to_value) {
+ std::string hole_loc = it.first;
+ std::string hole_value = it.second;
+
+#ifndef NDEBUG
+ auto pos = hole_loc_to_name.find(hole_loc);
+ log_assert(pos != hole_loc_to_name.end());
+#endif
+
+ std::string hole_name = hole_loc_to_name[hole_loc];
+ log("\t%s = %lu'b%s\n", hole_name.c_str(), hole_value.size(), hole_value.c_str());
+ std::vector<RTLIL::SigBit> value_bv;
+ value_bv.reserve(hole_value.size());
+ for (char c : hole_value)
+ value_bv.emplace_back(c == '1'? RTLIL::S1 : RTLIL::S0);
+ std::reverse(value_bv.begin(), value_bv.end());
+ }
+
+}
+
+void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wires) {
+ for (auto &n : input_wires) {
+ RTLIL::Wire *input = module->wire(n);
+#ifndef NDEBUG
+ log_assert(input != nullptr);
+#endif
+
+ RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst");
+ allconst->setParam(ID(WIDTH), input->width);
+ allconst->setPort(ID::Y, input);
+ allconst->set_src_attribute(input->get_src_attribute());
+ input->port_input = false;
+ log("Replaced input %s with $allconst cell.\n", n.c_str());
+ }
+ module->fixup_ports();
+}
+
+void assume_miter_outputs(RTLIL::Module *module) {
+ std::vector<RTLIL::Wire *> wires_to_assume;
+ for (auto w : module->wires())
+ if (w->port_output && w->width == 1)
+ wires_to_assume.push_back(w);
+
+ if (wires_to_assume.size() == 0)
+ return;
+ else {
+ log("Adding $assume cell for output(s): ");
+ for (auto w : wires_to_assume)
+ log("\"%s\" ", w->name.c_str());
+ log("\n");
+ }
+
+ for(auto i = 0; wires_to_assume.size() > 1; ++i) {
+ std::vector<RTLIL::Wire *> buf;
+ for (auto j = 0; j + 1 < GetSize(wires_to_assume); j += 2) {
+ std::stringstream strstr; strstr << i << "_" << j;
+ RTLIL::Wire *and_wire = module->addWire("\\_qbfsat_and_" + strstr.str(), 1);
+ module->addLogicAnd("$_qbfsat_and_" + strstr.str(), wires_to_assume[j], wires_to_assume[j+1], and_wire, false, wires_to_assume[j]->get_src_attribute());
+ buf.push_back(and_wire);
+ }
+ if (wires_to_assume.size() % 2 == 1)
+ buf.push_back(wires_to_assume[wires_to_assume.size() - 1]);
+ wires_to_assume.swap(buf);
+ }
+
+#ifndef NDEBUG
+ log_assert(wires_to_assume.size() == 1);
+#endif
+ module->addAssume("$assume_qbfsat_miter_outputs", wires_to_assume[0], RTLIL::S1);
+}
+
+QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) {
+ QbfSolutionType ret;
+ const std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc";
+ const std::string smtbmc_warning = "z3: WARNING:";
+ const bool show_smtbmc = opt.show_smtbmc;
+
+ const std::string tempdir_name = make_temp_dir("/tmp/yosys-z3-XXXXXX");
+ const std::string smt2_command = "write_smt2 -stbv -wires " + tempdir_name + "/problem.smt2";
+#ifndef NDEBUG
+ log_assert(mod->design != nullptr);
+#endif
+ Pass::call(mod->design, smt2_command);
+ log_header(mod->design, "Solving QBF-SAT problem.\n");
+
+ //Execute and capture stdout from `yosys-smtbmc -s z3 -t 1 -g --binary [--dump-smt2 <file>]`
+ {
+ const std::string cmd = yosys_smtbmc_exe + " -s z3 -t 1 -g --binary " + (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file + " " : "") + tempdir_name + "/problem.smt2 2>&1";
+ auto process_line = [&ret, &smtbmc_warning, &show_smtbmc](const std::string &line) {
+ ret.stdout.push_back(line.substr(0, line.size()-1)); //don't include trailing newline
+ auto warning_pos = line.find(smtbmc_warning);
+ if (warning_pos != std::string::npos)
+ log_warning("%s", line.substr(warning_pos + smtbmc_warning.size() + 1).c_str());
+ else
+ if (show_smtbmc)
+ log("smtbmc output: %s", line.c_str());
+ };
+
+ log("Launching \"%s\".\n", cmd.c_str());
+ int retval = run_command(cmd, process_line);
+ if (retval == 0) {
+ ret.sat = true;
+ ret.unknown = false;
+ } else if (retval == 1) {
+ ret.sat = false;
+ ret.unknown = false;
+ }
+ }
+
+ if(!opt.nocleanup)
+ remove_directory(tempdir_name);
+
+ recover_solution(ret);
+
+ return ret;
+}
+
+pool<std::string> validate_design_and_get_inputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
+ bool found_input = false;
+ bool found_hole = false;
+ bool found_1bit_output = false;
+ bool found_assert_assume = false;
+ pool<std::string> input_wires;
+ for (auto wire : module->wires()) {
+ if (wire->port_input) {
+ found_input = true;
+ input_wires.insert(wire->name.str());
+ }
+ if (wire->port_output && wire->width == 1)
+ found_1bit_output = true;
+ }
+ for (auto cell : module->cells()) {
+ if (cell->type == "$allconst")
+ found_input = true;
+ if (cell->type == "$anyconst")
+ found_hole = true;
+ if (cell->type.in("$assert", "$assume"))
+ found_assert_assume = true;
+ }
+ if (!found_input)
+ log_cmd_error("Can't perform QBF-SAT on a miter with no inputs!\n");
+ if (!found_hole)
+ log_cmd_error("Did not find any existentially-quantified variables. Use 'sat' instead.\n");
+ if (!found_1bit_output && !found_assert_assume)
+ log_cmd_error("Did not find any single-bit outputs or $assert/$assume cells. Is this a miter circuit?\n");
+ if (!found_assert_assume && !opt.assume_outputs)
+ log_cmd_error("Did not find any $assert/$assume cells. Single-bit outputs were found, but `-assume-outputs` was not specified.\n");
+
+ return input_wires;
+}
+
+QbfSolveOptions parse_args(const std::vector<std::string> &args) {
+ QbfSolveOptions opt;
+ for (opt.argidx = 1; opt.argidx < args.size(); opt.argidx++) {
+ if (args[opt.argidx] == "-nocleanup") {
+ opt.nocleanup = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-specialize") {
+ opt.specialize = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-assume-outputs") {
+ opt.assume_outputs = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-sat") {
+ opt.sat = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-unsat") {
+ opt.unsat = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-show-smtbmc") {
+ opt.show_smtbmc = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-dump-final-smt2") {
+ opt.dump_final_smt2 = true;
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("smt2 file not specified.\n");
+ else
+ opt.dump_final_smt2_file = args[++opt.argidx];
+ continue;
+ }
+ else if (args[opt.argidx] == "-specialize-from-file") {
+ opt.specialize_from_file = true;
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("solution file not specified.\n");
+ else
+ opt.specialize_soln_file = args[++opt.argidx];
+ continue;
+ }
+ else if (args[opt.argidx] == "-write-solution") {
+ opt.write_solution = true;
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("solution file not specified.\n");
+ else
+ opt.write_soln_soln_file = args[++opt.argidx];
+ continue;
+ }
+ break;
+ }
+
+ return opt;
+}
+
+void print_proof_failed()
+{
+ log("\n");
+ log(" ______ ___ ___ _ _ _ _ \n");
+ log(" (_____ \\ / __) / __) (_) | | | |\n");
+ log(" _____) )___ ___ ___ _| |__ _| |__ _____ _| | _____ __| | |\n");
+ log(" | ____/ ___) _ \\ / _ (_ __) (_ __|____ | | || ___ |/ _ |_|\n");
+ log(" | | | | | |_| | |_| || | | | / ___ | | || ____( (_| |_ \n");
+ log(" |_| |_| \\___/ \\___/ |_| |_| \\_____|_|\\_)_____)\\____|_|\n");
+ log("\n");
+}
+
+void print_qed()
+{
+ log("\n");
+ log(" /$$$$$$ /$$$$$$$$ /$$$$$$$ \n");
+ log(" /$$__ $$ | $$_____/ | $$__ $$ \n");
+ log(" | $$ \\ $$ | $$ | $$ \\ $$ \n");
+ log(" | $$ | $$ | $$$$$ | $$ | $$ \n");
+ log(" | $$ | $$ | $$__/ | $$ | $$ \n");
+ log(" | $$/$$ $$ | $$ | $$ | $$ \n");
+ log(" | $$$$$$/ /$$| $$$$$$$$ /$$| $$$$$$$//$$\n");
+ log(" \\____ $$$|__/|________/|__/|_______/|__/\n");
+ log(" \\__/ \n");
+ log("\n");
+}
+
+struct QbfSatPass : public Pass {
+ QbfSatPass() : Pass("qbfsat", "solve a 2QBF-SAT problem in the circuit") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" qbfsat [options] [selection]\n");
+ log("\n");
+ log("This command solves a 2QBF-SAT problem defined over the currently selected module.\n");
+ log("Existentially-quantified variables are declared by assigning a wire \"$anyconst\".\n");
+ log("Universally-quantified variables may be explicitly declared by assigning a wire\n");
+ log("\"$allconst\", but module inputs will be treated as universally-quantified variables\n");
+ log("by default.\n");
+ log("\n");
+ log(" -nocleanup\n");
+ log(" Do not delete temporary files and directories. Useful for\n");
+ log(" debugging.\n");
+ log("\n");
+ log(" -dump-final-smt2 <file>\n");
+ log(" Pass the --dump-smt2 option to yosys-smtbmc.\n");
+ log("\n");
+ log(" -assume-outputs\n");
+ log(" Add an $assume cell for the conjunction of all one-bit module output wires.\n");
+ log("\n");
+ log(" -sat\n");
+ log(" Generate an error if the solver does not return \"sat\".\n");
+ log("\n");
+ log(" -unsat\n");
+ log(" Generate an error if the solver does not return \"unsat\".\n");
+ log("\n");
+ log(" -show-smtbmc\n");
+ log(" Print the output from yosys-smtbmc.\n");
+ log("\n");
+ log(" -specialize\n");
+ log(" Replace all \"$anyconst\" cells with constant values determined by the solver.\n");
+ log("\n");
+ log(" -specialize-from-file <solution file>\n");
+ log(" Do not run the solver, but instead only attempt to replace all \"$anyconst\"\n");
+ log(" cells in the current module with values provided by the specified file.\n");
+ log("\n");
+ log(" -write-solution <solution file>\n");
+ log(" Write the assignments discovered by the solver for all \"$anyconst\" cells\n");
+ log(" to the specified file.");
+ log("\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing QBFSAT pass (solving QBF-SAT problems in the circuit).\n");
+ QbfSolveOptions opt = parse_args(args);
+ extra_args(args, opt.argidx, design);
+
+ RTLIL::Module *module = nullptr;
+ for (auto mod : design->selected_modules()) {
+ if (module)
+ log_cmd_error("Only one module must be selected for the QBF-SAT pass! (selected: %s and %s)\n", log_id(module), log_id(mod));
+ module = mod;
+ }
+ if (module == nullptr)
+ log_cmd_error("Can't perform QBF-SAT on an empty selection!\n");
+
+ log_push();
+ if (!opt.specialize_from_file) {
+ //Save the design to restore after modiyfing the current module.
+ std::string module_name = module->name.str();
+ Pass::call(design, "design -push-copy");
+
+ //Replace input wires with wires assigned $allconst cells.
+ pool<std::string> input_wires = validate_design_and_get_inputs(module, opt);
+ allconstify_inputs(module, input_wires);
+ if (opt.assume_outputs)
+ assume_miter_outputs(module);
+
+ QbfSolutionType ret = qbf_solve(module, opt);
+ Pass::call(design, "design -pop");
+ module = design->module(module_name);
+
+ if (ret.unknown)
+ log_warning("solver did not give an answer\n");
+ else if (ret.sat)
+ print_qed();
+ else
+ print_proof_failed();
+
+ if(!ret.unknown && ret.sat) {
+ if (opt.write_solution) {
+ write_solution(module, ret, opt.write_soln_soln_file);
+ }
+ if (opt.specialize) {
+ specialize(module, ret);
+ } else {
+ dump_model(module, ret);
+ }
+ if (opt.unsat)
+ log_cmd_error("expected problem to be UNSAT\n");
+ }
+ else if (!ret.unknown && !ret.sat && opt.sat)
+ log_cmd_error("expected problem to be SAT\n");
+ else if (ret.unknown && (opt.sat || opt.unsat))
+ log_cmd_error("expected problem to be %s\n", opt.sat? "SAT" : "UNSAT");
+ } else
+ specialize_from_file(module, opt.specialize_soln_file);
+ log_pop();
+ }
+} QbfSatPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index c16db0d57..766b954df 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -34,7 +34,6 @@ OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
OBJS += passes/techmap/lut2mux.o
OBJS += passes/techmap/nlutmap.o
-OBJS += passes/techmap/dffsr2dff.o
OBJS += passes/techmap/shregmap.o
OBJS += passes/techmap/deminout.o
OBJS += passes/techmap/insbuf.o
@@ -59,10 +58,10 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v
passes/techmap/techmap.o: passes/techmap/techmap.inc
ifneq ($(CONFIG),emcc)
-TARGETS += yosys-filterlib$(EXE)
+TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE)
EXTRA_OBJS += passes/techmap/filterlib.o
-yosys-filterlib$(EXE): passes/techmap/filterlib.o
+$(PROGRAM_PREFIX)yosys-filterlib$(EXE): passes/techmap/filterlib.o
$(Q) mkdir -p $(dir $@)
- $(P) $(LD) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
+ $(P) $(LD) -o $(PROGRAM_PREFIX)yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
endif
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 71ac7a110..aff0baa44 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -702,7 +702,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (dff_mode && clk_sig.empty())
log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
- std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
+ std::string tempdir_name = "/tmp/" + proc_program_prefix()+ "yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
tempdir_name = make_temp_dir(tempdir_name);
@@ -1286,7 +1286,7 @@ struct AbcPass : public Pass {
#ifdef ABCEXTERNAL
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
#else
- log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+ log(" use the specified command instead of \"<yosys-bindir>/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str());
#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
@@ -1472,7 +1472,7 @@ struct AbcPass : public Pass {
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
- std::string exe_file = proc_self_dirname() + "yosys-abc";
+ std::string exe_file = proc_self_dirname() + proc_program_prefix() + "yosys-abc";
#endif
std::string script_file, liberty_file, constr_file, clk_str;
std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
@@ -1490,8 +1490,8 @@ struct AbcPass : public Pass {
#ifdef _WIN32
#ifndef ABCEXTERNAL
- if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
- exe_file = proc_self_dirname() + "..\\yosys-abc";
+ if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix()+ "yosys-abc.exe"))
+ exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
#endif
#endif
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 9757b1539..1b3d5ff06 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -100,7 +100,7 @@ struct Abc9Pass : public ScriptPass
#ifdef ABCEXTERNAL
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
#else
- log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+ log(" use the specified command instead of \"<yosys-bindir>/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str());
#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
@@ -326,7 +326,7 @@ struct Abc9Pass : public ScriptPass
if (!active_design->selected_whole_module(mod))
log_error("Can't handle partially selected module %s!\n", log_id(mod));
- std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
+ std::string tempdir_name = "/tmp/" + proc_program_prefix() + "yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
tempdir_name = make_temp_dir(tempdir_name);
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index 898285c69..18618ff91 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -222,9 +222,9 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
abc9_script += stringf("; &ps -l; &write -n %s/output.aig", tempdir_name.c_str());
if (design->scratchpad_get_bool("abc9.verify")) {
if (dff_mode)
- abc9_script += "; verify -s";
+ abc9_script += "; &verify -s";
else
- abc9_script += "; verify";
+ abc9_script += "; &verify";
}
abc9_script += "; time";
abc9_script = add_echos_to_abc9_cmd(abc9_script);
@@ -293,7 +293,7 @@ struct Abc9ExePass : public Pass {
#ifdef ABCEXTERNAL
log(" use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
#else
- log(" use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
+ log(" use the specified command instead of \"<yosys-bindir>/%syosys-abc\" to execute ABC.\n", proc_program_prefix().c_str());
#endif
log(" This can e.g. be used to call a specific version of ABC or a wrapper.\n");
log("\n");
@@ -367,7 +367,7 @@ struct Abc9ExePass : public Pass {
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
- std::string exe_file = proc_self_dirname() + "yosys-abc";
+ std::string exe_file = proc_self_dirname() + proc_program_prefix()+ "yosys-abc";
#endif
std::string script_file, clk_str, box_file, lut_file;
std::string delay_target, lutin_shared = "-S 1", wire_delay;
@@ -383,8 +383,8 @@ struct Abc9ExePass : public Pass {
#ifdef _WIN32
#ifndef ABCEXTERNAL
- if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
- exe_file = proc_self_dirname() + "..\\yosys-abc";
+ if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc.exe"))
+ exe_file = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
#endif
#endif
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 00af36615..8ae1b51ff 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -434,6 +434,9 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
auto &t = timing.at(derived_type).required;
for (auto &conn : cell->connections_) {
auto port_wire = inst_module->wire(conn.first);
+ if (!port_wire)
+ log_error("Port %s in cell %s (type %s) of module %s does not actually exist",
+ log_id(conn.first), log_id(cell->name), log_id(cell->type), log_id(module->name));
if (!port_wire->port_input)
continue;
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index 0424ce434..35645582b 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -154,9 +154,11 @@ struct DffinitPass : public Pass {
value = Const(low_string);
}
- log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second),
- log_id(it.first), log_signal(sig), log_signal(value));
- cell->setParam(it.second, value);
+ if (value.size() != 0) {
+ log("Setting %s.%s.%s (port=%s, net=%s) to %s.\n", log_id(module), log_id(cell), log_id(it.second),
+ log_id(it.first), log_signal(sig), log_signal(value));
+ cell->setParam(it.second, value);
+ }
}
}
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index b15109cd3..aa344cf8a 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -78,7 +78,7 @@ static void logmap_all()
static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol)
{
- if (cell == NULL || attr == NULL || attr->value.empty())
+ if (cell == nullptr || attr == nullptr || attr->value.empty())
return false;
std::string value = attr->value;
@@ -117,7 +117,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode)
{
- LibertyAst *best_cell = NULL;
+ LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
bool best_cell_noninv = false;
@@ -132,11 +132,11 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
continue;
LibertyAst *dn = cell->find("dont_use");
- if (dn != NULL && dn->value == "true")
+ if (dn != nullptr && dn->value == "true")
continue;
LibertyAst *ff = cell->find("ff");
- if (ff == NULL)
+ if (ff == nullptr)
continue;
std::string cell_clk_pin, cell_rst_pin, cell_next_pin;
@@ -163,7 +163,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
double area = 0;
LibertyAst *ar = cell->find("area");
- if (ar != NULL && !ar->value.empty())
+ if (ar != nullptr && !ar->value.empty())
area = atof(ar->value.c_str());
int num_pins = 0;
@@ -175,7 +175,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
continue;
LibertyAst *dir = pin->find("direction");
- if (dir == NULL || dir->value == "internal")
+ if (dir == nullptr || dir->value == "internal")
continue;
num_pins++;
@@ -183,7 +183,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
goto continue_cell_loop;
LibertyAst *func = pin->find("function");
- if (dir->value == "output" && func != NULL) {
+ if (dir->value == "output" && func != nullptr) {
std::string value = func->value;
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))
value.erase(pos, 1);
@@ -205,10 +205,10 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
this_cell_ports[pin->args[0]] = 0;
}
- if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output))))
+ if (!found_output || (best_cell != nullptr && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output))))
continue;
- if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area)
+ if (best_cell != nullptr && num_pins == best_cell_pins && area > best_cell_area)
continue;
best_cell = cell;
@@ -219,7 +219,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
continue_cell_loop:;
}
- if (best_cell != NULL) {
+ if (best_cell != nullptr) {
log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str());
if (prepare_mode) {
@@ -238,7 +238,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode)
{
- LibertyAst *best_cell = NULL;
+ LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
bool best_cell_noninv = false;
@@ -253,11 +253,11 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
continue;
LibertyAst *dn = cell->find("dont_use");
- if (dn != NULL && dn->value == "true")
+ if (dn != nullptr && dn->value == "true")
continue;
LibertyAst *ff = cell->find("ff");
- if (ff == NULL)
+ if (ff == nullptr)
continue;
std::string cell_clk_pin, cell_set_pin, cell_clr_pin, cell_next_pin;
@@ -280,7 +280,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
double area = 0;
LibertyAst *ar = cell->find("area");
- if (ar != NULL && !ar->value.empty())
+ if (ar != nullptr && !ar->value.empty())
area = atof(ar->value.c_str());
int num_pins = 0;
@@ -292,7 +292,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
continue;
LibertyAst *dir = pin->find("direction");
- if (dir == NULL || dir->value == "internal")
+ if (dir == nullptr || dir->value == "internal")
continue;
num_pins++;
@@ -300,7 +300,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
goto continue_cell_loop;
LibertyAst *func = pin->find("function");
- if (dir->value == "output" && func != NULL) {
+ if (dir->value == "output" && func != nullptr) {
std::string value = func->value;
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))
value.erase(pos, 1);
@@ -322,10 +322,10 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
this_cell_ports[pin->args[0]] = 0;
}
- if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output))))
+ if (!found_output || (best_cell != nullptr && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output))))
continue;
- if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area)
+ if (best_cell != nullptr && num_pins == best_cell_pins && area > best_cell_area)
continue;
best_cell = cell;
@@ -336,7 +336,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
continue_cell_loop:;
}
- if (best_cell != NULL) {
+ if (best_cell != nullptr) {
log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n",
best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str());
if (prepare_mode) {
@@ -481,11 +481,11 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
SigMap sigmap(module);
std::vector<RTLIL::Cell*> cell_list;
- for (auto &it : module->cells_) {
- if (design->selected(module, it.second) && cell_mappings.count(it.second->type) > 0)
- cell_list.push_back(it.second);
- if (it.second->type == ID($_NOT_))
- notmap[sigmap(it.second->getPort(ID::A))].insert(it.second);
+ for (auto cell : module->cells()) {
+ if (design->selected(module, cell) && cell_mappings.count(cell->type) > 0)
+ cell_list.push_back(cell);
+ if (cell->type == ID($_NOT_))
+ notmap[sigmap(cell->getPort(ID::A))].insert(cell);
}
std::map<std::string, int> stats;
@@ -663,9 +663,9 @@ struct DfflibmapPass : public Pass {
log(" final dff cell mappings:\n");
logmap_all();
- for (auto &it : design->modules_)
- if (design->selected(it.second) && !it.second->get_blackbox_attribute())
- dfflibmap(design, it.second, prepare_mode);
+ for (auto module : design->selected_modules())
+ if (!module->get_blackbox_attribute())
+ dfflibmap(design, module, prepare_mode);
cell_mappings.clear();
}
diff --git a/passes/techmap/dffsr2dff.cc b/passes/techmap/dffsr2dff.cc
deleted file mode 100644
index 4a3ddaf73..000000000
--- a/passes/techmap/dffsr2dff.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * 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"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-void dffsr_worker(SigMap &sigmap, Module *module, Cell *cell)
-{
- if (cell->type == ID($dffsr))
- {
- int width = cell->getParam(ID::WIDTH).as_int();
- bool setpol = cell->getParam(ID::SET_POLARITY).as_bool();
- bool clrpol = cell->getParam(ID::CLR_POLARITY).as_bool();
-
- SigBit setunused = setpol ? State::S0 : State::S1;
- SigBit clrunused = clrpol ? State::S0 : State::S1;
-
- SigSpec setsig = sigmap(cell->getPort(ID::SET));
- SigSpec clrsig = sigmap(cell->getPort(ID::CLR));
-
- Const reset_val;
- SigSpec setctrl, clrctrl;
-
- for (int i = 0; i < width; i++)
- {
- SigBit setbit = setsig[i], clrbit = clrsig[i];
-
- if (setbit == setunused) {
- clrctrl.append(clrbit);
- reset_val.bits.push_back(State::S0);
- continue;
- }
-
- if (clrbit == clrunused) {
- setctrl.append(setbit);
- reset_val.bits.push_back(State::S1);
- continue;
- }
-
- return;
- }
-
- setctrl.sort_and_unify();
- clrctrl.sort_and_unify();
-
- if (GetSize(setctrl) > 1 || GetSize(clrctrl) > 1)
- return;
-
- if (GetSize(setctrl) == 0 && GetSize(clrctrl) == 0)
- return;
-
- if (GetSize(setctrl) == 1 && GetSize(clrctrl) == 1) {
- if (setpol != clrpol)
- return;
- if (setctrl != clrctrl)
- return;
- }
-
- log("Converting %s cell %s.%s to $adff.\n", log_id(cell->type), log_id(module), log_id(cell));
-
- if (GetSize(setctrl) == 1) {
- cell->setPort(ID::ARST, setctrl);
- cell->setParam(ID::ARST_POLARITY, setpol);
- } else {
- cell->setPort(ID::ARST, clrctrl);
- cell->setParam(ID::ARST_POLARITY, clrpol);
- }
-
- cell->type = ID($adff);
- cell->unsetPort(ID::SET);
- cell->unsetPort(ID::CLR);
- cell->setParam(ID::ARST_VALUE, reset_val);
- cell->unsetParam(ID::SET_POLARITY);
- cell->unsetParam(ID::CLR_POLARITY);
-
- return;
- }
-
- if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
- {
- char clkpol = cell->type.c_str()[8];
- char setpol = cell->type.c_str()[9];
- char clrpol = cell->type.c_str()[10];
-
- SigBit setbit = sigmap(cell->getPort(ID::S));
- SigBit clrbit = sigmap(cell->getPort(ID::R));
-
- SigBit setunused = setpol == 'P' ? State::S0 : State::S1;
- SigBit clrunused = clrpol == 'P' ? State::S0 : State::S1;
-
- IdString oldtype = cell->type;
-
- if (setbit == setunused) {
- cell->type = stringf("$_DFF_%c%c0_", clkpol, clrpol);
- cell->unsetPort(ID::S);
- goto converted_gate;
- }
-
- if (clrbit == clrunused) {
- cell->type = stringf("$_DFF_%c%c1_", clkpol, setpol);
- cell->setPort(ID::R, cell->getPort(ID::S));
- cell->unsetPort(ID::S);
- goto converted_gate;
- }
-
- return;
-
- converted_gate:
- log("Converting %s cell %s.%s to %s.\n", log_id(oldtype), log_id(module), log_id(cell), log_id(cell->type));
- return;
- }
-}
-
-void adff_worker(SigMap &sigmap, Module *module, Cell *cell)
-{
- if (cell->type == ID($adff))
- {
- bool rstpol = cell->getParam(ID::ARST_POLARITY).as_bool();
- SigBit rstunused = rstpol ? State::S0 : State::S1;
- SigSpec rstsig = sigmap(cell->getPort(ID::ARST));
-
- if (rstsig != rstunused)
- return;
-
- log("Converting %s cell %s.%s to $dff.\n", log_id(cell->type), log_id(module), log_id(cell));
-
- cell->type = ID($dff);
- cell->unsetPort(ID::ARST);
- cell->unsetParam(ID::ARST_VALUE);
- cell->unsetParam(ID::ARST_POLARITY);
-
- return;
- }
-
- if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
- {
- char clkpol = cell->type.c_str()[6];
- char rstpol = cell->type.c_str()[7];
-
- SigBit rstbit = sigmap(cell->getPort(ID::R));
- SigBit rstunused = rstpol == 'P' ? State::S0 : State::S1;
-
- if (rstbit != rstunused)
- return;
-
- IdString newtype = stringf("$_DFF_%c_", clkpol);
- log("Converting %s cell %s.%s to %s.\n", log_id(cell->type), log_id(module), log_id(cell), log_id(newtype));
-
- cell->type = newtype;
- cell->unsetPort(ID::R);
-
- return;
- }
-}
-
-struct Dffsr2dffPass : public Pass {
- Dffsr2dffPass() : Pass("dffsr2dff", "convert DFFSR cells to simpler FF cell types") { }
- void help() YS_OVERRIDE
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" dffsr2dff [options] [selection]\n");
- log("\n");
- log("This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) and ADFF cells ($adff,\n");
- log("$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
- {
- log_header(design, "Executing DFFSR2DFF pass (mapping DFFSR cells to simpler FFs).\n");
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++)
- {
- // if (args[argidx] == "-v") {
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- for (auto module : design->selected_modules()) {
- SigMap sigmap(module);
- for (auto cell : module->selected_cells()) {
- dffsr_worker(sigmap, module, cell);
- adff_worker(sigmap, module, cell);
- }
- }
- }
-} Dffsr2dffPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index aea958f0f..f29044790 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -29,8 +29,6 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-using RTLIL::id2cstr;
-
class SubCircuitSolver : public SubCircuit::Solver
{
public:
@@ -121,8 +119,8 @@ public:
if (wire_attr.size() > 0)
{
- RTLIL::Wire *lastNeedleWire = NULL;
- RTLIL::Wire *lastHaystackWire = NULL;
+ RTLIL::Wire *lastNeedleWire = nullptr;
+ RTLIL::Wire *lastHaystackWire = nullptr;
dict<RTLIL::IdString, RTLIL::Const> emptyAttr;
for (auto &conn : needleCell->connections())
@@ -149,27 +147,27 @@ struct bit_ref_t {
int bit;
};
-bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL,
- int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL)
+bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = nullptr,
+ int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = nullptr)
{
SigMap sigmap(mod);
std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref;
if (sel && !sel->selected(mod)) {
- log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name));
+ log(" Skipping module %s as it is not selected.\n", log_id(mod->name));
return false;
}
if (mod->processes.size() > 0) {
- log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name));
+ log(" Skipping module %s as it contains unprocessed processes.\n", log_id(mod->name));
return false;
}
if (constports) {
- graph.createNode("$const$0", "$const$0", NULL, true);
- graph.createNode("$const$1", "$const$1", NULL, true);
- graph.createNode("$const$x", "$const$x", NULL, true);
- graph.createNode("$const$z", "$const$z", NULL, true);
+ graph.createNode("$const$0", "$const$0", nullptr, true);
+ graph.createNode("$const$1", "$const$1", nullptr, true);
+ graph.createNode("$const$x", "$const$x", nullptr, true);
+ graph.createNode("$const$z", "$const$z", nullptr, true);
graph.createPort("$const$0", "\\Y", 1);
graph.createPort("$const$1", "\\Y", 1);
graph.createPort("$const$x", "\\Y", 1);
@@ -182,28 +180,26 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports,
std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count;
if (max_fanout > 0)
- for (auto &cell_it : mod->cells_)
+ for (auto cell : mod->cells())
{
- RTLIL::Cell *cell = cell_it.second;
if (!sel || sel->selected(mod, cell))
for (auto &conn : cell->connections()) {
RTLIL::SigSpec conn_sig = conn.second;
sigmap.apply(conn_sig);
for (auto &bit : conn_sig)
- if (bit.wire != NULL)
+ if (bit.wire != nullptr)
sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++;
}
}
// create graph nodes from cells
- for (auto &cell_it : mod->cells_)
+ for (auto cell : mod->cells())
{
- RTLIL::Cell *cell = cell_it.second;
if (sel && !sel->selected(mod, cell))
continue;
std::string type = cell->type.str();
- if (sel == NULL && type.compare(0, 2, "\\$") == 0)
+ if (sel == nullptr && type.compare(0, 2, "\\$") == 0)
type = type.substr(1);
graph.createNode(cell->name.str(), type, (void*)cell);
@@ -221,7 +217,7 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports,
{
auto &bit = conn_sig[i];
- if (bit.wire == NULL) {
+ if (bit.wire == nullptr) {
if (constports) {
std::string node = "$const$x";
if (bit == RTLIL::State::S0) node = "$const$0";
@@ -253,9 +249,8 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports,
}
// mark external signals (used in non-selected cells)
- for (auto &cell_it : mod->cells_)
+ for (auto cell : mod->cells())
{
- RTLIL::Cell *cell = cell_it.second;
if (sel && !sel->selected(mod, cell))
for (auto &conn : cell->connections())
{
@@ -271,9 +266,8 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports,
}
// mark external signals (used in module ports)
- for (auto &wire_it : mod->wires_)
+ for (auto wire : mod->wires())
{
- RTLIL::Wire *wire = wire_it.second;
if (wire->port_id > 0)
{
RTLIL::SigSpec conn_sig(wire);
@@ -300,8 +294,7 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit:
RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name);
// create cell ports
- for (auto &it : needle->wires_) {
- RTLIL::Wire *wire = it.second;
+ for (auto wire : needle->wires()) {
if (wire->port_id > 0) {
for (int i = 0; i < wire->width; i++)
sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i));
@@ -316,7 +309,7 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit:
RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;
- if (needle_cell == NULL)
+ if (needle_cell == nullptr)
continue;
for (auto &conn : needle_cell->connections()) {
@@ -587,7 +580,7 @@ struct ExtractPass : public Pass {
if (map_filenames.empty() && mine_outfile.empty())
log_cmd_error("Missing option -map <verilog_or_ilang_file> or -mine <output_ilang_file>.\n");
- RTLIL::Design *map = NULL;
+ RTLIL::Design *map = nullptr;
if (!mine_mode)
{
@@ -630,24 +623,24 @@ struct ExtractPass : public Pass {
log_header(design, "Creating graphs for SubCircuit library.\n");
if (!mine_mode)
- for (auto &mod_it : map->modules_) {
+ for (auto module : map->modules()) {
SubCircuit::Graph mod_graph;
- std::string graph_name = "needle_" + RTLIL::unescape_id(mod_it.first);
+ std::string graph_name = "needle_" + RTLIL::unescape_id(module->name);
log("Creating needle graph %s.\n", graph_name.c_str());
- if (module2graph(mod_graph, mod_it.second, constports)) {
+ if (module2graph(mod_graph, module, constports)) {
solver.addGraph(graph_name, mod_graph);
- needle_map[graph_name] = mod_it.second;
- needle_list.push_back(mod_it.second);
+ needle_map[graph_name] = module;
+ needle_list.push_back(module);
}
}
- for (auto &mod_it : design->modules_) {
+ for (auto module : design->modules()) {
SubCircuit::Graph mod_graph;
- std::string graph_name = "haystack_" + RTLIL::unescape_id(mod_it.first);
+ std::string graph_name = "haystack_" + RTLIL::unescape_id(module->name);
log("Creating haystack graph %s.\n", graph_name.c_str());
- if (module2graph(mod_graph, mod_it.second, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : NULL)) {
+ if (module2graph(mod_graph, module, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : nullptr)) {
solver.addGraph(graph_name, mod_graph);
- haystack_map[graph_name] = mod_it.second;
+ haystack_map[graph_name] = module;
}
}
@@ -680,7 +673,7 @@ struct ExtractPass : public Pass {
}
RTLIL::Cell *new_cell = replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result);
design->select(haystack_map.at(result.haystackGraphId), new_cell);
- log(" new cell: %s\n", id2cstr(new_cell->name));
+ log(" new cell: %s\n", log_id(new_cell->name));
}
}
}
@@ -697,12 +690,12 @@ struct ExtractPass : public Pass {
for (auto &result: results)
{
log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
- log(" primary match in %s:", id2cstr(haystack_map.at(result.graphId)->name));
+ log(" primary match in %s:", log_id(haystack_map.at(result.graphId)->name));
for (auto &node : result.nodes)
log(" %s", RTLIL::unescape_id(node.nodeId).c_str());
log("\n");
for (auto &it : result.matchesPerGraph)
- log(" matches in %s: %d\n", id2cstr(haystack_map.at(it.first)->name), it.second);
+ log(" matches in %s: %d\n", log_id(haystack_map.at(it.first)->name), it.second);
RTLIL::Module *mod = haystack_map.at(result.graphId);
std::set<RTLIL::Cell*> cells;
@@ -717,12 +710,12 @@ struct ExtractPass : public Pass {
for (auto &conn : cell->connections()) {
RTLIL::SigSpec sig = sigmap(conn.second);
for (auto &chunk : sig.chunks())
- if (chunk.wire != NULL)
+ if (chunk.wire != nullptr)
wires.insert(chunk.wire);
}
RTLIL::Module *newMod = new RTLIL::Module;
- newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, id2cstr(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits);
+ newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, log_id(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits);
map->add(newMod);
for (auto wire : wires) {
@@ -739,8 +732,8 @@ struct ExtractPass : public Pass {
for (auto &conn : cell->connections()) {
std::vector<SigChunk> chunks = sigmap(conn.second);
for (auto &chunk : chunks)
- if (chunk.wire != NULL)
- chunk.wire = newMod->wires_.at(chunk.wire->name);
+ if (chunk.wire != nullptr)
+ chunk.wire = newMod->wire(chunk.wire->name);
newCell->setPort(conn.first, chunks);
}
}
diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc
index 9ec651aef..5aeb5ea79 100644
--- a/passes/techmap/hilomap.cc
+++ b/passes/techmap/hilomap.cc
@@ -105,13 +105,9 @@ struct HilomapPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &it : design->modules_)
+ for (auto mod : design->selected_modules())
{
- module = it.second;
-
- if (!design->selected(module))
- continue;
-
+ module = mod;
last_hi = RTLIL::State::Sm;
last_lo = RTLIL::State::Sm;
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 518afa1a7..a554be257 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -1282,7 +1282,7 @@ struct TechmapPass : public Pass {
if (fn.compare(0, 1, "%") == 0) {
if (!saved_designs.count(fn.substr(1))) {
delete map;
- log_cmd_error("Can't saved design `%s'.\n", fn.c_str()+1);
+ log_cmd_error("Can't open saved design `%s'.\n", fn.c_str()+1);
}
for (auto mod : saved_designs.at(fn.substr(1))->modules())
if (!map->has(mod->name))
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index a427c4987..74604ba3b 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -57,8 +57,7 @@ struct ZinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> initbits;
- pool<SigBit> donebits;
+ dict<SigBit, std::pair<State,SigBit>> initbits;
for (auto wire : module->selected_wires())
{
@@ -67,7 +66,6 @@ struct ZinitPass : public Pass {
SigSpec wirebits = sigmap(wire);
Const initval = wire->attributes.at(ID::init);
- wire->attributes.erase(ID::init);
for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
{
@@ -78,24 +76,35 @@ struct ZinitPass : public Pass {
continue;
if (initbits.count(bit)) {
- if (initbits.at(bit) != val)
+ if (initbits.at(bit).first != val)
log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit)));
+ log_signal(val), log_signal(initbits.at(bit).first));
continue;
}
- initbits[bit] = val;
+ initbits[bit] = std::make_pair(val,SigBit(wire,i));
}
}
pool<IdString> dff_types = {
- ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($adff),
+ // FIXME: It would appear that supporting
+ // $dffsr/$_DFFSR_* would require a new
+ // cell type where S has priority over R
+ ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff),
ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
- ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
+ /*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
+ ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)
+ ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
+ // Async set/reset
+ ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
+ ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
+ // Sync set/reset
+ ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
+ ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_),
+ ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
+ ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)
};
for (auto cell : module->selected_cells())
@@ -113,8 +122,10 @@ struct ZinitPass : public Pass {
for (int i = 0; i < GetSize(sig_q); i++) {
if (initbits.count(sig_q[i])) {
- initval.bits.push_back(initbits.at(sig_q[i]));
- donebits.insert(sig_q[i]);
+ const auto &d = initbits.at(sig_q[i]);
+ initval.bits.push_back(d.first);
+ const auto &b = d.second;
+ b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
} else
initval.bits.push_back(all_mode ? State::S0 : State::Sx);
}
@@ -123,11 +134,11 @@ struct ZinitPass : public Pass {
initwire->attributes[ID::init] = initval;
for (int i = 0; i < GetSize(initwire); i++)
- if (initval.bits.at(i) == State::S1)
+ if (initval[i] == State::S1)
{
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
- initwire->attributes[ID::init].bits.at(i) = State::S0;
+ initwire->attributes[ID::init][i] = State::S0;
}
else
{
@@ -139,11 +150,36 @@ struct ZinitPass : public Pass {
cell->setPort(ID::D, sig_d);
cell->setPort(ID::Q, initwire);
- }
- for (auto &it : initbits)
- if (donebits.count(it.first) == 0)
- log_error("Failed to handle init bit %s = %s.\n", log_signal(it.first), log_signal(it.second));
+ if (cell->type == ID($adff)) {
+ auto val = cell->getParam(ID::ARST_VALUE);
+ for (int i = 0; i < GetSize(initwire); i++)
+ if (initval[i] == State::S1)
+ val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
+ cell->setParam(ID::ARST_VALUE, std::move(val));
+ }
+ else if (initval == State::S1) {
+ std::string t = cell->type.str();
+ if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
+ ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
+ {
+ t[8] = (t[8] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
+ ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
+ ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
+ ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_)))
+ {
+ t[10] = (t[10] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
+ ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)))
+ {
+ t[11] = (t[11] == '0' ? '1' : '0');
+ }
+ cell->type = t;
+ }
+ }
}
}
} ZinitPass;
diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc
index 1f071bd69..42e8a61ea 100644
--- a/passes/tests/test_autotb.cc
+++ b/passes/tests/test_autotb.cc
@@ -85,7 +85,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s
f << stringf("reg [31:0] xorshift128_x = 123456789;\n");
f << stringf("reg [31:0] xorshift128_y = 362436069;\n");
f << stringf("reg [31:0] xorshift128_z = 521288629;\n");
- f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(NULL)));
+ f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(nullptr)));
f << stringf("reg [31:0] xorshift128_t;\n\n");
f << stringf("task xorshift128;\n");
f << stringf("begin\n");
@@ -97,22 +97,19 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s
f << stringf("end\n");
f << stringf("endtask\n\n");
- for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it)
+ for (auto mod : design->modules())
{
std::map<std::string, int> signal_in;
std::map<std::string, std::string> signal_const;
std::map<std::string, int> signal_clk;
std::map<std::string, int> signal_out;
- RTLIL::Module *mod = it->second;
-
if (mod->get_bool_attribute(ID::gentb_skip))
continue;
int count_ports = 0;
- log("Generating test bench for module `%s'.\n", it->first.c_str());
- for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) {
- RTLIL::Wire *wire = it2->second;
+ log("Generating test bench for module `%s'.\n", mod->name.c_str());
+ for (auto wire : mod->wires()) {
if (wire->port_output) {
count_ports++;
signal_out[idy("sig", mod->name.str(), wire->name.str())] = wire->width;
@@ -140,8 +137,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s
}
}
f << stringf("%s %s(\n", id(mod->name.str()).c_str(), idy("uut", mod->name.str()).c_str());
- for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) {
- RTLIL::Wire *wire = it2->second;
+ for (auto wire : mod->wires()) {
if (wire->port_output || wire->port_input)
f << stringf("\t.%s(%s)%s\n", id(wire->name.str()).c_str(),
idy("sig", mod->name.str(), wire->name.str()).c_str(), --count_ports ? "," : "");
@@ -312,9 +308,9 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s
f << stringf("\t// $dumpfile(\"testbench.vcd\");\n");
f << stringf("\t// $dumpvars(0, testbench);\n");
f << stringf("\tfile = $fopen(`outfile);\n");
- for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it)
- if (!it->second->get_bool_attribute(ID::gentb_skip))
- f << stringf("\t%s;\n", idy(it->first.str(), "test").c_str());
+ for (auto module : design->modules())
+ if (!module->get_bool_attribute(ID::gentb_skip))
+ f << stringf("\t%s;\n", idy(module->name.str(), "test").c_str());
f << stringf("\t$fclose(file);\n");
f << stringf("\t$finish;\n");
f << stringf("end\n\n");