aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/cmds/Makefile.inc1
-rw-r--r--passes/cmds/add.cc4
-rw-r--r--passes/cmds/autoname.cc4
-rw-r--r--passes/cmds/blackbox.cc30
-rw-r--r--passes/cmds/bugpoint.cc4
-rw-r--r--passes/cmds/check.cc4
-rw-r--r--passes/cmds/chformal.cc4
-rw-r--r--passes/cmds/chtype.cc4
-rw-r--r--passes/cmds/connect.cc4
-rw-r--r--passes/cmds/connwrappers.cc4
-rw-r--r--passes/cmds/copy.cc4
-rw-r--r--passes/cmds/cover.cc4
-rw-r--r--passes/cmds/delete.cc4
-rw-r--r--passes/cmds/design.cc6
-rw-r--r--passes/cmds/edgetypes.cc4
-rw-r--r--passes/cmds/exec.cc4
-rw-r--r--passes/cmds/logcmd.cc4
-rw-r--r--passes/cmds/logger.cc43
-rw-r--r--passes/cmds/ltp.cc4
-rw-r--r--passes/cmds/plugin.cc4
-rw-r--r--passes/cmds/portlist.cc4
-rw-r--r--passes/cmds/printattrs.cc90
-rw-r--r--passes/cmds/qwp.cc4
-rw-r--r--passes/cmds/rename.cc4
-rw-r--r--passes/cmds/scatter.cc4
-rw-r--r--passes/cmds/scc.cc4
-rw-r--r--passes/cmds/scratchpad.cc4
-rw-r--r--passes/cmds/select.cc45
-rw-r--r--passes/cmds/setattr.cc16
-rw-r--r--passes/cmds/setundef.cc4
-rw-r--r--passes/cmds/show.cc4
-rw-r--r--passes/cmds/splice.cc4
-rw-r--r--passes/cmds/splitnets.cc39
-rw-r--r--passes/cmds/stat.cc11
-rw-r--r--passes/cmds/tee.cc4
-rw-r--r--passes/cmds/torder.cc4
-rw-r--r--passes/cmds/trace.cc20
-rw-r--r--passes/cmds/write_file.cc4
-rw-r--r--passes/equiv/equiv_add.cc4
-rw-r--r--passes/equiv/equiv_induct.cc4
-rw-r--r--passes/equiv/equiv_make.cc4
-rw-r--r--passes/equiv/equiv_mark.cc4
-rw-r--r--passes/equiv/equiv_miter.cc4
-rw-r--r--passes/equiv/equiv_opt.cc8
-rw-r--r--passes/equiv/equiv_purge.cc4
-rw-r--r--passes/equiv/equiv_remove.cc4
-rw-r--r--passes/equiv/equiv_simple.cc4
-rw-r--r--passes/equiv/equiv_status.cc4
-rw-r--r--passes/equiv/equiv_struct.cc4
-rw-r--r--passes/fsm/fsm.cc4
-rw-r--r--passes/fsm/fsm_detect.cc4
-rw-r--r--passes/fsm/fsm_expand.cc4
-rw-r--r--passes/fsm/fsm_export.cc4
-rw-r--r--passes/fsm/fsm_extract.cc6
-rw-r--r--passes/fsm/fsm_info.cc4
-rw-r--r--passes/fsm/fsm_map.cc4
-rw-r--r--passes/fsm/fsm_opt.cc4
-rw-r--r--passes/fsm/fsm_recode.cc4
-rw-r--r--passes/hierarchy/hierarchy.cc27
-rw-r--r--passes/hierarchy/submod.cc4
-rw-r--r--passes/hierarchy/uniquify.cc4
-rw-r--r--passes/memory/memory.cc4
-rw-r--r--passes/memory/memory_bram.cc4
-rw-r--r--passes/memory/memory_collect.cc4
-rw-r--r--passes/memory/memory_dff.cc4
-rw-r--r--passes/memory/memory_map.cc4
-rw-r--r--passes/memory/memory_memx.cc4
-rw-r--r--passes/memory/memory_nordff.cc4
-rw-r--r--passes/memory/memory_share.cc6
-rw-r--r--passes/memory/memory_unpack.cc4
-rw-r--r--passes/opt/muxpack.cc4
-rw-r--r--passes/opt/opt.cc21
-rw-r--r--passes/opt/opt_clean.cc8
-rw-r--r--passes/opt/opt_demorgan.cc4
-rw-r--r--passes/opt/opt_expr.cc99
-rw-r--r--passes/opt/opt_lut.cc4
-rw-r--r--passes/opt/opt_lut_ins.cc4
-rw-r--r--passes/opt/opt_mem.cc4
-rw-r--r--passes/opt/opt_merge.cc8
-rw-r--r--passes/opt/opt_muxtree.cc4
-rw-r--r--passes/opt/opt_reduce.cc4
-rw-r--r--passes/opt/opt_rmdff.cc4
-rw-r--r--passes/opt/opt_share.cc8
-rw-r--r--passes/opt/pmux2shiftx.cc14
-rw-r--r--passes/opt/rmports.cc4
-rw-r--r--passes/opt/share.cc10
-rw-r--r--passes/opt/wreduce.cc34
-rw-r--r--passes/pmgen/ice40_dsp.cc4
-rw-r--r--passes/pmgen/ice40_wrapcarry.cc4
-rw-r--r--passes/pmgen/peepopt.cc4
-rw-r--r--passes/pmgen/pmgen.py20
-rw-r--r--passes/pmgen/test_pmgen.cc4
-rw-r--r--passes/pmgen/xilinx_dsp.cc4
-rw-r--r--passes/pmgen/xilinx_srl.cc4
-rw-r--r--passes/proc/proc.cc4
-rw-r--r--passes/proc/proc_arst.cc4
-rw-r--r--passes/proc/proc_clean.cc4
-rw-r--r--passes/proc/proc_dff.cc4
-rw-r--r--passes/proc/proc_dlatch.cc4
-rw-r--r--passes/proc/proc_init.cc4
-rw-r--r--passes/proc/proc_mux.cc4
-rw-r--r--passes/proc/proc_prune.cc4
-rw-r--r--passes/proc/proc_rmdead.cc4
-rw-r--r--passes/sat/assertpmux.cc4
-rw-r--r--passes/sat/async2sync.cc4
-rw-r--r--passes/sat/clk2fflogic.cc4
-rw-r--r--passes/sat/cutpoint.cc23
-rw-r--r--passes/sat/eval.cc4
-rw-r--r--passes/sat/expose.cc34
-rw-r--r--passes/sat/fmcombine.cc7
-rw-r--r--passes/sat/fminit.cc4
-rw-r--r--passes/sat/freduce.cc4
-rw-r--r--passes/sat/miter.cc4
-rw-r--r--passes/sat/mutate.cc4
-rw-r--r--passes/sat/qbfsat.cc654
-rw-r--r--passes/sat/qbfsat.h252
-rw-r--r--passes/sat/sat.cc12
-rw-r--r--passes/sat/sim.cc9
-rw-r--r--passes/sat/supercover.cc4
-rw-r--r--passes/techmap/.gitignore1
-rw-r--r--passes/techmap/Makefile.inc14
-rw-r--r--passes/techmap/abc.cc4
-rw-r--r--passes/techmap/abc9.cc135
-rw-r--r--passes/techmap/abc9_exe.cc4
-rw-r--r--passes/techmap/abc9_ops.cc1205
-rw-r--r--passes/techmap/aigmap.cc4
-rw-r--r--passes/techmap/alumacc.cc4
-rw-r--r--passes/techmap/attrmap.cc16
-rw-r--r--passes/techmap/attrmvcp.cc4
-rw-r--r--passes/techmap/clkbufmap.cc4
-rw-r--r--passes/techmap/deminout.cc4
-rw-r--r--passes/techmap/dff2dffe.cc44
-rw-r--r--passes/techmap/dff2dffs.cc22
-rw-r--r--passes/techmap/dffinit.cc4
-rw-r--r--passes/techmap/dfflegalize.cc1356
-rw-r--r--passes/techmap/dfflibmap.cc14
-rw-r--r--passes/techmap/extract.cc4
-rw-r--r--passes/techmap/extract_counter.cc14
-rw-r--r--passes/techmap/extract_fa.cc4
-rw-r--r--passes/techmap/extract_reduce.cc4
-rw-r--r--passes/techmap/extractinv.cc4
-rw-r--r--passes/techmap/flatten.cc333
-rw-r--r--passes/techmap/flowmap.cc4
-rw-r--r--passes/techmap/hilomap.cc4
-rw-r--r--passes/techmap/insbuf.cc4
-rw-r--r--passes/techmap/iopadmap.cc4
-rw-r--r--passes/techmap/lut2mux.cc4
-rw-r--r--passes/techmap/maccmap.cc4
-rw-r--r--passes/techmap/muxcover.cc4
-rw-r--r--passes/techmap/nlutmap.cc4
-rw-r--r--passes/techmap/pmuxtree.cc4
-rw-r--r--passes/techmap/shregmap.cc4
-rw-r--r--passes/techmap/simplemap.cc151
-rw-r--r--passes/techmap/simplemap.h2
-rw-r--r--passes/techmap/techmap.cc763
-rw-r--r--passes/techmap/tribuf.cc4
-rw-r--r--passes/techmap/zinit.cc62
-rw-r--r--passes/tests/test_abcloop.cc8
-rw-r--r--passes/tests/test_autotb.cc4
-rw-r--r--passes/tests/test_cell.cc16
160 files changed, 4435 insertions, 1734 deletions
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index a88980eaf..53bfd40c6 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -39,3 +39,4 @@ OBJS += passes/cmds/bugpoint.o
endif
OBJS += passes/cmds/scratchpad.o
OBJS += passes/cmds/logger.o
+OBJS += passes/cmds/printattrs.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index 91f8c2add..a2f4a9100 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -116,7 +116,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
struct AddPass : public Pass {
AddPass() : Pass("add", "add objects to the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -150,7 +150,7 @@ struct AddPass : public Pass {
log("Add module[s] with the specified name[s].\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) override
{
std::string command;
std::string arg_name;
diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc
index 50632201e..28d4012c4 100644
--- a/passes/cmds/autoname.cc
+++ b/passes/cmds/autoname.cc
@@ -92,7 +92,7 @@ int autoname_worker(Module *module)
struct AutonamePass : public Pass {
AutonamePass() : Pass("autoname", "automatically assign names to objects") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -102,7 +102,7 @@ struct AutonamePass : public Pass {
log("with $-prefix).\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) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc
index 5c0405f15..08a635514 100644
--- a/passes/cmds/blackbox.cc
+++ b/passes/cmds/blackbox.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct BlackboxPass : public Pass {
BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -34,7 +34,7 @@ struct BlackboxPass : public Pass {
log("module attribute).\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) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -48,31 +48,7 @@ struct BlackboxPass : public Pass {
for (auto module : design->selected_whole_modules_warn())
{
- pool<Cell*> remove_cells;
- pool<Wire*> remove_wires;
-
- for (auto cell : module->cells())
- remove_cells.insert(cell);
-
- for (auto wire : module->wires())
- if (wire->port_id == 0)
- remove_wires.insert(wire);
-
- for (auto it = module->memories.begin(); it != module->memories.end(); ++it)
- delete it->second;
- module->memories.clear();
-
- for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
- delete it->second;
- module->processes.clear();
-
- module->new_connections(std::vector<RTLIL::SigSig>());
-
- for (auto cell : remove_cells)
- module->remove(cell);
-
- module->remove(remove_wires);
-
+ module->makeblackbox();
module->set_bool_attribute(ID::blackbox);
}
}
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index 00aac596f..98d42aa83 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN
struct BugpointPass : public Pass {
BugpointPass() : Pass("bugpoint", "minimize testcases") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -313,7 +313,7 @@ struct BugpointPass : public Pass {
return nullptr;
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
string yosys_cmd = "yosys", script, grep;
bool fast = false, clean = false;
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index ba29e6f4b..a8b5362b3 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CheckPass : public Pass {
CheckPass() : Pass("check", "check for obvious problems in the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -61,7 +61,7 @@ struct CheckPass : public Pass {
log(" Produce a runtime error if any problems are found in the current design.\n");
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
int counter = 0;
bool noinit = false;
diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc
index d6e7f2ccf..a1b3fbef7 100644
--- a/passes/cmds/chformal.cc
+++ b/passes/cmds/chformal.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ChformalPass : public Pass {
ChformalPass() : Pass("chformal", "change formal constraints of the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -62,7 +62,7 @@ struct ChformalPass : public Pass {
log(" change the roles of cells as indicated. these options can be combined\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) override
{
bool assert2assume = false;
bool assume2assert = false;
diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc
index 979aeadd4..b894f334c 100644
--- a/passes/cmds/chtype.cc
+++ b/passes/cmds/chtype.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ChtypePass : public Pass {
ChtypePass() : Pass("chtype", "change type of cells in the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -40,7 +40,7 @@ struct ChtypePass : public Pass {
log("\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) override
{
IdString set_type;
dict<IdString, IdString> map_types;
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index 0b0868dfb..0cc6cbe52 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -43,7 +43,7 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap &
struct ConnectPass : public Pass {
ConnectPass() : Pass("connect", "create or remove connections") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -75,7 +75,7 @@ struct ConnectPass : public Pass {
log("This command does not operate on module with processes.\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) override
{
RTLIL::Module *module = nullptr;
for (auto mod : design->selected_modules()) {
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index 6ae7c9304..9235dda2b 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -143,7 +143,7 @@ struct ConnwrappersWorker
struct ConnwrappersPass : public Pass {
ConnwrappersPass() : Pass("connwrappers", "match width of input-output port pairs") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -165,7 +165,7 @@ struct ConnwrappersPass : public Pass {
log("The options -signed, -unsigned, and -port can be specified multiple times.\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) override
{
ConnwrappersWorker worker;
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index 99f1f69cf..c351065f3 100644
--- a/passes/cmds/copy.cc
+++ b/passes/cmds/copy.cc
@@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CopyPass : public Pass {
CopyPass() : Pass("copy", "copy modules in the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -36,7 +36,7 @@ struct CopyPass : public Pass {
log("by this command.\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) override
{
if (args.size() != 3)
log_cmd_error("Invalid number of arguments!\n");
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 89d27c9aa..0867e3b4f 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -35,7 +35,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CoverPass : public Pass {
CoverPass() : Pass("cover", "print code coverage counters") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -83,7 +83,7 @@ struct CoverPass : public Pass {
log("Coverage counters are only available in Yosys for Linux.\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) override
{
std::vector<FILE*> out_files;
std::vector<std::string> patterns;
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index b124e3b0f..684fa37b0 100644
--- a/passes/cmds/delete.cc
+++ b/passes/cmds/delete.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct DeletePass : public Pass {
DeletePass() : Pass("delete", "delete objects in the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -40,7 +40,7 @@ struct DeletePass : public Pass {
log("selected wires, thus 'deleting' module ports.\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) override
{
bool flag_input = false;
bool flag_output = false;
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index 421defe0c..2d7ba1fef 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -28,7 +28,7 @@ std::vector<RTLIL::Design*> pushed_designs;
struct DesignPass : public Pass {
DesignPass() : Pass("design", "save, restore and reset current design") { }
- ~DesignPass() YS_OVERRIDE {
+ ~DesignPass() override {
for (auto &it : saved_designs)
delete it.second;
saved_designs.clear();
@@ -36,7 +36,7 @@ struct DesignPass : public Pass {
delete it;
pushed_designs.clear();
}
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -105,7 +105,7 @@ struct DesignPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
bool got_mode = false;
bool reset_mode = false;
diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc
index 58ed6457d..37c420400 100644
--- a/passes/cmds/edgetypes.cc
+++ b/passes/cmds/edgetypes.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct EdgetypePass : public Pass {
EdgetypePass() : Pass("edgetypes", "list all types of edges in selection") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -35,7 +35,7 @@ struct EdgetypePass : public Pass {
log("is a 4-tuple of source and sink cell type and port name.\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) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc
index 7eeefe705..951fa53fc 100644
--- a/passes/cmds/exec.cc
+++ b/passes/cmds/exec.cc
@@ -38,7 +38,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ExecPass : public Pass {
ExecPass() : Pass("exec", "execute commands in the operating system shell") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -71,7 +71,7 @@ struct ExecPass : public Pass {
log("\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) override
{
std::string cmd = "";
char buf[1024] = {};
diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc
index 522e1089d..12c43ecec 100644
--- a/passes/cmds/logcmd.cc
+++ b/passes/cmds/logcmd.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct LogPass : public Pass {
LogPass() : Pass("log", "print text and log files") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -52,7 +52,7 @@ struct LogPass : public Pass {
log(" do not append a newline\n");
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design*) override
{
size_t argidx;
bool to_stdout = false;
diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc
index 50b89d92f..6a9ed6036 100644
--- a/passes/cmds/logger.cc
+++ b/passes/cmds/logger.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct LoggerPass : public Pass {
LoggerPass() : Pass("logger", "set logger properties") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -66,7 +66,7 @@ struct LoggerPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design * design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design * design) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -159,39 +159,12 @@ struct LoggerPass : public Pass {
log_cmd_error("Expected error message occurrences must be 1 !\n");
log("Added regex '%s' for warnings to expected %s list.\n", pattern.c_str(), type.c_str());
try {
- if (type=="error") {
- auto it = log_expect_error.begin();
- auto ie = log_expect_error.end();
- for (; it != ie; it++)
- if (it->second.pattern == pattern) {
- it->second.expected_count = count;
- break;
- }
- if (it == ie)
- log_expect_error.emplace_back(YS_REGEX_COMPILE(pattern), LogExpectedItem(pattern, count));
- }
- else if (type=="warning") {
- auto it = log_expect_warning.begin();
- auto ie = log_expect_warning.end();
- for (; it != ie; it++)
- if (it->second.pattern == pattern) {
- it->second.expected_count = count;
- break;
- }
- if (it == ie)
- log_expect_warning.emplace_back(YS_REGEX_COMPILE(pattern), LogExpectedItem(pattern, count));
- }
- else if (type=="log") {
- auto it = log_expect_log.begin();
- auto ie = log_expect_log.end();
- for (; it != ie; it++)
- if (it->second.pattern == pattern) {
- it->second.expected_count = count;
- break;
- }
- if (it == ie)
- log_expect_log.emplace_back(YS_REGEX_COMPILE(pattern), LogExpectedItem(pattern, count));
- }
+ if (type == "error")
+ log_expect_error[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
+ else if (type == "warning")
+ log_expect_warning[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
+ else if (type == "log")
+ log_expect_log[pattern] = LogExpectedItem(YS_REGEX_COMPILE(pattern), count);
else log_abort();
}
catch (const YS_REGEX_NS::regex_error& e) {
diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc
index 05701710b..39ec432c2 100644
--- a/passes/cmds/ltp.cc
+++ b/passes/cmds/ltp.cc
@@ -141,7 +141,7 @@ struct LtpWorker
struct LtpPass : public Pass {
LtpPass() : Pass("ltp", "print longest topological path") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -154,7 +154,7 @@ struct LtpPass : public Pass {
log(" automatically exclude FF cell types\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) override
{
bool noff = false;
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index 4c16b56c4..3ed19497d 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -99,7 +99,7 @@ void load_plugin(std::string, std::vector<std::string>)
struct PluginPass : public Pass {
PluginPass() : Pass("plugin", "load and list loaded plugins") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -117,7 +117,7 @@ struct PluginPass : public Pass {
log(" List loaded plugins\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) override
{
std::string plugin_filename;
std::vector<std::string> plugin_aliases;
diff --git a/passes/cmds/portlist.cc b/passes/cmds/portlist.cc
index 38c4a8597..97f4bfd99 100644
--- a/passes/cmds/portlist.cc
+++ b/passes/cmds/portlist.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct PortlistPass : public Pass {
PortlistPass() : Pass("portlist", "list (top-level) ports") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -39,7 +39,7 @@ struct PortlistPass : public Pass {
log(" print verilog blackbox module definitions instead of port lists\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) override
{
bool m_mode = false;
diff --git a/passes/cmds/printattrs.cc b/passes/cmds/printattrs.cc
new file mode 100644
index 000000000..7973ac262
--- /dev/null
+++ b/passes/cmds/printattrs.cc
@@ -0,0 +1,90 @@
+/*
+ * 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"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct PrintAttrsPass : public Pass {
+ PrintAttrsPass() : Pass("printattrs", "print attributes of selected objects") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" printattrs [selection]\n");
+ log("\n");
+ log("Print all attributes of the selected objects.\n");
+ log("\n");
+ log("\n");
+ }
+
+ static std::string get_indent_str(const unsigned int indent) {
+ return stringf("%*s", indent, "");
+ }
+
+ static void log_const(const RTLIL::IdString &s, const RTLIL::Const &x, const unsigned int indent) {
+ if (x.flags == RTLIL::CONST_FLAG_STRING)
+ log("%s(* %s=\"%s\" *)\n", get_indent_str(indent).c_str(), log_id(s), x.decode_string().c_str());
+ else if (x.flags == RTLIL::CONST_FLAG_NONE)
+ log("%s(* %s=%s *)\n", get_indent_str(indent).c_str(), log_id(s), x.as_string().c_str());
+ else
+ log_assert(x.flags == RTLIL::CONST_FLAG_STRING || x.flags == RTLIL::CONST_FLAG_NONE); //intended to fail
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ size_t argidx = 1;
+ extra_args(args, argidx, design);
+
+ unsigned int indent = 0;
+ for (auto mod : design->selected_modules())
+ {
+ if (design->selected_whole_module(mod)) {
+ log("%s%s\n", get_indent_str(indent).c_str(), log_id(mod->name));
+ indent += 2;
+ for (auto &it : mod->attributes)
+ log_const(it.first, it.second, indent);
+ }
+
+ for (auto cell : mod->selected_cells()) {
+ log("%s%s\n", get_indent_str(indent).c_str(), log_id(cell->name));
+ indent += 2;
+ for (auto &it : cell->attributes)
+ log_const(it.first, it.second, indent);
+ indent -= 2;
+ }
+
+ for (auto wire : mod->selected_wires()) {
+ log("%s%s\n", get_indent_str(indent).c_str(), log_id(wire->name));
+ indent += 2;
+ for (auto &it : wire->attributes)
+ log_const(it.first, it.second, indent);
+ indent -= 2;
+ }
+
+ if (design->selected_whole_module(mod))
+ indent -= 2;
+ }
+
+ log("\n");
+ }
+} PrintAttrsPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index b178ef951..cf0f6d0de 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -778,7 +778,7 @@ struct QwpWorker
struct QwpPass : public Pass {
QwpPass() : Pass("qwp", "quadratic wirelength placer") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -808,7 +808,7 @@ struct QwpPass : public Pass {
log("dense matrix operations. It is only a toy-placer for small circuits.\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) override
{
QwpConfig config;
xorshift32_state = 123456789;
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index 7d6d84d42..6326b4b15 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -104,7 +104,7 @@ static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell)
struct RenamePass : public Pass {
RenamePass() : Pass("rename", "rename object in the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -152,7 +152,7 @@ struct RenamePass : public Pass {
log("Rename top module.\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) override
{
std::string pattern_prefix = "_", pattern_suffix = "_";
bool flag_src = false;
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index a5ef95f02..a70dd3086 100644
--- a/passes/cmds/scatter.cc
+++ b/passes/cmds/scatter.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ScatterPass : public Pass {
ScatterPass() : Pass("scatter", "add additional intermediate nets") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct ScatterPass : public Pass {
log("Use the opt_clean command to get rid of the additional nets.\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) override
{
CellTypes ct(design);
extra_args(args, 1, design);
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index ad0554bae..8e7f3f990 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -218,7 +218,7 @@ struct SccWorker
struct SccPass : public Pass {
SccPass() : Pass("scc", "detect strongly connected components (logic loops)") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -255,7 +255,7 @@ struct SccPass : public Pass {
log(" that are part of a found logic loop\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) override
{
std::map<std::string, std::string> setAttr;
bool allCellTypes = false;
diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc
index 34ec0863a..9369f5312 100644
--- a/passes/cmds/scratchpad.cc
+++ b/passes/cmds/scratchpad.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ScratchpadPass : public Pass {
ScratchpadPass() : Pass("scratchpad", "get/set values in the scratchpad") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -63,7 +63,7 @@ struct ScratchpadPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index 6e728c16f..b4f3994a2 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -30,26 +30,31 @@ using RTLIL::id2cstr;
static std::vector<RTLIL::Selection> work_stack;
-static bool match_ids(RTLIL::IdString id, std::string pattern)
+static bool match_ids(RTLIL::IdString id, const std::string &pattern)
{
if (id == pattern)
return true;
- if (id.size() > 0 && id[0] == '\\' && id.compare(1, std::string::npos, pattern.c_str()) == 0)
+
+ const char *id_c = id.c_str();
+ const char *pat_c = pattern.c_str();
+ size_t id_size = strlen(id_c);
+ size_t pat_size = pattern.size();
+
+ if (*id_c == '\\' && id_size == 1 + pat_size && memcmp(id_c + 1, pat_c, pat_size) == 0)
return true;
- if (patmatch(pattern.c_str(), id.c_str()))
+ if (patmatch(pat_c, id_c))
return true;
- if (id.size() > 0 && id[0] == '\\' && patmatch(pattern.c_str(), id.substr(1).c_str()))
+ if (*id_c == '\\' && patmatch(pat_c, id_c + 1))
return true;
- if (id.size() > 0 && id[0] == '$' && pattern.size() > 0 && pattern[0] == '$') {
- const char *p = id.c_str();
- const char *q = strrchr(p, '$');
+ if (*id_c == '$' && *pat_c == '$') {
+ const char *q = strrchr(id_c, '$');
if (pattern == q)
return true;
}
return false;
}
-static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char match_op)
+static bool match_attr_val(const RTLIL::Const &value, const std::string &pattern, char match_op)
{
if (match_op == 0)
return true;
@@ -101,7 +106,7 @@ static bool match_attr_val(const RTLIL::Const &value, std::string pattern, char
log_abort();
}
-static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, std::string name_pat, std::string value_pat, char match_op)
+static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, const std::string &name_pat, const std::string &value_pat, char match_op)
{
if (name_pat.find('*') != std::string::npos || name_pat.find('?') != std::string::npos || name_pat.find('[') != std::string::npos) {
for (auto &it : attributes) {
@@ -119,7 +124,7 @@ static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, st
return false;
}
-static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, std::string match_expr)
+static bool match_attr(const dict<RTLIL::IdString, RTLIL::Const> &attributes, const std::string &match_expr)
{
size_t pos = match_expr.find_first_of("<!=>");
@@ -410,7 +415,7 @@ namespace {
};
}
-static int parse_comma_list(std::set<RTLIL::IdString> &tokens, std::string str, size_t pos, std::string stopchar)
+static int parse_comma_list(std::set<RTLIL::IdString> &tokens, const std::string &str, size_t pos, std::string stopchar)
{
stopchar += ',';
while (1) {
@@ -495,7 +500,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v
return sel_objects;
}
-static void select_op_expand(RTLIL::Design *design, std::string arg, char mode, bool eval_only)
+static void select_op_expand(RTLIL::Design *design, const std::string &arg, char mode, bool eval_only)
{
int pos = (mode == 'x' ? 2 : 3) + (eval_only ? 1 : 0);
int levels = 1, rem_objects = -1;
@@ -966,7 +971,7 @@ PRIVATE_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
// used in kernel/register.cc and maybe other locations, extern decl. in register.h
-void handle_extra_select_args(Pass *pass, vector<string> args, size_t argidx, size_t args_size, RTLIL::Design *design)
+void handle_extra_select_args(Pass *pass, const vector<string> &args, size_t argidx, size_t args_size, RTLIL::Design *design)
{
work_stack.clear();
for (; argidx < args_size; argidx++) {
@@ -1016,7 +1021,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SelectPass : public Pass {
SelectPass() : Pass("select", "modify and view the list of selected objects") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1245,7 +1250,7 @@ struct SelectPass : public Pass {
log(" select */t:SWITCH %%x:+[GATE] */t:SWITCH %%d\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) override
{
bool add_mode = false;
bool del_mode = false;
@@ -1582,7 +1587,7 @@ struct SelectPass : public Pass {
struct CdPass : public Pass {
CdPass() : Pass("cd", "a shortcut for 'select -module <name>'") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1608,7 +1613,7 @@ struct CdPass : public Pass {
log("This is just a shortcut for 'select -clear'.\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) override
{
if (args.size() != 1 && args.size() != 2)
log_cmd_error("Invalid number of arguments.\n");
@@ -1670,7 +1675,7 @@ struct CdPass : public Pass {
} CdPass;
template<typename T>
-static void log_matches(const char *title, Module *module, T list)
+static void log_matches(const char *title, Module *module, const T &list)
{
std::vector<IdString> matches;
@@ -1688,7 +1693,7 @@ static void log_matches(const char *title, Module *module, T list)
struct LsPass : public Pass {
LsPass() : Pass("ls", "list modules or objects in modules") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1699,7 +1704,7 @@ struct LsPass : public Pass {
log("When an active module is selected, this prints a list of objects in the module.\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) override
{
size_t argidx = 1;
extra_args(args, argidx, design);
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 515f5a4ef..3a94209d4 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -56,7 +56,7 @@ static void do_setunset(dict<RTLIL::IdString, RTLIL::Const> &attrs, const std::v
struct SetattrPass : public Pass {
SetattrPass() : Pass("setattr", "set/unset attributes on objects") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -69,7 +69,7 @@ struct SetattrPass : public Pass {
log("instead of objects within modules.\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) override
{
std::vector<setunset_t> setunset_list;
bool flag_mod = false;
@@ -128,7 +128,7 @@ struct SetattrPass : public Pass {
struct WbflipPass : public Pass {
WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -138,7 +138,7 @@ struct WbflipPass : public Pass {
log("vice-versa. Blackbox cells are not effected by this command.\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) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -167,7 +167,7 @@ struct WbflipPass : public Pass {
struct SetparamPass : public Pass {
SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -179,7 +179,7 @@ struct SetparamPass : public Pass {
log("The -type option can be used to change the cell type of the selected cells.\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) override
{
vector<setunset_t> setunset_list;
string new_cell_type;
@@ -219,7 +219,7 @@ struct SetparamPass : public Pass {
struct ChparamPass : public Pass {
ChparamPass() : Pass("chparam", "re-evaluate modules with new parameters") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -234,7 +234,7 @@ struct ChparamPass : public Pass {
log("List the available parameters of the selected modules.\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) override
{
std::vector<setunset_t> setunset_list;
dict<RTLIL::IdString, RTLIL::Const> new_parameters;
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index 8d973869e..cf8d76619 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -107,7 +107,7 @@ struct SetundefWorker
struct SetundefPass : public Pass {
SetundefPass() : Pass("setundef", "replace undef values with defined constants") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -147,7 +147,7 @@ struct SetundefPass : public Pass {
log(" replace undef in cell parameters\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) override
{
int got_value = 0;
bool undriven_mode = false;
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index fa922454a..cbed08a3f 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -587,7 +587,7 @@ struct ShowWorker
struct ShowPass : public Pass {
ShowPass() : Pass("show", "generate schematics using graphviz") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -674,7 +674,7 @@ struct ShowPass : public Pass {
log("the 'show' command is executed.\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) override
{
log_header(design, "Generating Graphviz representation of design.\n");
log_push();
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index ea9e06979..20627d601 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -246,7 +246,7 @@ struct SpliceWorker
struct SplicePass : public Pass {
SplicePass() : Pass("splice", "create explicit splicing cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -287,7 +287,7 @@ struct SplicePass : public Pass {
log("by selected wires are rewired.\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) override
{
bool sel_by_cell = false;
bool sel_by_wire = false;
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index 1e7dedd70..fff8a0d3e 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -59,18 +59,26 @@ struct SplitnetsWorker
new_wire->port_id = wire->port_id ? wire->port_id + offset : 0;
new_wire->port_input = wire->port_input;
new_wire->port_output = wire->port_output;
+ new_wire->start_offset = wire->start_offset + offset;
- if (wire->attributes.count(ID::src))
- new_wire->attributes[ID::src] = wire->attributes.at(ID::src);
+ auto it = wire->attributes.find(ID::src);
+ if (it != wire->attributes.end())
+ new_wire->attributes.emplace(ID::src, it->second);
- if (wire->attributes.count(ID::keep))
- new_wire->attributes[ID::keep] = wire->attributes.at(ID::keep);
+ it = wire->attributes.find(ID::hdlname);
+ if (it != wire->attributes.end())
+ new_wire->attributes.emplace(ID::hdlname, it->second);
- if (wire->attributes.count(ID::init)) {
- Const old_init = wire->attributes.at(ID::init), new_init;
+ it = wire->attributes.find(ID::keep);
+ if (it != wire->attributes.end())
+ new_wire->attributes.emplace(ID::keep, it->second);
+
+ it = wire->attributes.find(ID::init);
+ if (it != wire->attributes.end()) {
+ Const old_init = it->second, new_init;
for (int i = offset; i < offset+width; i++)
new_init.bits.push_back(i < GetSize(old_init) ? old_init.bits.at(i) : State::Sx);
- new_wire->attributes[ID::init] = new_init;
+ new_wire->attributes.emplace(ID::init, new_init);
}
std::vector<RTLIL::SigBit> sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector();
@@ -87,7 +95,7 @@ struct SplitnetsWorker
struct SplitnetsPass : public Pass {
SplitnetsPass() : Pass("splitnets", "split up multi-bit nets") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -109,7 +117,7 @@ struct SplitnetsPass : public Pass {
log(" and split nets so that no driver drives only part of a net.\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) override
{
bool flag_ports = false;
bool flag_driver = false;
@@ -166,12 +174,12 @@ struct SplitnetsPass : public Pass {
std::map<RTLIL::Wire*, std::set<int>> split_wires_at;
- for (auto &c : module->cells_)
- for (auto &p : c.second->connections())
+ for (auto c : module->cells())
+ for (auto &p : c->connections())
{
- if (!ct.cell_known(c.second->type))
+ if (!ct.cell_known(c->type))
continue;
- if (!ct.cell_output(c.second->type, p.first))
+ if (!ct.cell_output(c->type, p.first))
continue;
RTLIL::SigSpec sig = p.second;
@@ -198,9 +206,8 @@ struct SplitnetsPass : public Pass {
}
else
{
- for (auto &w : module->wires_) {
- RTLIL::Wire *wire = w.second;
- if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, w.second))
+ for (auto wire : module->wires()) {
+ if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, wire))
worker.splitmap[wire] = std::vector<RTLIL::SigBit>();
}
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 6c4bc0e5b..ed51fdc24 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -109,7 +109,7 @@ struct statdata_t
ID($lut), ID($and), ID($or), ID($xor), ID($xnor),
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))) {
+ ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), ID($alu))) {
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;
@@ -117,7 +117,10 @@ struct statdata_t
}
else if (cell_type.in(ID($mux), ID($pmux)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)));
- else if (cell_type.in(ID($sr), ID($dff), ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr)))
+ else if (cell_type.in(
+ ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre),
+ ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce),
+ ID($dlatch), ID($adlatch), ID($dlatchsr)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q)));
}
@@ -282,7 +285,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil
struct StatPass : public Pass {
StatPass() : Pass("stat", "print some statistics") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -308,7 +311,7 @@ struct StatPass : public Pass {
log(" e.g. $add_8 for an 8 bit wide $add cell.\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) override
{
log_header(design, "Printing statistics.\n");
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index 1a44bdaec..60689fc82 100644
--- a/passes/cmds/tee.cc
+++ b/passes/cmds/tee.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct TeePass : public Pass {
TeePass() : Pass("tee", "redirect command output to file") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -49,7 +49,7 @@ struct TeePass : public Pass {
log(" Add/subtract INT from the -v setting for this command.\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) override
{
std::vector<FILE*> backup_log_files, files_to_close;
std::vector<std::ostream*> backup_log_streams;
diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc
index 5748ff7f0..30e76081e 100644
--- a/passes/cmds/torder.cc
+++ b/passes/cmds/torder.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct TorderPass : public Pass {
TorderPass() : Pass("torder", "print cells in topological order") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -43,7 +43,7 @@ struct TorderPass : public Pass {
log(" are not used in topological sorting. this option deactivates that.\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) override
{
bool noautostop = false;
dict<IdString, pool<IdString>> stop_db;
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index 8446e27b3..10742c370 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -25,34 +25,34 @@ PRIVATE_NAMESPACE_BEGIN
struct TraceMonitor : public RTLIL::Monitor
{
- void notify_module_add(RTLIL::Module *module) YS_OVERRIDE
+ void notify_module_add(RTLIL::Module *module) override
{
log("#TRACE# Module add: %s\n", log_id(module));
}
- void notify_module_del(RTLIL::Module *module) YS_OVERRIDE
+ void notify_module_del(RTLIL::Module *module) override
{
log("#TRACE# Module delete: %s\n", log_id(module));
}
- void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) YS_OVERRIDE
+ void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
{
log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig));
}
- void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) YS_OVERRIDE
+ void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) override
{
log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second));
}
- void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) YS_OVERRIDE
+ void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) override
{
log("#TRACE# New connections in module %s:\n", log_id(module));
for (auto &sigsig : sigsig_vec)
log("## %s = %s\n", log_signal(sigsig.first), log_signal(sigsig.second));
}
- void notify_blackout(RTLIL::Module *module) YS_OVERRIDE
+ void notify_blackout(RTLIL::Module *module) override
{
log("#TRACE# Blackout in module %s:\n", log_id(module));
}
@@ -60,7 +60,7 @@ struct TraceMonitor : public RTLIL::Monitor
struct TracePass : public Pass {
TracePass() : Pass("trace", "redirect command output to file") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -70,7 +70,7 @@ struct TracePass : public Pass {
log("the design in real time.\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) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -96,7 +96,7 @@ struct TracePass : public Pass {
struct DebugPass : public Pass {
DebugPass() : Pass("debug", "run command with debug log messages enabled") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -105,7 +105,7 @@ struct DebugPass : public Pass {
log("Execute the specified command with debug log messages enabled\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) override
{
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index 64a762d7c..3d898a5ef 100644
--- a/passes/cmds/write_file.cc
+++ b/passes/cmds/write_file.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct WriteFileFrontend : public Frontend {
WriteFileFrontend() : Frontend("=write_file", "write a text to a file") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -44,7 +44,7 @@ struct WriteFileFrontend : public Frontend {
log(" EOT\n");
log("\n");
}
- void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
+ void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) override
{
bool append_mode = false;
std::string output_filename;
diff --git a/passes/equiv/equiv_add.cc b/passes/equiv/equiv_add.cc
index cdc74b0b2..2abbb59bb 100644
--- a/passes/equiv/equiv_add.cc
+++ b/passes/equiv/equiv_add.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct EquivAddPass : public Pass {
EquivAddPass() : Pass("equiv_add", "add a $equiv cell") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -39,7 +39,7 @@ struct EquivAddPass : public Pass {
log("This command adds $equiv cells for the ports of the specified cells.\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
bool try_mode = false;
diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc
index ec651193e..596c938fc 100644
--- a/passes/equiv/equiv_induct.cc
+++ b/passes/equiv/equiv_induct.cc
@@ -162,7 +162,7 @@ struct EquivInductWorker
struct EquivInductPass : public Pass {
EquivInductPass() : Pass("equiv_induct", "proving $equiv cells using temporal induction") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -192,7 +192,7 @@ struct EquivInductPass : public Pass {
log("after reset.\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
int success_counter = 0;
bool model_undef = false;
diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc
index 50572ae5c..51b4ad0f1 100644
--- a/passes/equiv/equiv_make.cc
+++ b/passes/equiv/equiv_make.cc
@@ -466,7 +466,7 @@ struct EquivMakeWorker
struct EquivMakePass : public Pass {
EquivMakePass() : Pass("equiv_make", "prepare a circuit for equivalence checking") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -491,7 +491,7 @@ struct EquivMakePass : public Pass {
log("checking problem. Use 'miter -equiv' if you want to create a miter circuit.\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) override
{
EquivMakeWorker worker;
worker.ct.setup(design);
diff --git a/passes/equiv/equiv_mark.cc b/passes/equiv/equiv_mark.cc
index 737de25d9..a722b5ed6 100644
--- a/passes/equiv/equiv_mark.cc
+++ b/passes/equiv/equiv_mark.cc
@@ -204,7 +204,7 @@ struct EquivMarkWorker
struct EquivMarkPass : public Pass {
EquivMarkPass() : Pass("equiv_mark", "mark equivalence checking regions") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -216,7 +216,7 @@ struct EquivMarkPass : public Pass {
log("wires and cells.\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
log_header(design, "Executing EQUIV_MARK pass.\n");
diff --git a/passes/equiv/equiv_miter.cc b/passes/equiv/equiv_miter.cc
index 085970189..e028f806a 100644
--- a/passes/equiv/equiv_miter.cc
+++ b/passes/equiv/equiv_miter.cc
@@ -261,7 +261,7 @@ struct EquivMiterWorker
struct EquivMiterPass : public Pass {
EquivMiterPass() : Pass("equiv_miter", "extract miter from equiv circuit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -282,7 +282,7 @@ struct EquivMiterPass : public Pass {
log(" Create compare logic that handles undefs correctly\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) override
{
EquivMiterWorker worker;
worker.ct.setup(design);
diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc
index 7c6c2e685..4d0400448 100644
--- a/passes/equiv/equiv_opt.cc
+++ b/passes/equiv/equiv_opt.cc
@@ -26,7 +26,7 @@ struct EquivOptPass:public ScriptPass
{
EquivOptPass() : ScriptPass("equiv_opt", "prove equivalence for optimized circuit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -68,7 +68,7 @@ struct EquivOptPass:public ScriptPass
std::string command, techmap_opts, make_opts;
bool assert, undef, multiclock, async2sync;
- void clear_flags() YS_OVERRIDE
+ void clear_flags() override
{
command = "";
techmap_opts = "";
@@ -79,7 +79,7 @@ struct EquivOptPass:public ScriptPass
async2sync = false;
}
- void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE
+ void execute(std::vector < std::string > args, RTLIL::Design * design) override
{
string run_from, run_to;
clear_flags();
@@ -148,7 +148,7 @@ struct EquivOptPass:public ScriptPass
log_pop();
}
- void script() YS_OVERRIDE
+ void script() override
{
if (check_label("run_pass")) {
run("hierarchy -auto-top");
diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc
index 688c20f43..d15c8d183 100644
--- a/passes/equiv/equiv_purge.cc
+++ b/passes/equiv/equiv_purge.cc
@@ -176,7 +176,7 @@ struct EquivPurgeWorker
struct EquivPurgePass : public Pass {
EquivPurgePass() : Pass("equiv_purge", "purge equivalence checking module") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -187,7 +187,7 @@ struct EquivPurgePass : public Pass {
log("ports as needed.\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
log_header(design, "Executing EQUIV_PURGE pass.\n");
diff --git a/passes/equiv/equiv_remove.cc b/passes/equiv/equiv_remove.cc
index 6daa112b5..89442308b 100644
--- a/passes/equiv/equiv_remove.cc
+++ b/passes/equiv/equiv_remove.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct EquivRemovePass : public Pass {
EquivRemovePass() : Pass("equiv_remove", "remove $equiv cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -40,7 +40,7 @@ struct EquivRemovePass : public Pass {
log(" keep gate circuit\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
bool mode_gold = false;
bool mode_gate = false;
diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc
index 4d2839f4d..408c5a793 100644
--- a/passes/equiv/equiv_simple.cc
+++ b/passes/equiv/equiv_simple.cc
@@ -273,7 +273,7 @@ struct EquivSimpleWorker
struct EquivSimplePass : public Pass {
EquivSimplePass() : Pass("equiv_simple", "try proving simple $equiv instances") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -298,7 +298,7 @@ struct EquivSimplePass : public Pass {
log(" the max. number of time steps to be considered (default = 1)\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
bool verbose = false, short_cones = false, model_undef = false, nogroup = false;
int success_counter = 0;
diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc
index 258e2e45b..2db44ea90 100644
--- a/passes/equiv/equiv_status.cc
+++ b/passes/equiv/equiv_status.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct EquivStatusPass : public Pass {
EquivStatusPass() : Pass("equiv_status", "print status of equivalent checking module") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -36,7 +36,7 @@ struct EquivStatusPass : public Pass {
log(" produce an error if any unproven $equiv cell is found\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
bool assert_mode = false;
int unproven_count = 0;
diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc
index 1b7bf96a8..9784225db 100644
--- a/passes/equiv/equiv_struct.cc
+++ b/passes/equiv/equiv_struct.cc
@@ -283,7 +283,7 @@ struct EquivStructWorker
struct EquivStructPass : public Pass {
EquivStructPass() : Pass("equiv_struct", "structural equivalence checking") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -314,7 +314,7 @@ struct EquivStructPass : public Pass {
log(" maximum number of iterations to run before aborting\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
pool<IdString> fwonly_cells({ ID($equiv) });
bool mode_icells = false;
diff --git a/passes/fsm/fsm.cc b/passes/fsm/fsm.cc
index c5cb338ab..21d352407 100644
--- a/passes/fsm/fsm.cc
+++ b/passes/fsm/fsm.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct FsmPass : public Pass {
FsmPass() : Pass("fsm", "extract and optimize finite state machines") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -68,7 +68,7 @@ struct FsmPass : public Pass {
log(" passed through to fsm_recode pass\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) override
{
bool flag_nomap = false;
bool flag_norecode = false;
diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc
index 30e9e4dad..97c575ba7 100644
--- a/passes/fsm/fsm_detect.cc
+++ b/passes/fsm/fsm_detect.cc
@@ -257,7 +257,7 @@ static void detect_fsm(RTLIL::Wire *wire)
struct FsmDetectPass : public Pass {
FsmDetectPass() : Pass("fsm_detect", "finding FSMs in design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -273,7 +273,7 @@ struct FsmDetectPass : public Pass {
log("'fsm_encoding' attribute to \"none\".\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) override
{
log_header(design, "Executing FSM_DETECT pass (finding FSMs in design).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc
index ade6c17f5..d6b492af5 100644
--- a/passes/fsm/fsm_expand.cc
+++ b/passes/fsm/fsm_expand.cc
@@ -265,7 +265,7 @@ struct FsmExpand
struct FsmExpandPass : public Pass {
FsmExpandPass() : Pass("fsm_expand", "expand FSM cells by merging logic into it") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -279,7 +279,7 @@ struct FsmExpandPass : public Pass {
log("word-wide cells. Call with -full to consider all cells for merging.\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) override
{
bool full_mode = false;
diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc
index c02a54ea2..be6702d7e 100644
--- a/passes/fsm/fsm_export.cc
+++ b/passes/fsm/fsm_export.cc
@@ -120,7 +120,7 @@ void write_kiss2(struct RTLIL::Module *module, struct RTLIL::Cell *cell, std::st
*/
struct FsmExportPass : public Pass {
FsmExportPass() : Pass("fsm_export", "exporting FSMs to KISS2 files") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -143,7 +143,7 @@ struct FsmExportPass : public Pass {
log(" use binary state encoding as state names instead of s0, s1, ...\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) override
{
dict<RTLIL::IdString, RTLIL::Const>::iterator attr_it;
std::string arg;
diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc
index 3840aabc8..082973153 100644
--- a/passes/fsm/fsm_extract.cc
+++ b/passes/fsm/fsm_extract.cc
@@ -394,14 +394,14 @@ static void extract_fsm(RTLIL::Wire *wire)
RTLIL::Cell *cell = module->cells_.at(cellport.first);
RTLIL::SigSpec port_sig = assign_map(cell->getPort(cellport.second));
RTLIL::SigSpec unconn_sig = port_sig.extract(ctrl_out);
- RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%s$%d", log_signal(unconn_sig), autoidx++), unconn_sig.size());
+ RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%d", autoidx++), unconn_sig.size());
port_sig.replace(unconn_sig, RTLIL::SigSpec(unconn_wire), &cell->connections_[cellport.second]);
}
}
struct FsmExtractPass : public Pass {
FsmExtractPass() : Pass("fsm_extract", "extracting FSMs in design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -417,7 +417,7 @@ struct FsmExtractPass : public Pass {
log("'opt_clean' pass to eliminate this signal.\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) override
{
log_header(design, "Executing FSM_EXTRACT pass (extracting FSM from design).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc
index 90250f9b7..da0982bb9 100644
--- a/passes/fsm/fsm_info.cc
+++ b/passes/fsm/fsm_info.cc
@@ -30,7 +30,7 @@ PRIVATE_NAMESPACE_BEGIN
struct FsmInfoPass : public Pass {
FsmInfoPass() : Pass("fsm_info", "print information on finite state machines") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct FsmInfoPass : public Pass {
log("pass so that this information is included in the synthesis log file.\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) override
{
log_header(design, "Executing FSM_INFO pass (dumping all available information on FSM cells).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc
index 1765df092..a30d407f0 100644
--- a/passes/fsm/fsm_map.cc
+++ b/passes/fsm/fsm_map.cc
@@ -322,7 +322,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
struct FsmMapPass : public Pass {
FsmMapPass() : Pass("fsm_map", "mapping FSMs to basic logic") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -331,7 +331,7 @@ struct FsmMapPass : public Pass {
log("This pass translates FSM cells to flip-flops and logic.\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) override
{
log_header(design, "Executing FSM_MAP pass (mapping FSMs to basic logic).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc
index 89e8132d4..5fc1fb3bb 100644
--- a/passes/fsm/fsm_opt.cc
+++ b/passes/fsm/fsm_opt.cc
@@ -324,7 +324,7 @@ PRIVATE_NAMESPACE_BEGIN
struct FsmOptPass : public Pass {
FsmOptPass() : Pass("fsm_opt", "optimize finite state machines") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -335,7 +335,7 @@ struct FsmOptPass : public Pass {
log("combination with the 'opt_clean' pass (see also 'help fsm').\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) override
{
log_header(design, "Executing FSM_OPT pass (simple optimizations of FSMs).\n");
extra_args(args, 1, design);
diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc
index 7edb923b9..d4a704270 100644
--- a/passes/fsm/fsm_recode.cc
+++ b/passes/fsm/fsm_recode.cc
@@ -126,7 +126,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs
struct FsmRecodePass : public Pass {
FsmRecodePass() : Pass("fsm_recode", "recoding finite state machines") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -151,7 +151,7 @@ struct FsmRecodePass : public Pass {
log(" .map <old_bitpattern> <new_bitpattern>\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) override
{
FILE *fm_set_fsm_file = NULL;
FILE *encfile = NULL;
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 95d74d1eb..a2a428d15 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -254,16 +254,6 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
// some lists, so that the ports for sub-modules can be replaced further down:
for (auto &conn : cell->connections()) {
if(mod->wire(conn.first) != nullptr && mod->wire(conn.first)->get_bool_attribute(ID::is_interface)) { // Check if the connection is present as an interface in the sub-module's port list
- //const pool<string> &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute(ID::interface_type);
- //for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module (not crucially important, but good for robustness)
- //}
-
- // Find if the sub-module has set a modport for the current interface connection:
- const pool<string> &interface_modport_pool = mod->wire(conn.first)->get_strpool_attribute(ID::interface_modport);
- std::string interface_modport = "";
- for (auto &d : interface_modport_pool) {
- interface_modport = "\\" + d;
- }
if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute(ID::is_interface)) { // Check if the connected wire is a potential interface in the parent module
std::string interface_name_str = conn.second.bits()[0].wire->name.str();
interface_name_str.replace(0,23,""); // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name
@@ -297,9 +287,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
connections_to_remove.push_back(conn.first);
interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name2);
- // Add modports to a dict which will be passed to AstModule::derive
- if (interface_modport != "") {
- modports_used_in_submodule[conn.first] = interface_modport;
+ // Find if the sub-module has set a modport for the current
+ // interface connection. Add any modports to a dict which will
+ // be passed to AstModule::derive
+ string modport_name = mod->wire(conn.first)->get_string_attribute(ID::interface_modport);
+ if (!modport_name.empty()) {
+ modports_used_in_submodule[conn.first] = "\\" + modport_name;
}
}
else not_found_interface = true;
@@ -565,7 +558,7 @@ RTLIL::Wire *find_implicit_port_wire(Module *module, Cell *cell, const std::stri
struct HierarchyPass : public Pass {
HierarchyPass() : Pass("hierarchy", "check, expand and clean up design hierarchy") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -574,9 +567,9 @@ struct HierarchyPass : public Pass {
log("\n");
log("In parametric designs, a module might exists in several variations with\n");
log("different parameter values. This pass looks at all modules in the current\n");
- log("design an re-runs the language frontends for the parametric modules as\n");
+ log("design and re-runs the language frontends for the parametric modules as\n");
log("needed. It also resolves assignments to wired logic data types (wand/wor),\n");
- log("resolves positional module parameters, unroll array instances, and more.\n");
+ log("resolves positional module parameters, unrolls array instances, and more.\n");
log("\n");
log(" -check\n");
log(" also check the design hierarchy. this generates an error when\n");
@@ -646,7 +639,7 @@ struct HierarchyPass : public Pass {
log("in the current design.\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) override
{
log_header(design, "Executing HIERARCHY pass (managing design hierarchy).\n");
diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc
index 2db7cf26b..b2826cbff 100644
--- a/passes/hierarchy/submod.cc
+++ b/passes/hierarchy/submod.cc
@@ -319,7 +319,7 @@ struct SubmodWorker
struct SubmodPass : public Pass {
SubmodPass() : Pass("submod", "moving part of a module to a new submodule") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -351,7 +351,7 @@ struct SubmodPass : public Pass {
log(" original module with original public names.\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) override
{
log_header(design, "Executing SUBMOD pass (moving cells to submodules as requested).\n");
log_push();
diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc
index 5dbd15a7e..3f9443a63 100644
--- a/passes/hierarchy/uniquify.cc
+++ b/passes/hierarchy/uniquify.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
struct UniquifyPass : public Pass {
UniquifyPass() : Pass("uniquify", "create unique copies of modules") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct UniquifyPass : public Pass {
log("attribute set (the 'top' module is unique implicitly).\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) override
{
log_header(design, "Executing UNIQUIFY pass (creating unique copies of modules).\n");
diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc
index cee63bdd8..282517992 100644
--- a/passes/memory/memory.cc
+++ b/passes/memory/memory.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct MemoryPass : public Pass {
MemoryPass() : Pass("memory", "translate memories to basic cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -49,7 +49,7 @@ struct MemoryPass : public Pass {
log("or multiport memory blocks if called with the -nomap option.\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) override
{
bool flag_nomap = false;
bool flag_nordff = false;
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index 0898ec288..3cb0728b7 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -1265,7 +1265,7 @@ void handle_cell(Cell *cell, const rules_t &rules)
struct MemoryBramPass : public Pass {
MemoryBramPass() : Pass("memory_bram", "map memories to block rams") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1367,7 +1367,7 @@ struct MemoryBramPass : public Pass {
log("the data bits to accommodate the enable pattern of port A.\n");
log("\n");
}
- void execute(vector<string> args, Design *design) YS_OVERRIDE
+ void execute(vector<string> args, Design *design) override
{
rules_t rules;
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc
index ef8b07811..7e82f47dc 100644
--- a/passes/memory/memory_collect.cc
+++ b/passes/memory/memory_collect.cc
@@ -245,7 +245,7 @@ static void handle_module(Design *design, Module *module)
struct MemoryCollectPass : public Pass {
MemoryCollectPass() : Pass("memory_collect", "creating multi-port memory cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -255,7 +255,7 @@ struct MemoryCollectPass : public Pass {
log("memory cells.\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) override {
log_header(design, "Executing MEMORY_COLLECT pass (generating $mem cells).\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules())
diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc
index 726a5c1ff..947cf7b35 100644
--- a/passes/memory/memory_dff.cc
+++ b/passes/memory/memory_dff.cc
@@ -291,7 +291,7 @@ struct MemoryDffWorker
struct MemoryDffPass : public Pass {
MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -305,7 +305,7 @@ struct MemoryDffPass : public Pass {
log(" do not merge registers on read ports\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) override
{
bool flag_wr_only = false;
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index 9d455f55b..80dd3957d 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -403,7 +403,7 @@ struct MemoryMapWorker
struct MemoryMapPass : public Pass {
MemoryMapPass() : Pass("memory_map", "translate multiport memories to basic cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -425,7 +425,7 @@ struct MemoryMapPass : public Pass {
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) override
{
bool attr_icase = false;
dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc
index 5d5f61c7d..02e00cf30 100644
--- a/passes/memory/memory_memx.cc
+++ b/passes/memory/memory_memx.cc
@@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN
struct MemoryMemxPass : public Pass {
MemoryMemxPass() : Pass("memory_memx", "emulate vlog sim behavior for mem ports") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -38,7 +38,7 @@ struct MemoryMemxPass : public Pass {
log("behavior for out-of-bounds memory reads and writes.\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) override {
log_header(design, "Executing MEMORY_MEMX pass (converting $mem cells to logic and flip-flops).\n");
extra_args(args, 1, design);
diff --git a/passes/memory/memory_nordff.cc b/passes/memory/memory_nordff.cc
index 487785397..07bbd9fe8 100644
--- a/passes/memory/memory_nordff.cc
+++ b/passes/memory/memory_nordff.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct MemoryNordffPass : public Pass {
MemoryNordffPass() : Pass("memory_nordff", "extract read port FFs from memories") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -35,7 +35,7 @@ struct MemoryNordffPass : public Pass {
log("similar to what one would get from calling memory_dff with -nordff.\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) override
{
log_header(design, "Executing MEMORY_NORDFF pass (extracting $dff cells from $mem).\n");
diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc
index 477246687..7315aeae1 100644
--- a/passes/memory/memory_share.cc
+++ b/passes/memory/memory_share.cc
@@ -715,6 +715,8 @@ struct MemoryShareWorker
cone_ct.cell_types.erase(ID($mul));
cone_ct.cell_types.erase(ID($mod));
cone_ct.cell_types.erase(ID($div));
+ cone_ct.cell_types.erase(ID($modfloor));
+ cone_ct.cell_types.erase(ID($divfloor));
cone_ct.cell_types.erase(ID($pow));
cone_ct.cell_types.erase(ID($shl));
cone_ct.cell_types.erase(ID($shr));
@@ -732,7 +734,7 @@ struct MemoryShareWorker
struct MemorySharePass : public Pass {
MemorySharePass() : Pass("memory_share", "consolidate memory ports") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -758,7 +760,7 @@ struct MemorySharePass : public Pass {
log("optimizations) such as \"share\" and \"opt_merge\".\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) override {
log_header(design, "Executing MEMORY_SHARE pass (consolidating $memrd/$memwr cells).\n");
extra_args(args, 1, design);
MemoryShareWorker msw(design);
diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc
index 8d284edcd..d04d4ba7a 100644
--- a/passes/memory/memory_unpack.cc
+++ b/passes/memory/memory_unpack.cc
@@ -127,7 +127,7 @@ void handle_module(RTLIL::Design *design, RTLIL::Module *module)
struct MemoryUnpackPass : public Pass {
MemoryUnpackPass() : Pass("memory_unpack", "unpack multi-port memory cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -137,7 +137,7 @@ struct MemoryUnpackPass : public Pass {
log("$memwr cells. It is the counterpart to the memory_collect pass.\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) override {
log_header(design, "Executing MEMORY_UNPACK pass (generating $memrd/$memwr cells form $mem cells).\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules())
diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc
index 9df49ab3c..aa5f82437 100644
--- a/passes/opt/muxpack.cc
+++ b/passes/opt/muxpack.cc
@@ -326,7 +326,7 @@ struct MuxpackWorker
struct MuxpackPass : public Pass {
MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -341,7 +341,7 @@ struct MuxpackPass : public Pass {
log("certain that their select inputs are mutually exclusive.\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) override
{
log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n");
diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc
index 396819883..8be94e345 100644
--- a/passes/opt/opt.cc
+++ b/passes/opt/opt.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct OptPass : public Pass {
OptPass() : Pass("opt", "perform simple optimizations") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -44,8 +44,8 @@ struct OptPass : public Pass {
log(" opt_muxtree\n");
log(" opt_reduce [-fine] [-full]\n");
log(" opt_merge [-share_all]\n");
- log(" opt_share (-full only)\n");
- log(" opt_rmdff [-keepdc] [-sat]\n");
+ log(" opt_share (-full only)\n");
+ log(" opt_rmdff [-keepdc] [-sat] (except when called with -noff)\n");
log(" opt_clean [-purge]\n");
log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
log(" while <changed design>\n");
@@ -55,7 +55,7 @@ struct OptPass : public Pass {
log(" do\n");
log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n");
log(" opt_merge [-share_all]\n");
- log(" opt_rmdff [-keepdc] [-sat]\n");
+ log(" opt_rmdff [-keepdc] [-sat] (except when called with -noff)\n");
log(" opt_clean [-purge]\n");
log(" while <changed design in opt_rmdff>\n");
log("\n");
@@ -64,7 +64,7 @@ struct OptPass : public Pass {
log("\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) override
{
std::string opt_clean_args;
std::string opt_expr_args;
@@ -73,6 +73,7 @@ struct OptPass : public Pass {
std::string opt_rmdff_args;
bool opt_share = false;
bool fast_mode = false;
+ bool noff_mode = false;
log_header(design, "Executing OPT pass (performing simple optimizations).\n");
log_push();
@@ -127,6 +128,10 @@ struct OptPass : public Pass {
fast_mode = true;
continue;
}
+ if (args[argidx] == "-noff") {
+ noff_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -137,7 +142,8 @@ struct OptPass : public Pass {
Pass::call(design, "opt_expr" + opt_expr_args);
Pass::call(design, "opt_merge" + opt_merge_args);
design->scratchpad_unset("opt.did_something");
- Pass::call(design, "opt_rmdff" + opt_rmdff_args);
+ if (!noff_mode)
+ Pass::call(design, "opt_rmdff" + opt_rmdff_args);
if (design->scratchpad_get_bool("opt.did_something") == false)
break;
Pass::call(design, "opt_clean" + opt_clean_args);
@@ -156,7 +162,8 @@ struct OptPass : public Pass {
Pass::call(design, "opt_merge" + opt_merge_args);
if (opt_share)
Pass::call(design, "opt_share");
- Pass::call(design, "opt_rmdff" + opt_rmdff_args);
+ if (!noff_mode)
+ Pass::call(design, "opt_rmdff" + opt_rmdff_args);
Pass::call(design, "opt_clean" + opt_clean_args);
Pass::call(design, "opt_expr" + opt_expr_args);
if (design->scratchpad_get_bool("opt.did_something") == false)
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index f7de02164..44de60b48 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -526,7 +526,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
struct OptCleanPass : public Pass {
OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -543,7 +543,7 @@ struct OptCleanPass : public Pass {
log(" also remove internal nets if they have a public name\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) override
{
bool purge_mode = false;
@@ -592,7 +592,7 @@ struct OptCleanPass : public Pass {
struct CleanPass : public Pass {
CleanPass() : Pass("clean", "remove unused cells and wires") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -607,7 +607,7 @@ struct CleanPass : public Pass {
log("in -purge mode between the commands.\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) override
{
bool purge_mode = false;
diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc
index 4bc82815b..f0fa86f42 100644
--- a/passes/opt/opt_demorgan.cc
+++ b/passes/opt/opt_demorgan.cc
@@ -169,7 +169,7 @@ void demorgan_worker(
struct OptDemorganPass : public Pass {
OptDemorganPass() : Pass("opt_demorgan", "Optimize reductions with DeMorgan equivalents") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -179,7 +179,7 @@ struct OptDemorganPass : public Pass {
log("overall gate count of the circuit\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) override
{
log_header(design, "Executing OPT_DEMORGAN pass (push inverters through $reduce_* cells).\n");
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 777a24777..1051a59f2 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -117,7 +117,7 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct)
}
void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
- const std::string &info YS_ATTRIBUTE(unused), IdString out_port, RTLIL::SigSpec out_val)
+ const std::string &info, IdString out_port, RTLIL::SigSpec out_val)
{
RTLIL::SigSpec Y = cell->getPort(out_port);
out_val.extend_u0(Y.size(), false);
@@ -467,15 +467,21 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (clkinv)
{
- if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($adff), ID($fsm), ID($memrd), ID($memwr)))
+ if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($fsm), ID($memrd), ID($memwr)))
handle_polarity_inv(cell, ID::CLK, ID::CLK_POLARITY, assign_map, invert_map);
- if (cell->type.in(ID($sr), ID($dffsr), ID($dlatchsr))) {
+ if (cell->type.in(ID($sr), ID($dffsr), ID($dffsre), ID($dlatchsr))) {
handle_polarity_inv(cell, ID::SET, ID::SET_POLARITY, assign_map, invert_map);
handle_polarity_inv(cell, ID::CLR, ID::CLR_POLARITY, assign_map, invert_map);
}
- if (cell->type.in(ID($dffe), ID($dlatch), ID($dlatchsr)))
+ if (cell->type.in(ID($adff), ID($adffe), ID($adlatch)))
+ handle_polarity_inv(cell, ID::ARST, ID::ARST_POLARITY, assign_map, invert_map);
+
+ if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce)))
+ handle_polarity_inv(cell, ID::SRST, ID::SRST_POLARITY, assign_map, invert_map);
+
+ if (cell->type.in(ID($dffe), ID($adffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr)))
handle_polarity_inv(cell, ID::EN, ID::EN_POLARITY, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID::S, assign_map, invert_map);
@@ -489,12 +495,35 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", ID::C, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", ID::R, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFE_N???_", "$_DFFE_P???_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFE_?N??_", "$_DFFE_?P??_", ID::R, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFE_???N_", "$_DFFE_???P_", ID::E, assign_map, invert_map);
+
+ handle_clkpol_celltype_swap(cell, "$_SDFF_N??_", "$_SDFF_P??_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_SDFF_?N?_", "$_SDFF_?P?_", ID::R, assign_map, invert_map);
+
+ handle_clkpol_celltype_swap(cell, "$_SDFFE_N???_", "$_SDFFE_P???_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_SDFFE_?N??_", "$_SDFFE_?P??_", ID::R, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_SDFFE_???N_", "$_SDFFE_???P_", ID::E, assign_map, invert_map);
+
+ handle_clkpol_celltype_swap(cell, "$_SDFFCE_N???_", "$_SDFFCE_P???_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_SDFFCE_?N??_", "$_SDFFCE_?P??_", ID::R, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_SDFFCE_???N_", "$_SDFFCE_???P_", ID::E, assign_map, invert_map);
+
handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", ID::C, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", ID::S, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", ID::R, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFSRE_N???_", "$_DFFSRE_P???_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFSRE_?N??_", "$_DFFSRE_?P??_", ID::S, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFSRE_??N?_", "$_DFFSRE_??P?_", ID::R, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DFFSRE_???N_", "$_DFFSRE_???P_", ID::E, assign_map, invert_map);
+
handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", ID::E, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DLATCH_N??_", "$_DLATCH_P??_", ID::E, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_DLATCH_?N?_", "$_DLATCH_?P?_", ID::R, assign_map, invert_map);
+
handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", ID::E, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", ID::S, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID::R, assign_map, invert_map);
@@ -864,7 +893,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)))
+ ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow)))
{
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = cell->hasPort(ID::B) ? assign_map(cell->getPort(ID::B)) : RTLIL::SigSpec();
@@ -883,7 +912,7 @@ skip_fine_alu:
if (0) {
found_the_x_bit:
cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",
- "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str());
+ "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$divfloor", "$modfloor", "$pow", cell->type.str());
if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt)))
replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx);
else
@@ -1469,6 +1498,8 @@ skip_identity:
FOLD_2ARG_CELL(mul)
FOLD_2ARG_CELL(div)
FOLD_2ARG_CELL(mod)
+ FOLD_2ARG_CELL(divfloor)
+ FOLD_2ARG_CELL(modfloor)
FOLD_2ARG_CELL(pow)
FOLD_1ARG_CELL(pos)
@@ -1583,9 +1614,11 @@ skip_identity:
}
}
- if (!keepdc && cell->type.in(ID($div), ID($mod)))
+ if (!keepdc && cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor)))
{
+ bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
+ SigSpec sig_a = assign_map(cell->getPort(ID::A));
SigSpec sig_b = assign_map(cell->getPort(ID::B));
SigSpec sig_y = assign_map(cell->getPort(ID::Y));
@@ -1610,11 +1643,13 @@ skip_identity:
for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++)
if (b_val == (1 << i))
{
- if (cell->type == ID($div))
+ if (cell->type.in(ID($div), ID($divfloor)))
{
cover("opt.opt_expr.div_shift");
- log_debug("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
+ bool is_truncating = cell->type == ID($div);
+ log_debug("Replacing %s-divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
+ is_truncating ? "truncating" : "flooring",
b_val, cell->name.c_str(), module->name.c_str(), i);
std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
@@ -1622,17 +1657,35 @@ skip_identity:
while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
new_b.pop_back();
- cell->type = ID($shr);
+ cell->type = ID($sshr);
cell->parameters[ID::B_WIDTH] = GetSize(new_b);
cell->parameters[ID::B_SIGNED] = false;
cell->setPort(ID::B, new_b);
+
+ // Truncating division is the same as flooring division, except when
+ // the result is negative and there is a remainder - then trunc = floor + 1
+ if (is_truncating && a_signed) {
+ Wire *flooring = module->addWire(NEW_ID, sig_y.size());
+ cell->setPort(ID::Y, flooring);
+
+ Wire *result_neg = module->addWire(NEW_ID);
+ module->addXor(NEW_ID, sig_a[sig_a.size()-1], sig_b[sig_b.size()-1], result_neg);
+ Wire *rem_nonzero = module->addWire(NEW_ID);
+ module->addReduceOr(NEW_ID, sig_a.extract(0, i), rem_nonzero);
+ Wire *should_add = module->addWire(NEW_ID);
+ module->addAnd(NEW_ID, result_neg, rem_nonzero, should_add);
+ module->addAdd(NEW_ID, flooring, should_add, sig_y);
+ }
+
cell->check();
}
- else
+ else if (cell->type.in(ID($mod), ID($modfloor)))
{
cover("opt.opt_expr.mod_mask");
- log_debug("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
+ bool is_truncating = cell->type == ID($mod);
+ log_debug("Replacing %s-modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
+ is_truncating ? "truncating" : "flooring",
b_val, cell->name.c_str(), module->name.c_str());
std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
@@ -1643,6 +1696,24 @@ skip_identity:
cell->type = ID($and);
cell->parameters[ID::B_WIDTH] = GetSize(new_b);
cell->setPort(ID::B, new_b);
+
+ // truncating modulo has the same masked bits as flooring modulo, but
+ // the sign bits are those of A (except when R=0)
+ if (is_truncating && a_signed) {
+ Wire *flooring = module->addWire(NEW_ID, sig_y.size());
+ cell->setPort(ID::Y, flooring);
+ SigSpec truncating = SigSpec(flooring).extract(0, i);
+
+ Wire *rem_nonzero = module->addWire(NEW_ID);
+ module->addReduceOr(NEW_ID, truncating, rem_nonzero);
+ SigSpec a_sign = sig_a[sig_a.size()-1];
+ Wire *extend_bit = module->addWire(NEW_ID);
+ module->addAnd(NEW_ID, a_sign, rem_nonzero, extend_bit);
+
+ truncating.append(extend_bit);
+ module->addPos(NEW_ID, truncating, sig_y, true);
+ }
+
cell->check();
}
@@ -1967,7 +2038,7 @@ skip_alu_split:
struct OptExprPass : public Pass {
OptExprPass() : Pass("opt_expr", "perform const folding and simple expression rewriting") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -2001,7 +2072,7 @@ struct OptExprPass : public Pass {
log(" replaced by 'a'. the -keepdc option disables all such optimizations.\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) override
{
bool mux_undef = false;
bool mux_bool = false;
diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc
index 12927d052..07a91af8a 100644
--- a/passes/opt/opt_lut.cc
+++ b/passes/opt/opt_lut.cc
@@ -520,7 +520,7 @@ static void split(std::vector<std::string> &tokens, const std::string &text, cha
struct OptLutPass : public Pass {
OptLutPass() : Pass("opt_lut", "optimize LUT cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -538,7 +538,7 @@ struct OptLutPass : public Pass {
log(" only perform the first N combines, then stop. useful for debugging.\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) override
{
log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n");
diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc
index 1d32e84bb..bb40e1e55 100644
--- a/passes/opt/opt_lut_ins.cc
+++ b/passes/opt/opt_lut_ins.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct OptLutInsPass : public Pass {
OptLutInsPass() : Pass("opt_lut_ins", "discard unused LUT inputs") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -42,7 +42,7 @@ struct OptLutInsPass : public Pass {
log(" to the given technology. Valid values are: xilinx, ecp5, gowin.\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) override
{
log_header(design, "Executing OPT_LUT_INS pass (discard unused LUT inputs).\n");
string techname;
diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc
index ff9c06453..24df1356b 100644
--- a/passes/opt/opt_mem.cc
+++ b/passes/opt/opt_mem.cc
@@ -97,7 +97,7 @@ struct OptMemWorker
struct OptMemPass : public Pass {
OptMemPass() : Pass("opt_mem", "optimize memories") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -106,7 +106,7 @@ struct OptMemPass : public Pass {
log("This pass performs various optimizations on memories in the design.\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) override
{
log_header(design, "Executing OPT_MEM pass (optimize memories).\n");
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index d845926fc..f03faa9cf 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -298,9 +298,7 @@ struct OptMergeWorker
module->connect(RTLIL::SigSig(it.second, other_sig));
assign_map.add(it.second, other_sig);
- 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 (auto c : it.second.chunks()) {
auto jt = c.wire->attributes.find(ID::init);
if (jt == c.wire->attributes.end())
@@ -326,7 +324,7 @@ struct OptMergeWorker
struct OptMergePass : public Pass {
OptMergePass() : Pass("opt_merge", "consolidate identical cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -342,7 +340,7 @@ struct OptMergePass : public Pass {
log(" Operate on all cell types, not just built-in types.\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) override
{
log_header(design, "Executing OPT_MERGE pass (detect identical cells).\n");
diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc
index d076addae..67b283e11 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -473,7 +473,7 @@ struct OptMuxtreeWorker
struct OptMuxtreePass : public Pass {
OptMuxtreePass() : Pass("opt_muxtree", "eliminate dead trees in multiplexer trees") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -486,7 +486,7 @@ struct OptMuxtreePass : public Pass {
log("This pass only operates on completely selected modules without processes.\n");
log("\n");
}
- void execute(vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n");
extra_args(args, 1, design);
diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc
index f640f50a0..28de9ceb6 100644
--- a/passes/opt/opt_reduce.cc
+++ b/passes/opt/opt_reduce.cc
@@ -332,7 +332,7 @@ struct OptReduceWorker
struct OptReducePass : public Pass {
OptReducePass() : Pass("opt_reduce", "simplify large MUXes and AND/OR gates") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -353,7 +353,7 @@ struct OptReducePass : public Pass {
log(" alias for -fine\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) override
{
bool do_fine = false;
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc
index 81326a417..8f7628a4a 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -540,7 +540,7 @@ delete_dff:
struct OptRmdffPass : public Pass {
OptRmdffPass() : Pass("opt_rmdff", "remove DFFs with constant inputs") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -554,7 +554,7 @@ struct OptRmdffPass : public Pass {
log(" non-constant inputs) that can also be replaced with a constant driver\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) override
{
int total_count = 0, total_initdrv = 0;
log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n");
diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc
index 1f69c98f4..db21cef28 100644
--- a/passes/opt/opt_share.cc
+++ b/passes/opt/opt_share.cc
@@ -103,7 +103,7 @@ bool cell_supported(RTLIL::Cell *cell)
if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci)
return true;
- } else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($concat))) {
+ } else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($concat))) {
return true;
}
@@ -130,7 +130,7 @@ bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b)
RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name)
{
- if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID::B)
+ if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($concat), SHIFT_OPS) && port_name == ID::B)
return port_name;
return "";
@@ -473,7 +473,7 @@ dict<RTLIL::SigSpec, OpMuxConn> find_valid_op_mux_conns(RTLIL::Module *module, d
struct OptSharePass : public Pass {
OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {}
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -488,7 +488,7 @@ struct OptSharePass : public Pass {
log("multiplexing its output to multiplexing the non-shared input signals.\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) override
{
log_header(design, "Executing OPT_SHARE pass.\n");
diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc
index 11b80b6b3..9f226e12d 100644
--- a/passes/opt/pmux2shiftx.cc
+++ b/passes/opt/pmux2shiftx.cc
@@ -63,11 +63,13 @@ struct OnehotDatabase
vector<SigSpec> inputs;
SigSpec output;
- if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff)))
+ if (cell->type.in(ID($adff), ID($adffe), ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($ff)))
{
output = cell->getPort(ID::Q);
- if (cell->type == ID($adff))
+ if (cell->type.in(ID($adff), ID($adffe), ID($adlatch)))
inputs.push_back(cell->getParam(ID::ARST_VALUE));
+ if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce)))
+ inputs.push_back(cell->getParam(ID::SRST_VALUE));
inputs.push_back(cell->getPort(ID::D));
}
@@ -198,7 +200,7 @@ struct OnehotDatabase
struct Pmux2ShiftxPass : public Pass {
Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -225,7 +227,7 @@ struct Pmux2ShiftxPass : public Pass {
log(" disable $sub inference for \"range decoders\"\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) override
{
int min_density = 50;
int min_choices = 3;
@@ -737,7 +739,7 @@ struct Pmux2ShiftxPass : public Pass {
struct OnehotPass : public Pass {
OnehotPass() : Pass("onehot", "optimize $eq cells for onehot signals") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -749,7 +751,7 @@ struct OnehotPass : public Pass {
log(" verbose output\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) override
{
bool verbose = false;
bool verbose_onehot = false;
diff --git a/passes/opt/rmports.cc b/passes/opt/rmports.cc
index 32363dd68..99a2a61c8 100644
--- a/passes/opt/rmports.cc
+++ b/passes/opt/rmports.cc
@@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN
struct RmportsPassPass : public Pass {
RmportsPassPass() : Pass("rmports", "remove module ports with no connections") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -39,7 +39,7 @@ struct RmportsPassPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing RMPORTS pass (remove ports with no connections).\n");
diff --git a/passes/opt/share.cc b/passes/opt/share.cc
index 2839507b0..f7848e01d 100644
--- a/passes/opt/share.cc
+++ b/passes/opt/share.cc
@@ -376,7 +376,7 @@ struct ShareWorker
continue;
}
- if (cell->type.in(ID($mul), ID($div), ID($mod))) {
+ if (cell->type.in(ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor))) {
if (config.opt_aggressive || cell->parameters.at(ID::Y_WIDTH).as_int() >= 4)
shareable_cells.insert(cell);
continue;
@@ -1133,6 +1133,8 @@ struct ShareWorker
cone_ct.cell_types.erase(ID($mul));
cone_ct.cell_types.erase(ID($mod));
cone_ct.cell_types.erase(ID($div));
+ cone_ct.cell_types.erase(ID($modfloor));
+ cone_ct.cell_types.erase(ID($divfloor));
cone_ct.cell_types.erase(ID($pow));
cone_ct.cell_types.erase(ID($shl));
cone_ct.cell_types.erase(ID($shr));
@@ -1442,7 +1444,7 @@ struct ShareWorker
struct SharePass : public Pass {
SharePass() : Pass("share", "perform sat-based resource sharing") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1474,7 +1476,7 @@ struct SharePass : public Pass {
log(" Only perform the first N merges, then stop. This is useful for debugging.\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) override
{
ShareWorkerConfig config;
@@ -1512,6 +1514,8 @@ struct SharePass : public Pass {
config.generic_bin_ops.insert(ID($sub));
config.generic_bin_ops.insert(ID($div));
config.generic_bin_ops.insert(ID($mod));
+ config.generic_bin_ops.insert(ID($divfloor));
+ config.generic_bin_ops.insert(ID($modfloor));
// config.generic_bin_ops.insert(ID($pow));
config.generic_uni_ops.insert(ID($logic_not));
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index 195400bf0..78e2bcbea 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -37,9 +37,10 @@ struct WreduceConfig
ID($and), ID($or), ID($xor), ID($xnor),
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($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow),
ID($mux), ID($pmux),
- ID($dff), ID($adff)
+ ID($dff), ID($dffe), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce),
+ ID($dlatch), ID($adlatch),
});
}
};
@@ -143,8 +144,8 @@ struct WreduceWorker
SigSpec sig_d = mi.sigmap(cell->getPort(ID::D));
SigSpec sig_q = mi.sigmap(cell->getPort(ID::Q));
- bool is_adff = (cell->type == ID($adff));
- Const initval, arst_value;
+ bool has_reset = false;
+ Const initval, rst_value;
int width_before = GetSize(sig_q);
@@ -152,7 +153,11 @@ struct WreduceWorker
return;
if (cell->parameters.count(ID::ARST_VALUE)) {
- arst_value = cell->parameters[ID::ARST_VALUE];
+ rst_value = cell->parameters[ID::ARST_VALUE];
+ has_reset = true;
+ } else if (cell->parameters.count(ID::SRST_VALUE)) {
+ rst_value = cell->parameters[ID::SRST_VALUE];
+ has_reset = true;
}
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
@@ -169,7 +174,7 @@ struct WreduceWorker
for (int i = GetSize(sig_q)-1; i >= 0; i--)
{
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx) &&
- (!is_adff || i >= GetSize(arst_value) || arst_value[i] == State::S0 || arst_value[i] == State::Sx)) {
+ (!has_reset || i >= GetSize(rst_value) || rst_value[i] == State::S0 || rst_value[i] == State::Sx)) {
module->connect(sig_q[i], State::S0);
remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
@@ -178,7 +183,7 @@ struct WreduceWorker
}
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1] &&
- (!is_adff || i >= GetSize(arst_value) || arst_value[i] == arst_value[i-1])) {
+ (!has_reset || i >= GetSize(rst_value) || rst_value[i] == rst_value[i-1])) {
module->connect(sig_q[i], sig_q[i-1]);
remove_init_bits.insert(sig_q[i]);
sig_d.remove(i);
@@ -221,8 +226,11 @@ struct WreduceWorker
// Narrow ARST_VALUE parameter to new size.
if (cell->parameters.count(ID::ARST_VALUE)) {
- arst_value.bits.resize(GetSize(sig_q));
- cell->setParam(ID::ARST_VALUE, arst_value);
+ rst_value.bits.resize(GetSize(sig_q));
+ cell->setParam(ID::ARST_VALUE, rst_value);
+ } else if (cell->parameters.count(ID::SRST_VALUE)) {
+ rst_value.bits.resize(GetSize(sig_q));
+ cell->setParam(ID::SRST_VALUE, rst_value);
}
cell->setPort(ID::D, sig_d);
@@ -272,7 +280,7 @@ struct WreduceWorker
if (cell->type.in(ID($mux), ID($pmux)))
return run_cell_mux(cell);
- if (cell->type.in(ID($dff), ID($adff)))
+ if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch)))
return run_cell_dff(cell);
SigSpec sig = mi.sigmap(cell->getPort(ID::Y));
@@ -482,7 +490,7 @@ struct WreduceWorker
struct WreducePass : public Pass {
WreducePass() : Pass("wreduce", "reduce the word size of operations if possible") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -505,7 +513,7 @@ struct WreducePass : public Pass {
log(" Do not optimize explicit don't-care values.\n");
log("\n");
}
- void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, Design *design) override
{
WreduceConfig config;
bool opt_memx = false;
@@ -545,7 +553,7 @@ struct WreducePass : public Pass {
}
}
- if (c->type.in(ID($div), ID($mod), ID($pow)))
+ if (c->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow)))
{
SigSpec A = c->getPort(ID::A);
int original_a_width = GetSize(A);
diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc
index f16cc4a0b..fff04074b 100644
--- a/passes/pmgen/ice40_dsp.cc
+++ b/passes/pmgen/ice40_dsp.cc
@@ -275,7 +275,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
struct Ice40DspPass : public Pass {
Ice40DspPass() : Pass("ice40_dsp", "iCE40: map multipliers") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -294,7 +294,7 @@ struct Ice40DspPass : public Pass {
log("the accumulator to an arbitrary value can be inferred to use the {C,D} input.\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) override
{
log_header(design, "Executing ICE40_DSP pass (map multipliers).\n");
diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc
index 97d2008c2..e234906ad 100644
--- a/passes/pmgen/ice40_wrapcarry.cc
+++ b/passes/pmgen/ice40_wrapcarry.cc
@@ -72,7 +72,7 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
struct Ice40WrapCarryPass : public Pass {
Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -91,7 +91,7 @@ struct Ice40WrapCarryPass : public Pass {
log(" including restoring their attributes.\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) override
{
bool unwrap = false;
diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc
index 4379ce1e6..c16b4486d 100644
--- a/passes/pmgen/peepopt.cc
+++ b/passes/pmgen/peepopt.cc
@@ -32,7 +32,7 @@ pool<SigBit> rminitbits;
struct PeepoptPass : public Pass {
PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -41,7 +41,7 @@ struct PeepoptPass : public Pass {
log("This pass applies a collection of peephole optimizers to the current design.\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) override
{
std::string genmode;
diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py
index df0ffaff2..592a26fa6 100644
--- a/passes/pmgen/pmgen.py
+++ b/passes/pmgen/pmgen.py
@@ -589,7 +589,7 @@ with open(outfile, "w") as f:
if block["type"] in ("match", "code"):
print(" // {}".format(block["src"]), file=f)
- print(" void block_{}(int recursion YS_ATTRIBUTE(unused)) {{".format(index), file=f)
+ print(" void block_{}(int recursion YS_MAYBE_UNUSED) {{".format(index), file=f)
current_pattern, current_subpattern = block["pattern"]
if block["type"] == "final":
@@ -636,17 +636,17 @@ with open(outfile, "w") as f:
for s in sorted(const_st):
t = state_types[current_pattern][s]
if t.endswith("*"):
- print(" {} const &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
+ print(" {} const &{} YS_MAYBE_UNUSED = st_{}.{};".format(t, s, current_pattern, s), file=f)
else:
- print(" const {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
+ print(" const {} &{} YS_MAYBE_UNUSED = st_{}.{};".format(t, s, current_pattern, s), file=f)
for s in sorted(nonconst_st):
t = state_types[current_pattern][s]
- print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)
+ print(" {} &{} YS_MAYBE_UNUSED = st_{}.{};".format(t, s, current_pattern, s), file=f)
for u in sorted(udata_types[current_pattern].keys()):
t = udata_types[current_pattern][u]
- print(" {} &{} YS_ATTRIBUTE(unused) = ud_{}.{};".format(t, u, current_pattern, u), file=f)
+ print(" {} &{} YS_MAYBE_UNUSED = ud_{}.{};".format(t, u, current_pattern, u), file=f)
if len(restore_st):
print("", file=f)
@@ -676,7 +676,7 @@ with open(outfile, "w") as f:
print("", file=f)
print("rollback_label:", file=f)
- print(" YS_ATTRIBUTE(unused);", file=f)
+ print(" YS_MAYBE_UNUSED;", file=f)
if len(block["fcode"]):
print("#define accept do { accept_cnt++; on_accept(); } while(0)", file=f)
@@ -684,7 +684,7 @@ with open(outfile, "w") as f:
for line in block["fcode"]:
print(" " + line, file=f)
print("finish_label:", file=f)
- print(" YS_ATTRIBUTE(unused);", file=f)
+ print(" YS_MAYBE_UNUSED;", file=f)
print("#undef accept", file=f)
print("#undef finish", file=f)
@@ -733,13 +733,13 @@ with open(outfile, "w") as f:
valueidx = 1
for item in block["setup"]:
if item[0] == "slice":
- print(" const int &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], valueidx), file=f)
+ print(" const int &{} YS_MAYBE_UNUSED = std::get<{}>(cells[_pmg_idx]);".format(item[1], valueidx), file=f)
valueidx += 1
if item[0] == "choice":
- print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
+ print(" const {} &{} YS_MAYBE_UNUSED = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
valueidx += 1
if item[0] == "define":
- print(" const {} &{} YS_ATTRIBUTE(unused) = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
+ print(" const {} &{} YS_MAYBE_UNUSED = std::get<{}>(cells[_pmg_idx]);".format(item[1], item[2], valueidx), file=f)
valueidx += 1
print(" if (blacklist_cells.count({})) continue;".format(block["cell"]), file=f)
for expr in block["filter"]:
diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc
index 9cfad03ef..7b2938ddf 100644
--- a/passes/pmgen/test_pmgen.cc
+++ b/passes/pmgen/test_pmgen.cc
@@ -118,7 +118,7 @@ void opt_eqpmux(test_pmgen_pm &pm)
struct TestPmgenPass : public Pass {
TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -239,7 +239,7 @@ struct TestPmgenPass : public Pass {
log_cmd_error("Unknown pattern: %s\n", pattern.c_str());
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
if (GetSize(args) > 1)
{
diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc
index f1f4b4206..d05157270 100644
--- a/passes/pmgen/xilinx_dsp.cc
+++ b/passes/pmgen/xilinx_dsp.cc
@@ -744,7 +744,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm)
struct XilinxDspPass : public Pass {
XilinxDspPass() : Pass("xilinx_dsp", "Xilinx: pack resources into DSPs") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -785,7 +785,7 @@ struct XilinxDspPass : public Pass {
log(" default: xc7\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) override
{
log_header(design, "Executing XILINX_DSP pass (pack resources into DSPs).\n");
diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc
index b99653fb3..1410850c7 100644
--- a/passes/pmgen/xilinx_srl.cc
+++ b/passes/pmgen/xilinx_srl.cc
@@ -188,7 +188,7 @@ void run_variable(xilinx_srl_pm &pm)
struct XilinxSrlPass : public Pass {
XilinxSrlPass() : Pass("xilinx_srl", "Xilinx shift register extraction") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -212,7 +212,7 @@ struct XilinxSrlPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing XILINX_SRL pass (Xilinx shift register extraction).\n");
diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc
index a5b4a3112..f20a167b4 100644
--- a/passes/proc/proc.cc
+++ b/passes/proc/proc.cc
@@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ProcPass : public Pass {
ProcPass() : Pass("proc", "translate processes to netlists") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -58,7 +58,7 @@ struct ProcPass : public Pass {
log(" executed in -ifx mode.\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) override
{
std::string global_arst;
bool ifxmode = false;
diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc
index e400fcb72..16db461b2 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -203,7 +203,7 @@ restart_proc_arst:
struct ProcArstPass : public Pass {
ProcArstPass() : Pass("proc_arst", "detect asynchronous resets") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -221,7 +221,7 @@ struct ProcArstPass : public Pass {
log(" in the 'init' attribute on the net.\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) override
{
std::string global_arst;
bool global_arst_neg = false;
diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc
index 114c6ab03..5e78b7316 100644
--- a/passes/proc/proc_clean.cc
+++ b/passes/proc/proc_clean.cc
@@ -166,7 +166,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool
struct ProcCleanPass : public Pass {
ProcCleanPass() : Pass("proc_clean", "remove empty parts of processes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -179,7 +179,7 @@ struct ProcCleanPass : public Pass {
log("if it contains only empty structures.\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) override
{
int total_count = 0;
bool quiet = false;
diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc
index 59cc5bd65..e320a72a6 100644
--- a/passes/proc/proc_dff.cc
+++ b/passes/proc/proc_dff.cc
@@ -370,7 +370,7 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
struct ProcDffPass : public Pass {
ProcDffPass() : Pass("proc_dff", "extract flip-flops from processes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -380,7 +380,7 @@ struct ProcDffPass : public Pass {
log("d-type flip-flop cells.\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) override
{
log_header(design, "Executing PROC_DFF pass (convert process syncs to FFs).\n");
diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc
index c9da1d1e3..e7c8a80dd 100644
--- a/passes/proc/proc_dlatch.cc
+++ b/passes/proc/proc_dlatch.cc
@@ -434,7 +434,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
struct ProcDlatchPass : public Pass {
ProcDlatchPass() : Pass("proc_dlatch", "extract latches from processes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -444,7 +444,7 @@ struct ProcDlatchPass : public Pass {
log("d-type latches.\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) override
{
log_header(design, "Executing PROC_DLATCH pass (convert process syncs to latches).\n");
diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc
index dc00019aa..eb323038d 100644
--- a/passes/proc/proc_init.cc
+++ b/passes/proc/proc_init.cc
@@ -86,7 +86,7 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
struct ProcInitPass : public Pass {
ProcInitPass() : Pass("proc_init", "convert initial block to init attributes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -97,7 +97,7 @@ struct ProcInitPass : public Pass {
log("respective wire.\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) override
{
log_header(design, "Executing PROC_INIT pass (extract init attributes).\n");
diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc
index 867ba1698..d20f34534 100644
--- a/passes/proc/proc_mux.cc
+++ b/passes/proc/proc_mux.cc
@@ -438,7 +438,7 @@ void proc_mux(RTLIL::Module *mod, RTLIL::Process *proc, bool ifxmode)
struct ProcMuxPass : public Pass {
ProcMuxPass() : Pass("proc_mux", "convert decision trees to multiplexers") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -452,7 +452,7 @@ struct ProcMuxPass : public Pass {
log(" 'case' expressions and 'if' conditions.\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) override
{
bool ifxmode = false;
log_header(design, "Executing PROC_MUX pass (convert decision trees to multiplexers).\n");
diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc
index 8d11447f6..bd122b91f 100644
--- a/passes/proc/proc_prune.cc
+++ b/passes/proc/proc_prune.cc
@@ -125,7 +125,7 @@ struct PruneWorker
struct ProcPrunePass : public Pass {
ProcPrunePass() : Pass("proc_prune", "remove redundant assignments") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -135,7 +135,7 @@ struct ProcPrunePass : public Pass {
log("a later assignment to the same signal and removes them.\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) override
{
int total_removed_count = 0, total_promoted_count = 0;
log_header(design, "Executing PROC_PRUNE pass (remove redundant assignments in processes).\n");
diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc
index 6afaf25d1..ee91637ca 100644
--- a/passes/proc/proc_rmdead.cc
+++ b/passes/proc/proc_rmdead.cc
@@ -70,7 +70,7 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
struct ProcRmdeadPass : public Pass {
ProcRmdeadPass() : Pass("proc_rmdead", "eliminate dead trees in decision trees") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -79,7 +79,7 @@ struct ProcRmdeadPass : public Pass {
log("This pass identifies unreachable branches in decision trees and removes them.\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) override
{
log_header(design, "Executing PROC_RMDEAD pass (remove dead branches from decision trees).\n");
diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc
index 5bf2296ab..e9a10465e 100644
--- a/passes/sat/assertpmux.cc
+++ b/passes/sat/assertpmux.cc
@@ -181,7 +181,7 @@ struct AssertpmuxWorker
struct AssertpmuxPass : public Pass {
AssertpmuxPass() : Pass("assertpmux", "adds asserts for parallel muxes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -199,7 +199,7 @@ struct AssertpmuxPass : public Pass {
log(" additional constraint and check the $pmux condition always.\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) override
{
bool flag_noinit = false;
bool flag_always = false;
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc
index e344e2b5b..6fc480925 100644
--- a/passes/sat/async2sync.cc
+++ b/passes/sat/async2sync.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct Async2syncPass : public Pass {
Async2syncPass() : Pass("async2sync", "convert async FF inputs to sync circuits") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -42,7 +42,7 @@ struct Async2syncPass : public Pass {
log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\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) override
{
// bool flag_noinit = false;
diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc
index 1e155e52c..e5c5d0486 100644
--- a/passes/sat/clk2fflogic.cc
+++ b/passes/sat/clk2fflogic.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct Clk2fflogicPass : public Pass {
Clk2fflogicPass() : Pass("clk2fflogic", "convert clocked FFs to generic $ff cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -36,7 +36,7 @@ struct Clk2fflogicPass : public Pass {
log("multiple clocks.\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) override
{
// bool flag_noinit = false;
diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc
index 26cc69211..6fc267d51 100644
--- a/passes/sat/cutpoint.cc
+++ b/passes/sat/cutpoint.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct CutpointPass : public Pass {
CutpointPass() : Pass("cutpoint", "adds formal cut points to the design") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -38,7 +38,7 @@ struct CutpointPass : public Pass {
log(" $anyseq cell and drive the cutpoint net from that\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) override
{
bool flag_undef = false;
@@ -126,15 +126,16 @@ struct CutpointPass : public Pass {
}
vector<Wire*> rewrite_wires;
- for (auto wire : module->wires()) {
- if (!wire->port_input)
- continue;
- int bit_count = 0;
- for (auto &bit : sigmap(wire))
- if (cutpoint_bits.count(bit))
- bit_count++;
- if (bit_count)
- rewrite_wires.push_back(wire);
+ for (auto id : module->ports) {
+ RTLIL::Wire *wire = module->wire(id);
+ if (wire->port_input) {
+ int bit_count = 0;
+ for (auto &bit : sigmap(wire))
+ if (cutpoint_bits.count(bit))
+ bit_count++;
+ if (bit_count)
+ rewrite_wires.push_back(wire);
+ }
}
for (auto wire : rewrite_wires) {
diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc
index f910ea80d..085e7c5b8 100644
--- a/passes/sat/eval.cc
+++ b/passes/sat/eval.cc
@@ -359,7 +359,7 @@ struct VlogHammerReporter
struct EvalPass : public Pass {
EvalPass() : Pass("eval", "evaluate the circuit given an input") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -382,7 +382,7 @@ struct EvalPass : public Pass {
log(" then all output ports of the current module are used.\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) override
{
std::vector<std::pair<std::string, std::string>> sets;
std::vector<std::string> shows, tables;
diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc
index 80ab82cd5..2c65821cf 100644
--- a/passes/sat/expose.cc
+++ b/passes/sat/expose.cc
@@ -217,7 +217,7 @@ RTLIL::Wire *add_new_wire(RTLIL::Module *module, RTLIL::IdString name, int width
struct ExposePass : public Pass {
ExposePass() : Pass("expose", "convert internal signals to module ports") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -254,7 +254,7 @@ struct ExposePass : public Pass {
log(" designator for the exposed signal.\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) override
{
bool flag_shared = false;
bool flag_evert = false;
@@ -281,11 +281,15 @@ struct ExposePass : public Pass {
flag_dff = true;
continue;
}
- if (args[argidx] == "-cut" && !flag_input) {
+ if (args[argidx] == "-cut") {
+ if (flag_input)
+ log_cmd_error("Options -cut and -input are mutually exclusive.\n");
flag_cut = true;
continue;
}
- if (args[argidx] == "-input" && !flag_cut) {
+ if (args[argidx] == "-input") {
+ if (flag_cut)
+ log_cmd_error("Options -cut and -input are mutually exclusive.\n");
flag_input = true;
continue;
}
@@ -445,6 +449,8 @@ struct ExposePass : public Pass {
SigMap out_to_in_map;
+ std::map<RTLIL::Wire*, RTLIL::IdString> wire_map;
+
for (auto w : module->wires())
{
if (flag_shared) {
@@ -462,8 +468,7 @@ struct ExposePass : public Pass {
if (!w->port_input) {
w->port_input = true;
log("New module port: %s/%s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(w->name));
- RTLIL::Wire *in_wire = module->addWire(NEW_ID, GetSize(w));
- out_to_in_map.add(w, in_wire);
+ wire_map[w] = NEW_ID;
}
}
else
@@ -474,15 +479,19 @@ struct ExposePass : public Pass {
}
if (flag_cut) {
- RTLIL::Wire *in_wire = add_new_wire(module, w->name.str() + sep + "i", w->width);
- in_wire->port_input = true;
- out_to_in_map.add(sigmap(w), in_wire);
+ wire_map[w] = w->name.str() + sep + "i";
}
}
}
if (flag_input)
{
+ for (auto &wm : wire_map)
+ {
+ RTLIL::Wire *in_wire = module->addWire(wm.second, GetSize(wm.first));
+ out_to_in_map.add(wm.first, in_wire);
+ }
+
for (auto cell : module->cells()) {
if (!ct.cell_known(cell->type))
continue;
@@ -497,6 +506,13 @@ struct ExposePass : public Pass {
if (flag_cut)
{
+ for (auto &wm : wire_map)
+ {
+ RTLIL::Wire *in_wire = add_new_wire(module, wm.second, wm.first->width);
+ in_wire->port_input = true;
+ out_to_in_map.add(sigmap(wm.first), in_wire);
+ }
+
for (auto cell : module->cells()) {
if (!ct.cell_known(cell->type))
continue;
diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc
index 5066485aa..cb49edac3 100644
--- a/passes/sat/fmcombine.cc
+++ b/passes/sat/fmcombine.cc
@@ -114,8 +114,7 @@ struct FmcombineWorker
Cell *gold = import_prim_cell(cell, "_gold");
Cell *gate = import_prim_cell(cell, "_gate");
if (opts.initeq) {
- if (cell->type.in(ID($ff), ID($dff), ID($dffe),
- ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr))) {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
SigSpec gold_q = gold->getPort(ID::Q);
SigSpec gate_q = gate->getPort(ID::Q);
SigSpec en = module->Initstate(NEW_ID);
@@ -235,7 +234,7 @@ struct FmcombineWorker
struct FmcombinePass : public Pass {
FmcombinePass() : Pass("fmcombine", "combine two instances of a cell into one") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -272,7 +271,7 @@ struct FmcombinePass : public Pass {
log("If none of -fwd, -bwd, and -nop is given, then -fwd is used as default.\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) override
{
opts_t opts;
Module *module = nullptr;
diff --git a/passes/sat/fminit.cc b/passes/sat/fminit.cc
index 555a28dc6..c72e62548 100644
--- a/passes/sat/fminit.cc
+++ b/passes/sat/fminit.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct FminitPass : public Pass {
FminitPass() : Pass("fminit", "set init values/sequences for formal") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -47,7 +47,7 @@ struct FminitPass : public Pass {
log(" Set clock for init sequences\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) override
{
vector<pair<string, vector<string>>> initdata;
vector<pair<string, string>> setdata;
diff --git a/passes/sat/freduce.cc b/passes/sat/freduce.cc
index 5dfd7bd3f..762edfdfb 100644
--- a/passes/sat/freduce.cc
+++ b/passes/sat/freduce.cc
@@ -760,7 +760,7 @@ struct FreduceWorker
struct FreducePass : public Pass {
FreducePass() : Pass("freduce", "perform functional reduction") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -791,7 +791,7 @@ struct FreducePass : public Pass {
log("circuit that is analyzed.\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) override
{
reduce_counter = 0;
reduce_stop_at = 0;
diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc
index aeece9b94..fe4a819f3 100644
--- a/passes/sat/miter.cc
+++ b/passes/sat/miter.cc
@@ -354,7 +354,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
struct MiterPass : public Pass {
MiterPass() : Pass("miter", "automatically create a miter circuit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -398,7 +398,7 @@ struct MiterPass : public Pass {
log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\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) override
{
if (args.size() > 1 && args[1] == "-equiv") {
create_miter_equiv(this, args, design);
diff --git a/passes/sat/mutate.cc b/passes/sat/mutate.cc
index af8ffca9e..15abee73e 100644
--- a/passes/sat/mutate.cc
+++ b/passes/sat/mutate.cc
@@ -726,7 +726,7 @@ void mutate_cnot(Design *design, const mutate_opts_t &opts, bool one)
struct MutatePass : public Pass {
MutatePass() : Pass("mutate", "generate or apply design mutations") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -790,7 +790,7 @@ struct MutatePass : public Pass {
log(" Ignored. (They are generated by -list for documentation purposes.)\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) override
{
mutate_opts_t opts;
string filename;
diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc
index d99ca1b53..46f7f5070 100644
--- a/passes/sat/qbfsat.cc
+++ b/passes/sat/qbfsat.cc
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2020 Alberto Gonzalez <boqwxp@airmail.cc>
@@ -18,216 +18,149 @@
*/
#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
+#include "kernel/consteval.h"
+#include "qbfsat.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-struct QbfSolutionType {
- std::vector<std::string> stdout_lines;
- 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, assume_neg;
- 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), assume_neg(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_lines) {
- 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
+static inline unsigned int difference(unsigned int a, unsigned int b) {
+ if (a < b)
+ return b - a;
+ else
+ return a - b;
}
-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() && cell->type.in("$anyconst", "$anyseq")) {
- log_assert(hole_loc_to_name.find(pos->first) == hole_loc_to_name.end());
- hole_loc_to_name[pos->first] = cell->getPort(ID::Y).as_wire()->name.str();
+pool<std::string> validate_design_and_get_inputs(RTLIL::Module *module, bool assume_outputs) {
+ 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 && !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 hole_loc_to_name;
+ return input_wires;
}
-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");
+void specialize_from_file(RTLIL::Module *module, const std::string &file) {
+ YS_REGEX_TYPE hole_bit_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.+) ([0-9]+) ([^ ]+) \\[([0-9]+)] = ([01])$");
+ YS_REGEX_TYPE hole_assn_regex = YS_REGEX_COMPILE_WITH_SUBS("^(.+) ([0-9]+) ([^ ]+) = ([01])$"); //if no index specified
+ YS_REGEX_MATCH_TYPE bit_m, m;
+ dict<pool<std::string>, RTLIL::Cell*> anyconst_loc_to_cell;
+ dict<RTLIL::SigBit, RTLIL::State> hole_assignments;
- 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;
-}
+ for (auto cell : module->cells())
+ if (cell->type == "$anyconst")
+ anyconst_loc_to_cell[cell->get_strpool_attribute(ID::src)] = cell;
-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;
- }
+ bool bit_assn = true;
+ if (!YS_REGEX_NS::regex_search(buf, bit_m, hole_bit_assn_regex)) {
+ bit_assn = false;
+ if (!YS_REGEX_NS::regex_search(buf, m, hole_assn_regex))
+ log_cmd_error("solution file is not formatted correctly: \"%s\"\n", buf.c_str());
+ }
- 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);
+ std::string hole_loc = bit_assn? bit_m[1].str() : m[1].str();
+ unsigned int hole_bit = bit_assn? atoi(bit_m[2].str().c_str()) : atoi(m[2].str().c_str());
+ std::string hole_name = bit_assn? bit_m[3].str() : m[3].str();
+ unsigned int hole_offset = bit_assn? atoi(bit_m[4].str().c_str()) : 0;
+ RTLIL::State hole_value = bit_assn? (atoi(bit_m[5].str().c_str()) == 1? RTLIL::State::S1 : RTLIL::State::S0)
+ : (atoi(m[4].str().c_str()) == 1? RTLIL::State::S1 : RTLIL::State::S0);
+
+ //We have two options to identify holes. First, try to match wire names. If we can't find a matching wire,
+ //then try to find a cell with a matching location.
+ RTLIL::SigBit hole_sigbit;
+ if (module->wire(hole_name) != nullptr) {
+ RTLIL::Wire *hole_wire = module->wire(hole_name);
+ hole_sigbit = RTLIL::SigSpec(hole_wire)[hole_offset];
+ } else {
+ auto locs = split_tokens(hole_loc, "|");
+ pool<std::string> hole_loc_pool(locs.begin(), locs.end());
+ auto hole_cell_it = anyconst_loc_to_cell.find(hole_loc_pool);
+ if (hole_cell_it == anyconst_loc_to_cell.end())
+ log_cmd_error("cannot find matching wire name or $anyconst cell location for hole spec \"%s\"\n", buf.c_str());
+
+ RTLIL::Cell *hole_cell = hole_cell_it->second;
+ hole_sigbit = hole_cell->getPort(ID::Y)[hole_bit];
}
- for (auto cell : anyconsts_to_remove)
- module->remove(cell);
+ hole_assignments[hole_sigbit] = hole_value;
+ }
- 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);
+ for (auto &it : anyconst_loc_to_cell)
+ module->remove(it.second);
+
+ for (auto &it : hole_assignments) {
+ RTLIL::SigSpec lhs(it.first);
+ RTLIL::SigSpec rhs(it.second);
+ log("Specializing %s from file with %s = %d.\n", module->name.c_str(), log_signal(it.first), it.second == RTLIL::State::S1? 1 : 0);
+ module->connect(lhs, rhs);
}
}
-void specialize(RTLIL::Module *module, const QbfSolutionType &sol) {
- dict<std::string, std::string> hole_loc_to_name = get_hole_loc_name_map(module, sol);
+void specialize(RTLIL::Module *module, const QbfSolutionType &sol, bool quiet = false) {
+ auto hole_loc_idx_to_sigbit = sol.get_hole_loc_idx_sigbit_map(module);
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())
+ if (hole_loc_idx_to_sigbit.find(std::make_pair(cell->get_strpool_attribute(ID::src), 0)) != hole_loc_idx_to_sigbit.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;
+ pool<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());
+ for (unsigned int i = 0; i < hole_value.size(); ++i) {
+ int bit_idx = GetSize(hole_value) - 1 - i;
+ auto it = hole_loc_idx_to_sigbit.find(std::make_pair(hole_loc, i));
+ log_assert(it != hole_loc_idx_to_sigbit.end());
+
+ RTLIL::SigBit hole_sigbit = it->second;
+ log_assert(hole_sigbit.wire != nullptr);
+ log_assert(hole_value[bit_idx] == '0' || hole_value[bit_idx] == '1');
+ RTLIL::SigSpec lhs(hole_sigbit.wire, hole_sigbit.offset, 1);
+ RTLIL::State hole_bit_val = hole_value[bit_idx] == '1'? RTLIL::State::S1 : RTLIL::State::S0;
+ if (!quiet)
+ log("Specializing %s with %s = %d.\n", module->name.c_str(), log_signal(hole_sigbit), hole_bit_val == RTLIL::State::S0? 0 : 1)
+;
+ module->connect(lhs, hole_bit_val);
+ }
}
-
}
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);
@@ -239,7 +172,7 @@ void allconstify_inputs(RTLIL::Module *module, const pool<std::string> &input_wi
module->fixup_ports();
}
-void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
+void assume_miter_outputs(RTLIL::Module *module, bool assume_neg) {
std::vector<RTLIL::Wire *> wires_to_assume;
for (auto w : module->wires())
if (w->port_output && w->width == 1)
@@ -254,7 +187,7 @@ void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
log("\n");
}
- if (opt.assume_neg) {
+ if (assume_neg) {
for (unsigned int i = 0; i < wires_to_assume.size(); ++i) {
RTLIL::SigSpec n_wire = module->LogicNot(wires_to_assume[i]->name.str() + "__n__qbfsat", wires_to_assume[i], false, wires_to_assume[i]->get_src_attribute());
wires_to_assume[i] = n_wire.as_wire();
@@ -274,90 +207,173 @@ void assume_miter_outputs(RTLIL::Module *module, const QbfSolveOptions &opt) {
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 call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt, const std::string &tempdir_name, const bool quiet = false, const int iter_num = 0) {
+ //Execute and capture stdout from `yosys-smtbmc -s z3 -t 1 -g --binary [--dump-smt2 <file>]`
QbfSolutionType ret;
const std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc";
+ const std::string smt2_command = stringf("write_smt2 -stbv -wires %s/problem%d.smt2", tempdir_name.c_str(), iter_num);
const std::string smtbmc_warning = "z3: WARNING:";
- const bool show_smtbmc = opt.show_smtbmc;
+ const std::string smtbmc_cmd = stringf("%s -s %s %s -t 1 -g --binary %s %s/problem%d.smt2 2>&1",
+ yosys_smtbmc_exe.c_str(), opt.get_solver_name().c_str(),
+ (opt.timeout != 0? stringf("--timeout %d", opt.timeout) : "").c_str(),
+ (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file : "").c_str(),
+ tempdir_name.c_str(), iter_num);
- 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);
+
+ auto process_line = [&ret, &smtbmc_warning, &opt, &quiet](const std::string &line) {
+ ret.stdout_lines.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 (opt.show_smtbmc && !quiet)
+ log("smtbmc output: %s", line.c_str());
+ };
log_header(mod->design, "Solving QBF-SAT problem.\n");
+ if (!quiet) log("Launching \"%s\".\n", smtbmc_cmd.c_str());
+ int64_t begin = PerformanceTimer::query();
+ run_command(smtbmc_cmd, process_line);
+ int64_t end = PerformanceTimer::query();
+ ret.solver_time = (end - begin) / 1e9f;
+ if (!quiet) log("Solver finished in %.3f seconds.\n", ret.solver_time);
+
+ ret.recover_solution();
+ return ret;
+}
- //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_lines.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;
+QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) {
+ QbfSolutionType ret, best_soln;
+ const std::string tempdir_name = make_temp_dir("/tmp/yosys-qbfsat-XXXXXX");
+ RTLIL::Module *module = mod;
+ RTLIL::Design *design = module->design;
+ std::string module_name = module->name.str();
+ RTLIL::IdString wire_to_optimize_name = "";
+ bool maximize = false;
+ log_assert(module->design != nullptr);
+
+ 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.assume_outputs);
+ allconstify_inputs(module, input_wires);
+ if (opt.assume_outputs)
+ assume_miter_outputs(module, opt.assume_neg);
+
+ //Find the wire to be optimized, if any:
+ for (auto wire : module->wires()) {
+ if (wire->get_bool_attribute("\\maximize") || wire->get_bool_attribute("\\minimize")) {
+ wire_to_optimize_name = wire->name;
+ maximize = wire->get_bool_attribute("\\maximize");
+ if (opt.nooptimize) {
+ if (maximize)
+ wire->set_bool_attribute("\\maximize", false);
+ else
+ wire->set_bool_attribute("\\minimize", false);
+ }
}
}
- if(!opt.nocleanup)
- remove_directory(tempdir_name);
+ //If -O1 or -O2 was specified, use ABC to simplify the problem:
+ if (opt.oflag == opt.OptimizationLevel::O1)
+ Pass::call(module->design, "abc -g AND,NAND,OR,NOR,XOR,XNOR,MUX,NMUX -script +print_stats;strash;print_stats;drwsat;print_stats;fraig;print_stats;refactor,-N,10,-lz;print_stats;&get,-n;&dch,-pem;&nf;&put " + mod->name.str());
+ else if (opt.oflag == opt.OptimizationLevel::O2)
+ Pass::call(module->design, "abc -g AND,NAND,OR,NOR,XOR,XNOR,MUX,NMUX -script +print_stats;strash;print_stats;drwsat;print_stats;dch,-S,1000000,-C,100000,-p;print_stats;fraig;print_stats;refactor,-N,15,-lz;print_stats;dc2,-pbl;print_stats;drwsat;print_stats;&get,-n;&dch,-pem;&nf;&put " + mod->name.str());
+ if (opt.oflag != opt.OptimizationLevel::O0) {
+ Pass::call(module->design, "techmap");
+ Pass::call(module->design, "opt");
+ }
- recover_solution(ret);
+ if (opt.nobisection || opt.nooptimize || wire_to_optimize_name == "") {
+ ret = call_qbf_solver(module, opt, tempdir_name, false, 0);
+ } else {
+ //Do the iterated bisection method:
+ unsigned int iter_num = 1;
+ unsigned int success = 0;
+ unsigned int failure = 0;
+ unsigned int cur_thresh = 0;
+
+ log_assert(wire_to_optimize_name != "");
+ log_assert(module->wire(wire_to_optimize_name) != nullptr);
+ log("%s wire \"%s\".\n", (maximize? "Maximizing" : "Minimizing"), wire_to_optimize_name.c_str());
+
+ //If maximizing, grow until we get a failure. Then bisect success and failure.
+ while (failure == 0 || difference(success, failure) > 1) {
+ Pass::call(design, "design -push-copy");
+ log_header(design, "Preparing QBF-SAT problem.\n");
- return ret;
-}
+ if (cur_thresh != 0) {
+ //Add thresholding logic (but not on the initial run when we don't have a sense of where to start):
+ RTLIL::SigSpec comparator = maximize? module->Ge(NEW_ID, module->wire(wire_to_optimize_name), RTLIL::Const(cur_thresh), false)
+ : module->Le(NEW_ID, module->wire(wire_to_optimize_name), RTLIL::Const(cur_thresh), false);
-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());
+ module->addAssume(wire_to_optimize_name.str() + "__threshold", comparator, RTLIL::Const(1, 1));
+ log("Trying to solve with %s %s %d.\n", wire_to_optimize_name.c_str(), (maximize? ">=" : "<="), cur_thresh);
+ }
+
+ ret = call_qbf_solver(module, opt, tempdir_name, false, iter_num);
+ Pass::call(design, "design -pop");
+ module = design->module(module_name);
+
+ if (!ret.unknown && ret.sat) {
+ Pass::call(design, "design -push-copy");
+ specialize(module, ret, true);
+
+ RTLIL::SigSpec wire, value, undef;
+ RTLIL::SigSpec::parse_sel(wire, design, module, wire_to_optimize_name.str());
+
+ ConstEval ce(module);
+ value = wire;
+ if (!ce.eval(value, undef))
+ log_cmd_error("Failed to evaluate signal %s: Missing value for %s.\n", log_signal(wire), log_signal(undef));
+ log_assert(value.is_fully_const());
+ success = value.as_const().as_int();
+ best_soln = ret;
+ log("Problem is satisfiable with %s = %d.\n", wire_to_optimize_name.c_str(), success);
+ Pass::call(design, "design -pop");
+ module = design->module(module_name);
+
+ //sometimes this happens if we get an 'unknown' or timeout
+ if (!maximize && success < failure)
+ break;
+ else if (maximize && failure != 0 && success > failure)
+ break;
+
+ } else {
+ //Treat 'unknown' as UNSAT
+ failure = cur_thresh;
+ if (failure == 0) {
+ log("Problem is NOT satisfiable.\n");
+ break;
+ }
+ else
+ log("Problem is NOT satisfiable with %s %s %d.\n", wire_to_optimize_name.c_str(), (maximize? ">=" : "<="), failure);
+ }
+
+ iter_num++;
+ if (maximize && failure == 0 && success == 0)
+ cur_thresh = 2;
+ else if (maximize && failure == 0)
+ cur_thresh = 2 * success; //growth
+ else //if (!maximize || failure != 0)
+ cur_thresh = (success + failure) / 2; //bisection
+ }
+ if (success != 0 || failure != 0) {
+ log("Wire %s is %s at %d.\n", wire_to_optimize_name.c_str(), (maximize? "maximized" : "minimized"), success);
+ ret = best_soln;
}
- 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;
+ if(!opt.nocleanup)
+ remove_directory(tempdir_name);
+
+ Pass::call(design, "design -pop");
+
+ return ret;
}
QbfSolveOptions parse_args(const std::vector<std::string> &args) {
@@ -379,6 +395,59 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) {
opt.assume_neg = true;
continue;
}
+ else if (args[opt.argidx] == "-nooptimize") {
+ opt.nooptimize = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-nobisection") {
+ opt.nobisection = true;
+ continue;
+ }
+ else if (args[opt.argidx] == "-solver") {
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("solver not specified.\n");
+ else {
+ if (args[opt.argidx+1] == "z3")
+ opt.solver = opt.Solver::Z3;
+ else if (args[opt.argidx+1] == "yices")
+ opt.solver = opt.Solver::Yices;
+ else if (args[opt.argidx+1] == "cvc4")
+ opt.solver = opt.Solver::CVC4;
+ else
+ log_cmd_error("Unknown solver \"%s\".\n", args[opt.argidx+1].c_str());
+ opt.argidx++;
+ }
+ continue;
+ }
+ else if (args[opt.argidx] == "-timeout") {
+ if (args.size() <= opt.argidx + 1)
+ log_cmd_error("timeout not specified.\n");
+ else {
+ int timeout = atoi(args[opt.argidx+1].c_str());
+ if (timeout > 0)
+ opt.timeout = timeout;
+ else
+ log_cmd_error("timeout must be greater than 0.\n");
+ opt.argidx++;
+ }
+ continue;
+ }
+ else if (args[opt.argidx].substr(0, 2) == "-O" && args[opt.argidx].size() == 3) {
+ switch (args[opt.argidx][2]) {
+ case '0':
+ opt.oflag = opt.OptimizationLevel::O0;
+ break;
+ case '1':
+ opt.oflag = opt.OptimizationLevel::O1;
+ break;
+ case '2':
+ opt.oflag = opt.OptimizationLevel::O2;
+ break;
+ default:
+ log_cmd_error("unknown argument %s\n", args[opt.argidx].c_str());
+ }
+ continue;
+ }
else if (args[opt.argidx] == "-sat") {
opt.sat = true;
continue;
@@ -421,62 +490,56 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) {
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
+ void help() 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("This command solves an \"exists-forall\" 2QBF-SAT problem defined over the currently\n");
+ log("selected module. Existentially-quantified variables are declared by assigning a wire\n");
+ log("\"$anyconst\". Universally-quantified variables may be explicitly declared by assigning\n");
+ log("a wire \"$allconst\", but module inputs will be treated as universally-quantified\n");
+ log("variables by default.\n");
log("\n");
log(" -nocleanup\n");
- log(" Do not delete temporary files and directories. Useful for\n");
- log(" debugging.\n");
+ log(" Do not delete temporary files and directories. Useful for 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(" Add an \"$assume\" cell for the conjunction of all one-bit module output wires.\n");
log("\n");
log(" -assume-negative-polarity\n");
log(" When adding $assume cells for one-bit module output wires, assume they are\n");
log(" negative polarity signals and should always be low, for example like the\n");
log(" miters created with the `miter` command.\n");
log("\n");
+ log(" -nooptimize\n");
+ log(" Ignore \"\\minimize\" and \"\\maximize\" attributes, do not emit \"(maximize)\" or\n");
+ log(" \"(minimize)\" in the SMT-LIBv2, and generally make no attempt to optimize anything.\n");
+ log("\n");
+ log(" -nobisection\n");
+ log(" If a wire is marked with the \"\\minimize\" or \"\\maximize\" attribute, do not\n");
+ log(" attempt to optimize that value with the default iterated solving and threshold\n");
+ log(" bisection approach. Instead, have yosys-smtbmc emit a \"(minimize)\" or \"(maximize)\"\n");
+ log(" command in the SMT-LIBv2 output and hope that the solver supports optimizing\n");
+ log(" quantified bitvector problems.\n");
+ log("\n");
+ log(" -solver <solver>\n");
+ log(" Use a particular solver. Choose one of: \"z3\", \"yices\", and \"cvc4\".\n");
+ log(" (default: yices)\n");
+ log("\n");
+ log(" -timeout <value>\n");
+ log(" Set the per-iteration timeout in seconds.\n");
+ log(" (default: no timeout)\n");
+ log("\n");
+ log(" -O0, -O1, -O2\n");
+ log(" Control the use of ABC to simplify the QBF-SAT problem before solving.\n");
+ log("\n");
log(" -sat\n");
log(" Generate an error if the solver does not return \"sat\".\n");
log("\n");
@@ -487,20 +550,21 @@ struct QbfSatPass : public Pass {
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(" If the problem is satisfiable, replace each \"$anyconst\" cell with its\n");
+ log(" corresponding constant value from the model produced 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(" Do not run the solver, but instead only attempt to replace each \"$anyconst\"\n");
+ log(" cell in the current module with a constant value 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(" If the problem is satisfiable, write the corresponding constant value for each\n");
+ log(" \"$anyconst\" cell from the model produced by the solver to the specified file.");
log("\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) override
{
log_header(design, "Executing QBFSAT pass (solving QBF-SAT problems in the circuit).\n");
QbfSolveOptions opt = parse_args(args);
@@ -519,41 +583,31 @@ struct QbfSatPass : public Pass {
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, opt);
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)
+ if (ret.unknown) {
+ if (opt.sat || opt.unsat)
+ log_cmd_error("expected problem to be %s\n", opt.sat? "SAT" : "UNSAT");
+ }
+ 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);
+ ret.write_solution(module, opt.write_soln_soln_file);
}
if (opt.specialize) {
specialize(module, ret);
} else {
- dump_model(module, ret);
+ ret.dump_model(module);
}
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 {
+ print_proof_failed();
+ if (opt.sat)
+ log_cmd_error("expected problem to be SAT\n");
+ }
} else
specialize_from_file(module, opt.specialize_soln_file);
log_pop();
diff --git a/passes/sat/qbfsat.h b/passes/sat/qbfsat.h
new file mode 100644
index 000000000..401f9c7a6
--- /dev/null
+++ b/passes/sat/qbfsat.h
@@ -0,0 +1,252 @@
+/* -*- c++ -*-
+ * 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.
+ *
+ */
+
+#ifndef QBFSAT_H
+#define QBFSAT_H
+
+#include "kernel/yosys.h"
+#include <numeric>
+
+YOSYS_NAMESPACE_BEGIN
+
+struct QbfSolveOptions {
+ bool specialize = false, specialize_from_file = false, write_solution = false, nocleanup = false;
+ bool dump_final_smt2 = false, assume_outputs = false, assume_neg = false, nooptimize = false;
+ bool nobisection = false, sat = false, unsat = false, show_smtbmc = false;
+ enum Solver{Z3, Yices, CVC4} solver = Yices;
+ enum OptimizationLevel{O0, O1, O2} oflag = O0;
+ int timeout = 0;
+ std::string specialize_soln_file = "";
+ std::string write_soln_soln_file = "";
+ std::string dump_final_smt2_file = "";
+ size_t argidx = 0;
+
+ std::string get_solver_name() const {
+ if (solver == Solver::Z3)
+ return "z3";
+ else if (solver == Solver::Yices)
+ return "yices";
+ else if (solver == Solver::CVC4)
+ return "cvc4";
+
+ log_cmd_error("unknown solver specified.\n");
+ return "";
+ }
+};
+
+struct QbfSolutionType {
+ std::vector<std::string> stdout_lines = {};
+ dict<pool<std::string>, std::string> hole_to_value = {};
+ double solver_time = 0;
+ bool sat = false;
+ bool unknown = true; //true if neither 'sat' nor 'unsat'
+
+ dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> get_hole_loc_idx_sigbit_map(RTLIL::Module *module) const {
+ dict<std::pair<pool<std::string>, int>, RTLIL::SigBit> hole_loc_idx_to_sigbit;
+ pool<RTLIL::SigBit> anyconst_sigbits;
+ dict<RTLIL::SigBit, RTLIL::SigBit> anyconst_sigbit_to_wire_sigbit;
+
+ for (auto cell : module->cells()) {
+ pool<std::string> cell_src = cell->get_strpool_attribute(ID::src);
+ auto pos = hole_to_value.find(cell_src);
+ if (pos != hole_to_value.end() && cell->type.in("$anyconst", "$anyseq")) {
+ RTLIL::SigSpec port_y = cell->getPort(ID::Y);
+ for (int i = GetSize(port_y) - 1; i >= 0; --i) {
+ hole_loc_idx_to_sigbit[std::make_pair(pos->first, i)] = port_y[i];
+ anyconst_sigbits.insert(port_y[i]);
+ }
+ }
+ }
+
+ for (auto &conn : module->connections()) {
+ auto lhs = conn.first;
+ auto rhs = conn.second;
+ for (auto i = 0; i < GetSize(rhs); ++i) {
+ if (anyconst_sigbits[rhs[i]]) {
+ auto pos = anyconst_sigbit_to_wire_sigbit.find(rhs[i]);
+ if (pos != anyconst_sigbit_to_wire_sigbit.end())
+ log_cmd_error("conflicting names for hole $anyconst sigbit %s\n", log_signal(rhs[i]));
+ anyconst_sigbit_to_wire_sigbit[rhs[i]] = lhs[i];
+ }
+ }
+ }
+
+ for (auto &it : hole_loc_idx_to_sigbit) {
+ auto pos = anyconst_sigbit_to_wire_sigbit.find(it.second);
+ if (pos != anyconst_sigbit_to_wire_sigbit.end())
+ it.second = pos->second;
+ }
+
+ return hole_loc_idx_to_sigbit;
+ }
+
+ void dump_model(RTLIL::Module *module) const {
+ log("Satisfiable model:\n");
+ auto hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module);
+ for (auto &it : hole_to_value) {
+ pool<std::string> hole_loc = it.first;
+ std::string hole_value = it.second;
+
+ for (unsigned int i = 0; i < hole_value.size(); ++i) {
+ int bit_idx = GetSize(hole_value) - 1 - i;
+ auto it = hole_loc_idx_to_sigbit.find(std::make_pair(hole_loc, i));
+ log_assert(it != hole_loc_idx_to_sigbit.end());
+
+ RTLIL::SigBit hole_sigbit = it->second;
+ log("\t%s = 1'b%c\n", log_signal(hole_sigbit), hole_value[bit_idx]);
+ }
+ }
+ }
+
+ void write_solution(RTLIL::Module *module, const std::string &file) const {
+ std::ofstream fout(file.c_str());
+ if (!fout)
+ log_cmd_error("could not open solution file for writing.\n");
+
+ //There is a question here: How exactly shall we identify holes?
+ //There are at least two reasonable options:
+ //1. By the source location of the $anyconst cells
+ //2. By the name(s) of the wire(s) connected to each SigBit of the $anyconst cell->getPort(ID::Y) SigSpec.
+ //
+ //Option 1 has the benefit of being very precise. There is very limited potential for confusion, as long
+ //as the source attribute has been set. However, if the source attribute is not set, this won't work.
+ //More importantly, we want to have the ability to port hole assignments to other modules with compatible
+ //hole names and widths. Obviously in those cases source locations of the $anyconst cells will not match.
+ //
+ //Option 2 has the benefits previously described, but wire names can be changed automatically by
+ //optimization or techmapping passes, especially when (ex/im)porting from BLIF for optimization with ABC.
+ //
+ //The approach taken here is to allow both options. We write the assignment information for each bit of
+ //the solution on a separate line. Each line is of one of two forms:
+ //
+ //location bit name = value
+ //location bit name [offset] = value
+ //
+ //where '[', ']', and '=' are literal symbols, "location" is the $anyconst cell source location attribute,
+ //"bit" is the index of the $anyconst cell, "name" is the `wire->name` field of the SigBit corresponding
+ //to the current bit of the $anyconst cell->getPort(ID::Y), "offset" is the `offset` field of that same
+ //SigBit, and "value", which is either '0' or '1', represents the assignment for that bit.
+ auto hole_loc_idx_to_sigbit = get_hole_loc_idx_sigbit_map(module);
+ for (auto &x : hole_to_value) {
+ std::string src_as_str = std::accumulate(x.first.begin(), x.first.end(), std::string(), [](const std::string &a, const std::string &b){return a + "|" + b;});
+ for (auto i = 0; i < GetSize(x.second); ++i)
+ fout << src_as_str.c_str() << " " << i << " " << log_signal(hole_loc_idx_to_sigbit[std::make_pair(x.first, i)]) << " = " << x.second[GetSize(x.second) - 1 - i] << std::endl;
+ }
+ }
+
+ void recover_solution() {
+ 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 unsat_regex2 = YS_REGEX_COMPILE("Status: FAILED");
+ YS_REGEX_TYPE timeout_regex = YS_REGEX_COMPILE("No solution found! \\(timeout\\)");
+ YS_REGEX_TYPE timeout_regex2 = YS_REGEX_COMPILE("No solution found! \\(interrupted\\)");
+ YS_REGEX_TYPE unknown_regex = YS_REGEX_COMPILE("No solution found! \\(unknown\\)");
+ YS_REGEX_TYPE unknown_regex2 = YS_REGEX_COMPILE("Unexpected EOF response from solver");
+ YS_REGEX_TYPE memout_regex = YS_REGEX_COMPILE("Solver Error:.*error \"out of memory\"");
+ 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 : stdout_lines) {
+ 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
+ auto locs = split_tokens(loc, "|");
+ pool<std::string> loc_pool(locs.begin(), locs.end());
+ hole_to_value[loc_pool] = val;
+ }
+ else if (YS_REGEX_NS::regex_search(x, sat_regex)) {
+ sat_regex_found = true;
+ sat = true;
+ unknown = false;
+ }
+ else if (YS_REGEX_NS::regex_search(x, unsat_regex)) {
+ unsat_regex_found = true;
+ sat = false;
+ unknown = false;
+ }
+ else if (YS_REGEX_NS::regex_search(x, memout_regex)) {
+ unknown = true;
+ log_warning("solver ran out of memory\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, timeout_regex)) {
+ unknown = true;
+ log_warning("solver timed out\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, timeout_regex2)) {
+ unknown = true;
+ log_warning("solver timed out\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, unknown_regex)) {
+ unknown = true;
+ log_warning("solver returned \"unknown\"\n");
+ }
+ else if (YS_REGEX_NS::regex_search(x, unsat_regex2)) {
+ unsat_regex_found = true;
+ sat = false;
+ unknown = false;
+ }
+ else if (YS_REGEX_NS::regex_search(x, unknown_regex2)) {
+ unknown = true;
+ }
+ }
+ log_assert(!unknown && sat? sat_regex_found : true);
+ log_assert(!unknown && !sat? unsat_regex_found : true);
+ }
+};
+
+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");
+}
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc
index 6acdbc800..d7bf125d1 100644
--- a/passes/sat/sat.cc
+++ b/passes/sat/sat.cc
@@ -256,13 +256,13 @@ struct SatHelper
{
RTLIL::SigSpec big_lhs, big_rhs;
- for (auto &it : module->wires_)
+ for (auto wire : module->wires())
{
- if (it.second->attributes.count(ID::init) == 0)
+ if (wire->attributes.count(ID::init) == 0)
continue;
- RTLIL::SigSpec lhs = sigmap(it.second);
- RTLIL::SigSpec rhs = it.second->attributes.at(ID::init);
+ RTLIL::SigSpec lhs = sigmap(wire);
+ RTLIL::SigSpec rhs = wire->attributes.at(ID::init);
log_assert(lhs.size() == rhs.size());
RTLIL::SigSpec removed_bits;
@@ -893,7 +893,7 @@ void print_qed()
struct SatPass : public Pass {
SatPass() : Pass("sat", "solve a SAT problem in the circuit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1060,7 +1060,7 @@ struct SatPass : public Pass {
log(" Like -falsify but do not return an error for timeouts.\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) override
{
std::vector<std::pair<std::string, std::string>> sets, sets_init, prove, prove_x;
std::map<int, std::vector<std::pair<std::string, std::string>>> sets_at;
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index 03ca42cf3..fb496ff87 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -163,7 +163,10 @@ struct SimInstance
mem_database[cell] = mem;
}
-
+ if (cell->type.in(ID($memwr),ID($memrd)))
+ {
+ log_error("$memrd and $memwr cells have to be merged to stand-alone $mem cells (execute memory_collect pass)\n");
+ }
if (cell->type.in(ID($assert), ID($cover), ID($assume))) {
formal_database.insert(cell);
}
@@ -751,7 +754,7 @@ struct SimWorker : SimShared
struct SimPass : public Pass {
SimPass() : Pass("sim", "simulate the circuit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -793,7 +796,7 @@ struct SimPass : public Pass {
log(" enable debug output\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) override
{
SimWorker worker;
int numcycles = 20;
diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc
index ba44f02d8..aacc044fb 100644
--- a/passes/sat/supercover.cc
+++ b/passes/sat/supercover.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SupercoverPass : public Pass {
SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -35,7 +35,7 @@ struct SupercoverPass : public Pass {
log("checking for a hi signal level and one checking for lo level.\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) override
{
// bool flag_noinit = false;
diff --git a/passes/techmap/.gitignore b/passes/techmap/.gitignore
deleted file mode 100644
index e6dcc6bc0..000000000
--- a/passes/techmap/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-techmap.inc
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 1802ba0de..e3b3d8dea 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -1,4 +1,5 @@
+OBJS += passes/techmap/flatten.o
OBJS += passes/techmap/techmap.o
OBJS += passes/techmap/simplemap.o
OBJS += passes/techmap/dfflibmap.o
@@ -40,23 +41,12 @@ OBJS += passes/techmap/insbuf.o
OBJS += passes/techmap/attrmvcp.o
OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
+OBJS += passes/techmap/dfflegalize.o
OBJS += passes/techmap/dff2dffs.o
OBJS += passes/techmap/flowmap.o
OBJS += passes/techmap/extractinv.o
endif
-GENFILES += passes/techmap/techmap.inc
-
-passes/techmap/techmap.inc: techlibs/common/techmap.v
- $(Q) mkdir -p $(dir $@)
- $(P) echo "// autogenerated from $<" > $@.new
- $(Q) echo "static char stdcells_code[] = {" >> $@.new
- $(Q) od -v -td1 -An $< | $(SED) -e 's/[0-9][0-9]*/&,/g' >> $@.new
- $(Q) echo "0};" >> $@.new
- $(Q) mv $@.new $@
-
-passes/techmap/techmap.o: passes/techmap/techmap.inc
-
ifeq ($(DISABLE_SPAWN),0)
TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE)
EXTRA_OBJS += passes/techmap/filterlib.o
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index fae8b2426..0a58fdcc0 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -1276,7 +1276,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
struct AbcPass : public Pass {
AbcPass() : Pass("abc", "use ABC for technology mapping") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1460,7 +1460,7 @@ struct AbcPass : public Pass {
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\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) override
{
log_header(design, "Executing ABC pass (technology mapping using ABC).\n");
log_push();
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 1b3d5ff06..127f8934e 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -36,7 +36,7 @@ PRIVATE_NAMESPACE_BEGIN
struct Abc9Pass : public ScriptPass
{
Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
- void on_register() YS_OVERRIDE
+ void on_register() override
{
RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs";
RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -a -v; &mfs";
@@ -81,7 +81,7 @@ struct Abc9Pass : public ScriptPass
"&st; &if {C} -g -K 6; &synch2; &if {C} {W} {D} {R} -v; &save; &load;"\
"&mfs";
}
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -151,8 +151,8 @@ struct Abc9Pass : public ScriptPass
log(" specified).\n");
log("\n");
log(" -dff\n");
- log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
- log(" domains are marked as such and automatically partitioned by ABC.\n");
+ log(" also pass $_DFF_[NP]_ cells through to ABC. modules with many clock\n");
+ log(" domains are supported and automatically partitioned by ABC.\n");
log("\n");
log(" -nocleanup\n");
log(" when this option is used, the temporary files created by this pass\n");
@@ -184,7 +184,7 @@ struct Abc9Pass : public ScriptPass
int maxlut;
std::string box_file;
- void clear_flags() YS_OVERRIDE
+ void clear_flags() override
{
exe_cmd.str("");
exe_cmd << "abc9_exe";
@@ -195,7 +195,7 @@ struct Abc9Pass : public ScriptPass
box_file = "";
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
std::string run_from, run_to;
clear_flags();
@@ -272,42 +272,108 @@ struct Abc9Pass : public ScriptPass
log_pop();
}
- void script() YS_OVERRIDE
+ void script() override
{
+ if (check_label("check")) {
+ if (help_mode)
+ run("abc9_ops -check [-dff]", "(option if -dff)");
+ else
+ run(stringf("abc9_ops -check %s", dff_mode ? "-dff" : ""));
+ }
+
+ if (check_label("map")) {
+ if (help_mode)
+ run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)");
+ else
+ run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : ""));
+ if (dff_mode) {
+ run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)");
+ run("select -unset $abc9_flops", " (only if -dff)");
+ }
+ run("design -stash $abc9");
+ run("design -load $abc9_map");
+ run("proc");
+ run("wbflip");
+ run("techmap");
+ run("opt");
+ if (dff_mode || help_mode) {
+ if (!help_mode)
+ active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something");
+ run("abc9_ops -prep_dff_submod", " (only if -dff)"); // rewrite specify
+ bool did_something = help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_dff_submod.did_something");
+ if (did_something) {
+ // select all $_DFF_[NP]_
+ // then select all its fanins
+ // then select all fanouts of all that
+ // lastly remove $_DFF_[NP]_ cells
+ run("setattr -set submod \"$abc9_flop\" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d", " (only if -dff)");
+ run("submod", " (only if -dff)");
+ run("setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop", "(only if -dff)");
+ if (help_mode) {
+ run("foreach module in design");
+ run(" rename <module-name>_$abc9_flop _TECHMAP_REPLACE_", " (only if -dff)");
+ }
+ else {
+ // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs
+ for (auto module : active_design->selected_modules()) {
+ active_design->selected_active_module = module->name.str();
+ if (module->cell(stringf("%s_$abc9_flop", module->name.c_str())))
+ run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name.c_str()));
+ }
+ active_design->selected_active_module.clear();
+ }
+ run("abc9_ops -prep_dff_unmap", " (only if -dff)");
+ run("design -copy-to $abc9 =*_$abc9_flop", " (only if -dff)"); // copy submod out
+ run("delete =*_$abc9_flop", " (only if -dff)");
+ }
+ }
+ run("design -stash $abc9_map");
+ run("design -load $abc9");
+ run("design -delete $abc9");
+ if (help_mode)
+ run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)");
+ else
+ run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : ""));
+ run("design -delete $abc9_map");
+ }
+
if (check_label("pre")) {
- run("abc9_ops -check");
+ run("read_verilog -icells -lib -specify +/abc9_model.v");
run("scc -set_attr abc9_scc_id {}");
if (help_mode)
run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
else
- run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)");
+ run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""));
if (help_mode)
run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)");
else if (!lut_mode)
run(stringf("abc9_ops -prep_lut %d", maxlut));
if (help_mode)
- run("abc9_ops -prep_box [-dff]", "(skip if -box)");
+ run("abc9_ops -prep_box", "(skip if -box)");
else if (box_file.empty())
- run(stringf("abc9_ops -prep_box %s", dff_mode ? "-dff" : ""));
- run("select -set abc9_holes A:abc9_holes");
- run("flatten -wb @abc9_holes");
- run("techmap @abc9_holes");
- if (dff_mode || help_mode)
- run("abc9_ops -prep_dff", "(only if -dff)");
- run("opt -purge @abc9_holes");
- run("aigmap");
- run("wbflip @abc9_holes");
+ run("abc9_ops -prep_box");
+ if (saved_designs.count("$abc9_holes") || help_mode) {
+ run("design -stash $abc9");
+ run("design -load $abc9_holes");
+ run("techmap -wb -map %$abc9 -map +/techmap.v");
+ run("opt -purge");
+ run("aigmap");
+ run("design -stash $abc9_holes");
+ run("design -load $abc9");
+ run("design -delete $abc9");
+ }
}
- if (check_label("map")) {
+ if (check_label("exe")) {
+ run("aigmap");
if (help_mode) {
run("foreach module in selection");
run(" abc9_ops -write_lut <abc-temp-dir>/input.lut", "(skip if '-lut' or '-luts')");
- run(" abc9_ops -write_box <abc-temp-dir>/input.box");
- run(" write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
- run(" abc9_exe [options] -cwd <abc-temp-dir> [-lut <abc-temp-dir>/input.lut] -box <abc-temp-dir>/input.box");
+ run(" abc9_ops -write_box <abc-temp-dir>/input.box", "(skip if '-box')");
+ run(" write_xaiger -map <abc-temp-dir>/input.sym [-dff] <abc-temp-dir>/input.xaig");
+ run(" abc9_exe [options] -cwd <abc-temp-dir> -lut [<abc-temp-dir>/input.lut] -box [<abc-temp-dir>/input.box]");
run(" read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig");
- run(" abc9_ops -reintegrate");
+ run(" abc9_ops -reintegrate [-dff]");
}
else {
auto selected_modules = active_design->selected_modules();
@@ -318,7 +384,6 @@ struct Abc9Pass : public ScriptPass
log("Skipping module %s as it contains processes.\n", log_id(mod));
continue;
}
- log_assert(!mod->attributes.count(ID::abc9_box_id));
log_push();
active_design->selection().select(mod);
@@ -333,8 +398,9 @@ struct Abc9Pass : public ScriptPass
if (!lut_mode)
run_nocheck(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str()));
- run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str()));
- run_nocheck(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
+ if (box_file.empty())
+ run_nocheck(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str()));
+ run_nocheck(stringf("write_xaiger -map %s/input.sym %s %s/input.xaig", tempdir_name.c_str(), dff_mode ? "-dff" : "", tempdir_name.c_str()));
int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs");
@@ -349,10 +415,13 @@ struct Abc9Pass : public ScriptPass
abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str());
if (!lut_mode)
abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str());
- abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str());
+ if (box_file.empty())
+ abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str());
+ else
+ abc9_exe_cmd += stringf(" -box %s", box_file.c_str());
run_nocheck(abc9_exe_cmd);
run_nocheck(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str()));
- run_nocheck("abc9_ops -reintegrate");
+ run_nocheck(stringf("abc9_ops -reintegrate %s", dff_mode ? "-dff" : ""));
}
else
log("Don't call ABC as there is nothing to map.\n");
@@ -369,6 +438,14 @@ struct Abc9Pass : public ScriptPass
active_design->selection_stack.pop_back();
}
}
+
+ if (check_label("unmap")) {
+ run("techmap -wb -map %$abc9_unmap -map +/abc9_unmap.v"); // techmap user design from submod back to original cell
+ // ($_DFF_[NP]_ already shorted by -reintegrate)
+ run("design -delete $abc9_unmap");
+ if (saved_designs.count("$abc9_holes") || help_mode)
+ run("design -delete $abc9_holes");
+ }
}
} Abc9Pass;
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index 0bf547921..7355840aa 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -293,7 +293,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
struct Abc9ExePass : public Pass {
Abc9ExePass() : Pass("abc9_exe", "use ABC9 for technology mapping") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -375,7 +375,7 @@ struct Abc9ExePass : public Pass {
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\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) override
{
log_header(design, "Executing ABC9_EXE pass (technology mapping using ABC9).\n");
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 1345188a4..98d0207c4 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -34,13 +34,10 @@ inline std::string remap_name(RTLIL::IdString abc9_name)
return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
}
-void check(RTLIL::Design *design)
+void check(RTLIL::Design *design, bool dff_mode)
{
dict<IdString,IdString> box_lookup;
for (auto m : design->modules()) {
- if (m->name.begins_with("$paramod"))
- continue;
-
auto flop = m->get_bool_attribute(ID::abc9_flop);
auto it = m->attributes.find(ID::abc9_box_id);
if (!flop) {
@@ -88,6 +85,463 @@ void check(RTLIL::Design *design)
log_error("Module '%s' with (* abc9_flop *) has %d outputs (expect 1).\n", log_id(m), num_outputs);
}
}
+
+ if (dff_mode) {
+ static pool<IdString> unsupported{
+ ID($adff), ID($dlatch), ID($dlatchsr), ID($sr),
+ ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
+ ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
+ ID($_DLATCH_N_), ID($_DLATCH_P_),
+ ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
+ ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
+ ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)
+ };
+ pool<IdString> processed;
+ for (auto module : design->selected_modules())
+ for (auto cell : module->cells()) {
+ auto inst_module = design->module(cell->type);
+ if (!inst_module)
+ continue;
+ IdString derived_type;
+ Module *derived_module;
+ if (cell->parameters.empty()) {
+ derived_type = cell->type;
+ derived_module = inst_module;
+ }
+ else {
+ // Check potential (since its value may depend on a parameter,
+ // but not its existence)
+ if (!inst_module->has_attribute(ID::abc9_flop))
+ continue;
+ derived_type = inst_module->derive(design, cell->parameters);
+ derived_module = design->module(derived_type);
+ log_assert(derived_module);
+ }
+ if (!derived_module->get_bool_attribute(ID::abc9_flop))
+ continue;
+ if (derived_module->get_blackbox_attribute(true /* ignore_wb */))
+ log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type));
+
+ if (derived_module->has_processes())
+ Pass::call_on_module(design, derived_module, "proc");
+
+ bool found = false;
+ for (auto derived_cell : derived_module->cells()) {
+ if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) {
+ if (found)
+ log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module));
+ found = true;
+
+ SigBit Q = derived_cell->getPort(ID::Q);
+ log_assert(GetSize(Q.wire) == 1);
+
+ if (!Q.wire->port_output)
+ log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", log_id(derived_module), log_id(derived_cell->type));
+
+ Const init = Q.wire->attributes.at(ID::init, State::Sx);
+ log_assert(GetSize(init) == 1);
+ }
+ else if (unsupported.count(derived_cell->type))
+ log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type));
+ }
+ }
+ }
+}
+
+void prep_hier(RTLIL::Design *design, bool dff_mode)
+{
+ auto r = saved_designs.emplace("$abc9_unmap", nullptr);
+ if (r.second)
+ r.first->second = new Design;
+ Design *unmap_design = r.first->second;
+
+ static const pool<IdString> seq_types{
+ ID($dff), ID($dffsr), ID($adff),
+ ID($dlatch), ID($dlatchsr), ID($sr),
+ ID($mem),
+ ID($_DFF_N_), ID($_DFF_P_),
+ 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($_DLATCH_N_), ID($_DLATCH_P_),
+ ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
+ ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
+ ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)
+ };
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->cells()) {
+ auto inst_module = design->module(cell->type);
+ if (!inst_module)
+ continue;
+ IdString derived_type;
+ Module *derived_module;
+ if (cell->parameters.empty()) {
+ derived_type = cell->type;
+ derived_module = inst_module;
+ }
+ else {
+ // Check potential for any one of those three
+ // (since its value may depend on a parameter, but not its existence)
+ if (!inst_module->has_attribute(ID::abc9_flop) && !inst_module->has_attribute(ID::abc9_box) && !inst_module->get_bool_attribute(ID::abc9_bypass))
+ continue;
+ derived_type = inst_module->derive(design, cell->parameters);
+ derived_module = design->module(derived_type);
+ }
+ if (derived_module->get_blackbox_attribute(true /* ignore_wb */))
+ continue;
+
+ if (derived_module->get_bool_attribute(ID::abc9_flop)) {
+ if (!dff_mode)
+ continue;
+ }
+ else {
+ if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass))
+ continue;
+ }
+
+ if (!unmap_design->module(derived_type)) {
+ if (derived_module->has_processes())
+ Pass::call_on_module(design, derived_module, "proc");
+
+ if (derived_module->get_bool_attribute(ID::abc9_flop)) {
+ for (auto derived_cell : derived_module->cells())
+ if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) {
+ SigBit Q = derived_cell->getPort(ID::Q);
+ Const init = Q.wire->attributes.at(ID::init, State::Sx);
+ log_assert(GetSize(init) == 1);
+
+ // Block sequential synthesis on cells with (* init *) != 1'b0
+ // because ABC9 doesn't support them
+ if (init != State::S0) {
+ log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type));
+ derived_module->set_bool_attribute(ID::abc9_flop, false);
+ }
+ break;
+ }
+ }
+ else if (derived_module->get_bool_attribute(ID::abc9_box)) {
+ for (auto derived_cell : derived_module->cells())
+ if (seq_types.count(derived_cell->type)) {
+ derived_module->set_bool_attribute(ID::abc9_box, false);
+ derived_module->set_bool_attribute(ID::abc9_bypass);
+ break;
+ }
+ }
+
+ if (derived_type != cell->type) {
+ auto unmap_module = unmap_design->addModule(derived_type);
+ for (auto port : derived_module->ports) {
+ auto w = unmap_module->addWire(port, derived_module->wire(port));
+ // Do not propagate (* init *) values into the box,
+ // in fact, remove it from outside too
+ if (w->port_output)
+ w->attributes.erase(ID::init);
+ }
+ unmap_module->ports = derived_module->ports;
+ unmap_module->check();
+
+ auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type);
+ for (const auto &conn : cell->connections()) {
+ auto w = unmap_module->wire(conn.first);
+ log_assert(w);
+ replace_cell->setPort(conn.first, w);
+ }
+ replace_cell->parameters = cell->parameters;
+ }
+ }
+
+ cell->type = derived_type;
+ cell->parameters.clear();
+ }
+}
+
+void prep_bypass(RTLIL::Design *design)
+{
+ auto r = saved_designs.emplace("$abc9_map", nullptr);
+ if (r.second)
+ r.first->second = new Design;
+ Design *map_design = r.first->second;
+
+ r = saved_designs.emplace("$abc9_unmap", nullptr);
+ if (r.second)
+ r.first->second = new Design;
+ Design *unmap_design = r.first->second;
+
+ pool<IdString> processed;
+ for (auto module : design->selected_modules())
+ for (auto cell : module->cells()) {
+ if (!processed.insert(cell->type).second)
+ continue;
+ auto inst_module = design->module(cell->type);
+ if (!inst_module)
+ continue;
+ if (!inst_module->get_bool_attribute(ID::abc9_bypass))
+ continue;
+ log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */));
+ log_assert(cell->parameters.empty());
+
+
+ // The idea is to create two techmap designs, one which maps:
+ //
+ // box u0 (.i(i), .o(o));
+ //
+ // to
+ //
+ // wire $abc9$o;
+ // box u0 (.i(i), .o($abc9_byp$o));
+ // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o));
+ //
+ // the purpose being to move the (* abc9_box *) status from 'box'
+ // (which is stateful) to 'box_$abc9_byp' (which becomes a new
+ // combinatorial black- (not white-) box with all state elements
+ // removed). This has the effect of preserving any combinatorial
+ // paths through an otherwise sequential primitive -- e.g. LUTRAMs.
+ //
+ // The unmap design performs the reverse:
+ //
+ // wire $abc9$o;
+ // box u0 (.i(i), .o($abc9_byp$o));
+ // box_$abc9_byp (.i(i), .$abc9_byp$o($abc9_byp$o), .o(o));
+ //
+ // to:
+ //
+ // wire $abc9$o;
+ // box u0 (.i(i), .o($abc9_byp$o));
+ // assign o = $abc9_byp$o;
+
+
+ // Copy inst_module into map_design, with the same interface
+ // and duplicate $abc9$* wires for its output ports
+ auto map_module = map_design->addModule(cell->type);
+ for (auto port_name : inst_module->ports) {
+ auto w = map_module->addWire(port_name, inst_module->wire(port_name));
+ if (w->port_output)
+ w->attributes.erase(ID::init);
+ }
+ map_module->ports = inst_module->ports;
+ map_module->check();
+ map_module->set_bool_attribute(ID::whitebox);
+
+ // Create the bypass module in the user design, which has the same
+ // interface as the derived module but with additional input
+ // ports driven by the outputs of the replaced cell
+ auto bypass_module = design->addModule(cell->type.str() + "_$abc9_byp");
+ for (auto port_name : inst_module->ports) {
+ auto port = inst_module->wire(port_name);
+ if (!port->port_output)
+ continue;
+ auto dst = bypass_module->addWire(port_name, port);
+ auto src = bypass_module->addWire("$abc9byp$" + port_name.str(), GetSize(port));
+ src->port_input = true;
+ // For these new input ports driven by the replaced
+ // cell, then create a new simple-path specify entry:
+ // (input => output) = 0
+ auto specify = bypass_module->addCell(NEW_ID, ID($specify2));
+ specify->setPort(ID::EN, State::S1);
+ specify->setPort(ID::SRC, src);
+ specify->setPort(ID::DST, dst);
+ specify->setParam(ID::FULL, 0);
+ specify->setParam(ID::SRC_WIDTH, GetSize(src));
+ specify->setParam(ID::DST_WIDTH, GetSize(dst));
+ specify->setParam(ID::SRC_DST_PEN, 0);
+ specify->setParam(ID::SRC_DST_POL, 0);
+ specify->setParam(ID::T_RISE_MIN, 0);
+ specify->setParam(ID::T_RISE_TYP, 0);
+ specify->setParam(ID::T_RISE_MAX, 0);
+ specify->setParam(ID::T_FALL_MIN, 0);
+ specify->setParam(ID::T_FALL_TYP, 0);
+ specify->setParam(ID::T_FALL_MAX, 0);
+ }
+ bypass_module->set_bool_attribute(ID::blackbox);
+ bypass_module->set_bool_attribute(ID::abc9_box);
+
+ // Copy any 'simple' (combinatorial) specify paths from
+ // the derived module into the bypass module, if EN
+ // is not false and SRC/DST are driven only by
+ // module ports; create new input port if one doesn't
+ // already exist
+ for (auto cell : inst_module->cells()) {
+ if (cell->type != ID($specify2))
+ continue;
+ auto EN = cell->getPort(ID::EN).as_bit();
+ SigBit newEN;
+ if (!EN.wire && EN != State::S1)
+ continue;
+ auto SRC = cell->getPort(ID::SRC);
+ for (const auto &c : SRC.chunks())
+ if (c.wire && !c.wire->port_input) {
+ SRC = SigSpec();
+ break;
+ }
+ if (SRC.empty())
+ continue;
+ auto DST = cell->getPort(ID::DST);
+ for (const auto &c : DST.chunks())
+ if (c.wire && !c.wire->port_output) {
+ DST = SigSpec();
+ break;
+ }
+ if (DST.empty())
+ continue;
+ auto rw = [bypass_module](RTLIL::SigSpec &sig)
+ {
+ SigSpec new_sig;
+ for (auto c : sig.chunks()) {
+ if (c.wire) {
+ auto port = bypass_module->wire(c.wire->name);
+ if (!port)
+ port = bypass_module->addWire(c.wire->name, c.wire);
+ c.wire = port;
+ }
+ new_sig.append(std::move(c));
+ }
+ sig = std::move(new_sig);
+ };
+ auto specify = bypass_module->addCell(NEW_ID, cell);
+ specify->rewrite_sigspecs(rw);
+ }
+ bypass_module->fixup_ports();
+
+ // Create an _TECHMAP_REPLACE_ cell identical to the original cell,
+ // and a bypass cell that has the same inputs/outputs as the
+ // original cell, but with additional inputs taken from the
+ // replaced cell
+ auto replace_cell = map_module->addCell(ID::_TECHMAP_REPLACE_, cell->type);
+ auto bypass_cell = map_module->addCell(NEW_ID, cell->type.str() + "_$abc9_byp");
+ for (const auto &conn : cell->connections()) {
+ auto port = map_module->wire(conn.first);
+ if (cell->input(conn.first)) {
+ replace_cell->setPort(conn.first, port);
+ if (bypass_module->wire(conn.first))
+ bypass_cell->setPort(conn.first, port);
+ }
+ if (cell->output(conn.first)) {
+ bypass_cell->setPort(conn.first, port);
+ auto n = "$abc9byp$" + conn.first.str();
+ auto w = map_module->addWire(n, GetSize(conn.second));
+ replace_cell->setPort(conn.first, w);
+ bypass_cell->setPort(n, w);
+ }
+ }
+
+
+ // Lastly, create a new module in the unmap_design that shorts
+ // out the bypass cell back to leave the replace cell behind
+ // driving the outputs
+ auto unmap_module = unmap_design->addModule(cell->type.str() + "_$abc9_byp");
+ for (auto port_name : inst_module->ports) {
+ auto w = unmap_module->addWire(port_name, inst_module->wire(port_name));
+ if (w->port_output) {
+ w->attributes.erase(ID::init);
+ auto w2 = unmap_module->addWire("$abc9byp$" + port_name.str(), GetSize(w));
+ w2->port_input = true;
+ unmap_module->connect(w, w2);
+ }
+ }
+ unmap_module->fixup_ports();
+ }
+}
+
+void prep_dff(RTLIL::Design *design)
+{
+ auto r = design->selection_vars.insert(std::make_pair(ID($abc9_flops), RTLIL::Selection(false)));
+ auto &modules_sel = r.first->second;
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->cells()) {
+ if (modules_sel.selected_whole_module(cell->type))
+ continue;
+ auto inst_module = design->module(cell->type);
+ if (!inst_module)
+ continue;
+ if (!inst_module->get_bool_attribute(ID::abc9_flop))
+ continue;
+ log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */));
+ log_assert(cell->parameters.empty());
+ modules_sel.select(inst_module);
+ }
+}
+
+void prep_dff_submod(RTLIL::Design *design)
+{
+ for (auto module : design->modules()) {
+ vector<Cell*> specify_cells;
+ SigBit Q;
+ Cell* dff_cell = nullptr;
+
+ if (!module->get_bool_attribute(ID::abc9_flop))
+ continue;
+
+ for (auto cell : module->cells())
+ if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_))) {
+ log_assert(!dff_cell);
+ dff_cell = cell;
+ Q = cell->getPort(ID::Q);
+ log_assert(GetSize(Q.wire) == 1);
+ }
+ else if (cell->type.in(ID($specify3), ID($specrule)))
+ specify_cells.emplace_back(cell);
+ log_assert(dff_cell);
+
+ // Add an always-enabled CE mux that drives $_DFF_[NP]_.D so that:
+ // (a) flop box will have an output
+ // (b) $_DFF_[NP]_.Q will be present as an input
+ SigBit D = module->addWire(NEW_ID);
+ module->addMuxGate(NEW_ID, dff_cell->getPort(ID::D), Q, State::S0, D);
+ dff_cell->setPort(ID::D, D);
+
+ // Rewrite $specify cells that end with $_DFF_[NP]_.Q
+ // to $_DFF_[NP]_.D since it will be moved into
+ // the submodule
+ for (auto cell : specify_cells) {
+ auto DST = cell->getPort(ID::DST);
+ DST.replace(Q, D);
+ cell->setPort(ID::DST, DST);
+ }
+
+ design->scratchpad_set_bool("abc9_ops.prep_dff_submod.did_something", true);
+ }
+}
+
+void prep_dff_unmap(RTLIL::Design *design)
+{
+ Design *unmap_design = saved_designs.at("$abc9_unmap");
+
+ for (auto module : design->modules()) {
+ if (!module->get_bool_attribute(ID::abc9_flop) || module->get_bool_attribute(ID::abc9_box))
+ continue;
+
+ // Make sure the box module has all the same ports present on flop cell
+ auto replace_cell = module->cell(ID::_TECHMAP_REPLACE_);
+ log_assert(replace_cell);
+ auto box_module = design->module(module->name.str() + "_$abc9_flop");
+ log_assert(box_module);
+ for (auto port_name : module->ports) {
+ auto port = module->wire(port_name);
+ auto box_port = box_module->wire(port_name);
+ if (box_port) {
+ // Do not propagate init -- already captured by box
+ box_port->attributes.erase(ID::init);
+ continue;
+ }
+ log_assert(port->port_input);
+ box_module->addWire(port_name, port);
+ replace_cell->setPort(port_name, port);
+ }
+ box_module->fixup_ports();
+
+ auto unmap_module = unmap_design->addModule(box_module->name);
+ replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name);
+ for (auto port_name : box_module->ports) {
+ auto w = unmap_module->addWire(port_name, box_module->wire(port_name));
+ if (module->wire(port_name))
+ replace_cell->setPort(port_name, w);
+ }
+ unmap_module->ports = box_module->ports;
+ unmap_module->check();
+ }
}
void mark_scc(RTLIL::Module *module)
@@ -95,7 +549,7 @@ void mark_scc(RTLIL::Module *module)
// For every unique SCC found, (arbitrarily) find the first
// cell in the component, and replace its output connections
// with a new wire driven by the old connection but with a
- // special (* abc9_scc *) attribute set (which is used by
+ // special (* abc9_keep *) attribute set (which is used by
// write_xaiger to break this wire into PI and POs)
pool<RTLIL::Const> ids_seen;
for (auto cell : module->cells()) {
@@ -111,7 +565,7 @@ void mark_scc(RTLIL::Module *module)
if (c.second.is_fully_const()) continue;
if (cell->output(c.first)) {
Wire *w = module->addWire(NEW_ID, GetSize(c.second));
- w->set_bool_attribute(ID::abc9_scc);
+ w->set_bool_attribute(ID::abc9_keep);
module->connect(w, c.second);
c.second = w;
}
@@ -119,80 +573,94 @@ void mark_scc(RTLIL::Module *module)
}
}
-void prep_dff(RTLIL::Module *module)
+void prep_delays(RTLIL::Design *design, bool dff_mode)
{
- auto design = module->design;
- log_assert(design);
+ TimingInfo timing;
- SigMap assign_map(module);
+ // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes
+ // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations
+ std::vector<Cell*> cells;
+ for (auto module : design->selected_modules()) {
+ if (module->processes.size() > 0) {
+ log("Skipping module %s as it contains processes.\n", log_id(module));
+ continue;
+ }
- typedef SigSpec clkdomain_t;
- dict<clkdomain_t, int> clk_to_mergeability;
+ for (auto cell : module->cells()) {
+ if (cell->type.in(ID($_AND_), ID($_NOT_), ID($_DFF_N_), ID($_DFF_P_)))
+ continue;
+ log_assert(!cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
- for (auto cell : module->cells()) {
- if (cell->type != ID($__ABC9_FF_))
- continue;
+ RTLIL::Module* inst_module = design->module(cell->type);
+ if (!inst_module)
+ continue;
+ if (!inst_module->get_blackbox_attribute())
+ continue;
+ if (!cell->parameters.empty())
+ continue;
- Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str()));
- if (abc9_clock_wire == NULL)
- log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
- SigSpec abc9_clock = assign_map(abc9_clock_wire);
+ if (inst_module->get_bool_attribute(ID::abc9_box))
+ continue;
+ if (inst_module->get_bool_attribute(ID::abc9_bypass))
+ continue;
- clkdomain_t key(abc9_clock);
+ if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) {
+ continue; // do not add $__ABC9_DELAY boxes to flops
+ // as delays will be captured in the flop box
+ }
+
+ if (!timing.count(cell->type))
+ timing.setup_module(inst_module);
- auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1));
- auto r2 = cell->attributes.insert(ID::abc9_mergeability);
- log_assert(r2.second);
- r2.first->second = r.first->second;
+ cells.emplace_back(cell);
+ }
}
- RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str()));
- if (holes_module) {
- SigMap sigmap(holes_module);
+ // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes
+ // (or bypassed white-boxes with required times)
+ dict<int, IdString> box_cache;
+ Module *delay_module = design->module(ID($__ABC9_DELAY));
+ log_assert(delay_module);
+ for (auto cell : cells) {
+ auto module = cell->module;
+ auto inst_module = design->module(cell->type);
+ log_assert(inst_module);
- dict<SigSpec, SigSpec> replace;
- for (auto cell : holes_module->cells().to_vector()) {
- if (!cell->type.in(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_)))
+ auto &t = timing.at(cell->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) from module %s does not actually exist",
+ log_id(conn.first), log_id(cell), log_id(cell->type), log_id(module));
+ if (!port_wire->port_input)
+ continue;
+ if (conn.second.is_fully_const())
continue;
- SigBit D = cell->getPort(ID::D);
- SigBit Q = cell->getPort(ID::Q);
- // Emulate async control embedded inside $_DFF_* cell with mux in front of D
- if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_PN0_)))
- D = holes_module->MuxGate(NEW_ID, State::S0, D, cell->getPort(ID::R));
- else if (cell->type.in(ID($_DFF_NN1_), ID($_DFF_PN1_)))
- D = holes_module->MuxGate(NEW_ID, State::S1, D, cell->getPort(ID::R));
- else if (cell->type.in(ID($_DFF_NP0_), ID($_DFF_PP0_)))
- D = holes_module->MuxGate(NEW_ID, D, State::S0, cell->getPort(ID::R));
- else if (cell->type.in(ID($_DFF_NP1_), ID($_DFF_PP1_)))
- D = holes_module->MuxGate(NEW_ID, D, State::S1, cell->getPort(ID::R));
- // Remove the $_DFF_* cell from what needs to be a combinatorial box
- holes_module->remove(cell);
- Wire *port;
- if (GetSize(Q.wire) == 1)
- port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str()));
- else
- port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset));
- log_assert(port);
- // Prepare to replace "assign <port> = $_DFF_*.Q;" with "assign <port> = $_DFF_*.D;"
- // in order to extract just the combinatorial control logic that feeds the box
- // (i.e. clock enable, synchronous reset, etc.)
- replace.insert(std::make_pair(Q,D));
- // Since `flatten` above would have created wires named "<cell>.Q",
- // extract the pre-techmap cell name
- auto pos = Q.wire->name.str().rfind(".");
- log_assert(pos != std::string::npos);
- IdString driver = Q.wire->name.substr(0, pos);
- // And drive the signal that was previously driven by "DFF.Q" (typically
- // used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
- // wire (which itself is driven an by input port) we inserted above
- Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str()));
- log_assert(currQ);
- holes_module->connect(Q, currQ);
- }
- for (auto &conn : holes_module->connections_)
- conn.second = replace.at(sigmap(conn.second), conn.second);
+ SigSpec O = module->addWire(NEW_ID, GetSize(conn.second));
+ for (int i = 0; i < GetSize(conn.second); i++) {
+ auto d = t.at(TimingInfo::NameBit(conn.first,i), 0);
+ if (d == 0)
+ continue;
+
+#ifndef NDEBUG
+ if (ys_debug(1)) {
+ static std::set<std::tuple<IdString,IdString,int>> seen;
+ if (seen.emplace(cell->type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n",
+ log_id(cell->type), log_id(conn.first), i, d);
+ }
+#endif
+ auto r = box_cache.insert(d);
+ if (r.second) {
+ r.first->second = delay_module->derive(design, {{ID::DELAY, d}});
+ log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
+ }
+ auto box = module->addCell(NEW_ID, r.first->second);
+ box->setPort(ID::I, conn.second[i]);
+ box->setPort(ID::O, O[i]);
+ conn.second[i] = O[i];
+ }
+ }
}
}
@@ -208,17 +676,17 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
dict<IdString, std::vector<IdString>> box_ports;
for (auto cell : module->cells()) {
- if (cell->type == ID($__ABC9_FF_))
+ if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
continue;
if (cell->has_keep_attr())
continue;
- auto inst_module = module->design->module(cell->type);
+ auto inst_module = design->module(cell->type);
bool abc9_flop = inst_module && inst_module->get_bool_attribute(ID::abc9_flop);
if (abc9_flop && !dff)
continue;
- if ((inst_module && inst_module->get_bool_attribute(ID::abc9_box)) || abc9_flop) {
+ if (inst_module && inst_module->get_bool_attribute(ID::abc9_box)) {
auto r = box_ports.insert(cell->type);
if (r.second) {
// Make carry in the last PI, and carry out the last PO
@@ -253,8 +721,10 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
bit_users[bit].insert(cell->name);
if (cell->output(conn.first) && !abc9_flop)
- for (auto bit : sigmap(conn.second))
- bit_drivers[bit].insert(cell->name);
+ for (const auto &chunk : conn.second.chunks())
+ if (!chunk.wire->get_bool_attribute(ID::abc9_keep))
+ for (auto b : sigmap(SigSpec(chunk)))
+ bit_drivers[b].insert(cell->name);
}
toposort.node(cell->name);
}
@@ -271,7 +741,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
if (ys_debug(1))
toposort.analyze_loops = true;
- bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
+ bool no_loops = toposort.sort();
if (ys_debug(1)) {
unsigned i = 0;
@@ -287,9 +757,13 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
log_assert(no_loops);
- RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str()));
+ auto r = saved_designs.emplace("$abc9_holes", nullptr);
+ if (r.second)
+ r.first->second = new Design;
+ RTLIL::Design *holes_design = r.first->second;
+ log_assert(holes_design);
+ RTLIL::Module *holes_module = holes_design->addModule(module->name);
log_assert(holes_module);
- holes_module->set_bool_attribute(ID::abc9_holes);
dict<IdString, Cell*> cell_cache;
TimingInfo timing;
@@ -300,22 +774,20 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
log_assert(cell);
RTLIL::Module* box_module = design->module(cell->type);
- if (!box_module || (!box_module->get_bool_attribute(ID::abc9_box) && !box_module->get_bool_attribute(ID::abc9_flop)))
+ if (!box_module)
+ continue;
+ if (!box_module->get_bool_attribute(ID::abc9_box))
continue;
+ log_assert(cell->parameters.empty());
+ log_assert(box_module->get_blackbox_attribute());
cell->attributes[ID::abc9_box_seq] = box_count++;
- IdString derived_type = box_module->derive(design, cell->parameters);
- box_module = design->module(derived_type);
-
- auto r = cell_cache.insert(derived_type);
+ auto r = cell_cache.insert(cell->type);
auto &holes_cell = r.first->second;
if (r.second) {
- if (box_module->has_processes())
- Pass::call_on_module(design, box_module, "proc");
-
if (box_module->get_bool_attribute(ID::whitebox)) {
- holes_cell = holes_module->addCell(cell->name, derived_type);
+ holes_cell = holes_module->addCell(cell->name, cell->type);
if (box_module->has_processes())
Pass::call_on_module(design, box_module, "proc");
@@ -340,22 +812,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
}
}
else if (w->port_output)
- conn = holes_module->addWire(stringf("%s.%s", derived_type.c_str(), log_id(port_name)), GetSize(w));
- }
-
- // For flops only, create an extra 1-bit input that drives a new wire
- // called "<cell>.abc9_ff.Q" that is used below
- if (box_module->get_bool_attribute(ID::abc9_flop)) {
- box_inputs++;
- Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
- if (!holes_wire) {
- holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
- holes_wire->port_input = true;
- holes_wire->port_id = port_id++;
- holes_module->ports.push_back(holes_wire->name);
- }
- Wire *Q = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str()));
- holes_module->connect(Q, holes_wire);
+ conn = holes_module->addWire(stringf("%s.%s", cell->type.c_str(), log_id(port_name)), GetSize(w));
}
}
else // box_module is a blackbox
@@ -379,90 +836,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
}
}
-void prep_delays(RTLIL::Design *design, bool dff_mode)
-{
- TimingInfo timing;
-
- // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes
- // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations
- pool<Module*> flops;
- std::vector<Cell*> cells;
- for (auto module : design->selected_modules()) {
- if (module->processes.size() > 0) {
- log("Skipping module %s as it contains processes.\n", log_id(module));
- continue;
- }
-
- for (auto cell : module->cells()) {
- if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY)))
- continue;
-
- RTLIL::Module* inst_module = module->design->module(cell->type);
- if (!inst_module)
- continue;
- if (!inst_module->get_blackbox_attribute())
- continue;
- if (inst_module->attributes.count(ID::abc9_box))
- continue;
- IdString derived_type = inst_module->derive(design, cell->parameters);
- inst_module = design->module(derived_type);
- log_assert(inst_module);
-
- if (dff_mode && inst_module->get_bool_attribute(ID::abc9_flop)) {
- flops.insert(inst_module);
- continue; // do not add $__ABC9_DELAY boxes to flops
- // as delays will be captured in the flop box
- }
-
- if (!timing.count(derived_type))
- timing.setup_module(inst_module);
-
- cells.emplace_back(cell);
- }
- }
-
- // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes
- // with required times
- for (auto cell : cells) {
- auto module = cell->module;
- RTLIL::Module* inst_module = module->design->module(cell->type);
- log_assert(inst_module);
- IdString derived_type = inst_module->derive(design, cell->parameters);
- inst_module = design->module(derived_type);
- log_assert(inst_module);
-
- 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;
-
- SigSpec O = module->addWire(NEW_ID, GetSize(conn.second));
- for (int i = 0; i < GetSize(conn.second); i++) {
- auto d = t.at(TimingInfo::NameBit(conn.first,i), 0);
- if (d == 0)
- continue;
-
-#ifndef NDEBUG
- if (ys_debug(1)) {
- static std::set<std::tuple<IdString,IdString,int>> seen;
- if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n",
- log_id(cell->type), log_id(conn.first), i, d);
- }
-#endif
- auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY));
- box->setPort(ID::I, conn.second[i]);
- box->setPort(ID::O, O[i]);
- box->setParam(ID::DELAY, d);
- conn.second[i] = O[i];
- }
- }
- }
-}
-
void prep_lut(RTLIL::Design *design, int maxlut)
{
TimingInfo timing;
@@ -540,7 +913,7 @@ void write_lut(RTLIL::Module *module, const std::string &dst) {
ofs.close();
}
-void prep_box(RTLIL::Design *design, bool dff_mode)
+void prep_box(RTLIL::Design *design)
{
TimingInfo timing;
@@ -555,165 +928,162 @@ void prep_box(RTLIL::Design *design, bool dff_mode)
dict<IdString,std::vector<IdString>> box_ports;
for (auto module : design->modules()) {
- auto abc9_flop = module->get_bool_attribute(ID::abc9_flop);
- if (abc9_flop) {
- auto r = module->attributes.insert(ID::abc9_box_id);
- if (!r.second)
- continue;
- r.first->second = abc9_box_id++;
-
- if (dff_mode) {
- int num_inputs = 0, num_outputs = 0;
- for (auto port_name : module->ports) {
- auto wire = module->wire(port_name);
- log_assert(GetSize(wire) == 1);
- if (wire->port_input) num_inputs++;
- if (wire->port_output) num_outputs++;
- }
- log_assert(num_outputs == 1);
+ auto it = module->attributes.find(ID::abc9_box);
+ if (it == module->attributes.end())
+ continue;
+ bool box = it->second.as_bool();
+ module->attributes.erase(it);
+ if (!box)
+ continue;
- ss << log_id(module) << " " << r.first->second.as_int();
- ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
- ss << " " << num_inputs+1 << " " << num_outputs << std::endl;
+ auto r = module->attributes.insert(ID::abc9_box_id);
+ if (!r.second)
+ continue;
+ r.first->second = abc9_box_id++;
+
+ if (module->get_bool_attribute(ID::abc9_flop)) {
+ int num_inputs = 0, num_outputs = 0;
+ for (auto port_name : module->ports) {
+ auto wire = module->wire(port_name);
+ log_assert(GetSize(wire) == 1);
+ if (wire->port_input) num_inputs++;
+ if (wire->port_output) num_outputs++;
+ }
+ log_assert(num_outputs == 1);
+
+ ss << log_id(module) << " " << r.first->second.as_int();
+ log_assert(module->get_bool_attribute(ID::whitebox));
+ ss << " " << "1";
+ ss << " " << num_inputs << " " << num_outputs << std::endl;
+
+ ss << "#";
+ bool first = true;
+ for (auto port_name : module->ports) {
+ auto wire = module->wire(port_name);
+ if (!wire->port_input)
+ continue;
+ if (first)
+ first = false;
+ else
+ ss << " ";
+ ss << log_id(wire);
+ }
+ ss << std::endl;
- ss << "#";
- bool first = true;
- for (auto port_name : module->ports) {
- auto wire = module->wire(port_name);
- if (!wire->port_input)
- continue;
- if (first)
- first = false;
- else
- ss << " ";
- ss << log_id(wire);
- }
- ss << " abc9_ff.Q" << std::endl;
+ auto &t = timing.setup_module(module).required;
+ if (t.empty())
+ log_error("Module '%s' with (* abc9_flop *) has no clk-to-q timing (and thus no connectivity) information.\n", log_id(module));
- auto &t = timing.setup_module(module).required;
- first = true;
- for (auto port_name : module->ports) {
- auto wire = module->wire(port_name);
- if (!wire->port_input)
- continue;
- if (first)
- first = false;
- else
- ss << " ";
- log_assert(GetSize(wire) == 1);
- auto it = t.find(TimingInfo::NameBit(port_name,0));
- if (it == t.end())
- // Assume that no setup time means zero
- ss << 0;
- else {
- ss << it->second;
+ first = true;
+ for (auto port_name : module->ports) {
+ auto wire = module->wire(port_name);
+ if (!wire->port_input)
+ continue;
+ if (first)
+ first = false;
+ else
+ ss << " ";
+ log_assert(GetSize(wire) == 1);
+ auto it = t.find(TimingInfo::NameBit(port_name,0));
+ if (it == t.end())
+ // Assume no connectivity if no setup time
+ ss << "-";
+ else {
+ ss << it->second;
#ifndef NDEBUG
- if (ys_debug(1)) {
- static std::set<std::pair<IdString,IdString>> seen;
- if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module),
- log_id(port_name), it->second);
- }
-#endif
+ if (ys_debug(1)) {
+ static std::set<std::pair<IdString,IdString>> seen;
+ if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module),
+ log_id(port_name), it->second);
}
-
+#endif
}
- // Last input is 'abc9_ff.Q'
- ss << " 0" << std::endl << std::endl;
- continue;
}
+ ss << " # $_DFF_[NP]_.D" << std::endl;
+ ss << std::endl;
}
else {
- if (!module->attributes.erase(ID::abc9_box))
- continue;
-
- auto r = module->attributes.insert(ID::abc9_box_id);
- if (!r.second)
- continue;
- r.first->second = abc9_box_id++;
- }
+ auto r2 = box_ports.insert(module->name);
+ if (r2.second) {
+ // Make carry in the last PI, and carry out the last PO
+ // since ABC requires it this way
+ IdString carry_in, carry_out;
+ for (const auto &port_name : module->ports) {
+ auto w = module->wire(port_name);
+ log_assert(w);
+ if (w->get_bool_attribute(ID::abc9_carry)) {
+ log_assert(w->port_input != w->port_output);
+ if (w->port_input)
+ carry_in = port_name;
+ else if (w->port_output)
+ carry_out = port_name;
+ }
+ else
+ r2.first->second.push_back(port_name);
+ }
- auto r = box_ports.insert(module->name);
- if (r.second) {
- // Make carry in the last PI, and carry out the last PO
- // since ABC requires it this way
- IdString carry_in, carry_out;
- for (const auto &port_name : module->ports) {
- auto w = module->wire(port_name);
- log_assert(w);
- if (w->get_bool_attribute(ID::abc9_carry)) {
- log_assert(w->port_input != w->port_output);
- if (w->port_input)
- carry_in = port_name;
- else if (w->port_output)
- carry_out = port_name;
+ if (carry_in != IdString()) {
+ r2.first->second.push_back(carry_in);
+ r2.first->second.push_back(carry_out);
}
- else
- r.first->second.push_back(port_name);
}
- if (carry_in != IdString()) {
- r.first->second.push_back(carry_in);
- r.first->second.push_back(carry_out);
+ std::vector<SigBit> inputs, outputs;
+ for (auto port_name : r2.first->second) {
+ auto wire = module->wire(port_name);
+ if (wire->port_input)
+ for (int i = 0; i < GetSize(wire); i++)
+ inputs.emplace_back(wire, i);
+ if (wire->port_output)
+ for (int i = 0; i < GetSize(wire); i++)
+ outputs.emplace_back(wire, i);
}
- }
-
- std::vector<SigBit> inputs;
- std::vector<SigBit> outputs;
- for (auto port_name : r.first->second) {
- auto wire = module->wire(port_name);
- if (wire->port_input)
- for (int i = 0; i < GetSize(wire); i++)
- inputs.emplace_back(wire, i);
- if (wire->port_output)
- for (int i = 0; i < GetSize(wire); i++)
- outputs.emplace_back(wire, i);
- }
- ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int();
- ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
- ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl;
+ ss << log_id(module) << " " << module->attributes.at(ID::abc9_box_id).as_int();
+ ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0");
+ ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl;
- bool first = true;
- ss << "#";
- for (const auto &i : inputs) {
- if (first)
- first = false;
- else
- ss << " ";
- if (GetSize(i.wire) == 1)
- ss << log_id(i.wire);
- else
- ss << log_id(i.wire) << "[" << i.offset << "]";
- }
- ss << std::endl;
-
- auto &t = timing.setup_module(module).comb;
- if (!abc9_flop && t.empty())
- log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module));
-
- for (const auto &o : outputs) {
- first = true;
+ bool first = true;
+ ss << "#";
for (const auto &i : inputs) {
if (first)
first = false;
else
ss << " ";
- auto jt = t.find(TimingInfo::BitBit(i,o));
- if (jt == t.end())
- ss << "-";
+ if (GetSize(i.wire) == 1)
+ ss << log_id(i.wire);
else
- ss << jt->second;
+ ss << log_id(i.wire) << "[" << i.offset << "]";
}
- ss << " # ";
- if (GetSize(o.wire) == 1)
- ss << log_id(o.wire);
- else
- ss << log_id(o.wire) << "[" << o.offset << "]";
ss << std::endl;
+ auto &t = timing.setup_module(module);
+ if (t.comb.empty())
+ log_error("Module '%s' with (* abc9_box *) has no timing (and thus no connectivity) information.\n", log_id(module));
+
+ for (const auto &o : outputs) {
+ first = true;
+ for (const auto &i : inputs) {
+ if (first)
+ first = false;
+ else
+ ss << " ";
+ auto jt = t.comb.find(TimingInfo::BitBit(i,o));
+ if (jt == t.comb.end())
+ ss << "-";
+ else
+ ss << jt->second;
+ }
+ ss << " # ";
+ if (GetSize(o.wire) == 1)
+ ss << log_id(o.wire);
+ else
+ ss << log_id(o.wire) << "[" << o.offset << "]";
+ ss << std::endl;
+ }
+ ss << std::endl;
}
- ss << std::endl;
}
// ABC expects at least one box
@@ -730,7 +1100,7 @@ void write_box(RTLIL::Module *module, const std::string &dst) {
ofs.close();
}
-void reintegrate(RTLIL::Module *module)
+void reintegrate(RTLIL::Module *module, bool dff_mode)
{
auto design = module->design;
log_assert(design);
@@ -744,6 +1114,8 @@ void reintegrate(RTLIL::Module *module)
for (auto w : mapped_mod->wires()) {
auto nw = module->addWire(remap_name(w->name), GetSize(w));
nw->start_offset = w->start_offset;
+ // Remove all (* init *) since they only exist on $_DFF_[NP]_
+ w->attributes.erase(ID::init);
}
dict<IdString,std::vector<IdString>> box_ports;
@@ -779,11 +1151,38 @@ void reintegrate(RTLIL::Module *module)
}
}
+ SigMap initmap;
+ if (dff_mode) {
+ // Build a sigmap prioritising bits with (* init *)
+ initmap.set(module);
+ for (auto w : module->wires()) {
+ auto it = w->attributes.find(ID::init);
+ if (it == w->attributes.end())
+ continue;
+ for (auto i = 0; i < GetSize(w); i++)
+ if (it->second[i] == State::S0 || it->second[i] == State::S1)
+ initmap.add(w);
+ }
+ }
+
std::vector<Cell*> boxes;
for (auto cell : module->cells().to_vector()) {
if (cell->has_keep_attr())
continue;
- if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
+
+ // Short out (so that existing name can be preserved) and remove
+ // $_DFF_[NP]_ cells since flop box already has all the information
+ // we need to reconstruct them
+ if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) {
+ SigBit Q = cell->getPort(ID::Q);
+ module->connect(Q, cell->getPort(ID::D));
+ module->remove(cell);
+ auto Qi = initmap(Q);
+ auto it = Qi.wire->attributes.find(ID::init);
+ if (it != Qi.wire->attributes.end())
+ it->second[Qi.offset] = State::Sx;
+ }
+ else if (cell->type.in(ID($_AND_), ID($_NOT_)))
module->remove(cell);
else if (cell->attributes.erase(ID::abc9_box_seq))
boxes.emplace_back(cell);
@@ -797,6 +1196,18 @@ void reintegrate(RTLIL::Module *module)
std::map<IdString, int> cell_stats;
for (auto mapped_cell : mapped_mod->cells())
{
+ // Short out $_FF_ cells since the flop box already has
+ // all the information we need to reconstruct cell
+ if (dff_mode && mapped_cell->type == ID($_FF_)) {
+ SigBit D = mapped_cell->getPort(ID::D);
+ SigBit Q = mapped_cell->getPort(ID::Q);
+ if (D.wire)
+ D.wire = module->wires_.at(remap_name(D.wire->name));
+ Q.wire = module->wires_.at(remap_name(Q.wire->name));
+ module->connect(Q, D);
+ continue;
+ }
+
// TODO: Speed up toposort -- we care about NOT ordering only
toposort.node(mapped_cell->name);
@@ -846,7 +1257,7 @@ void reintegrate(RTLIL::Module *module)
continue;
}
- if (mapped_cell->type.in(ID($lut), ID($__ABC9_FF_))) {
+ if (mapped_cell->type == ID($lut)) {
RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
cell->parameters = mapped_cell->parameters;
cell->attributes = mapped_cell->attributes;
@@ -881,7 +1292,7 @@ void reintegrate(RTLIL::Module *module)
if (!existing_cell)
log_error("Cannot find existing box cell with name '%s' in original design.\n", log_id(mapped_cell));
- if (existing_cell->type == ID($__ABC9_DELAY)) {
+ if (existing_cell->type.begins_with("$paramod$__ABC9_DELAY\\DELAY=")) {
SigBit I = mapped_cell->getPort(ID(i));
SigBit O = mapped_cell->getPort(ID(o));
if (I.wire)
@@ -893,10 +1304,8 @@ void reintegrate(RTLIL::Module *module)
}
RTLIL::Module* box_module = design->module(existing_cell->type);
- IdString derived_type = box_module->derive(design, existing_cell->parameters);
- RTLIL::Module* derived_module = design->module(derived_type);
- log_assert(derived_module);
- log_assert(mapped_cell->type == stringf("$__boxid%d", derived_module->attributes.at(ID::abc9_box_id).as_int()));
+ log_assert(existing_cell->parameters.empty());
+ log_assert(mapped_cell->type == stringf("$__boxid%d", box_module->attributes.at(ID::abc9_box_id).as_int()));
mapped_cell->type = existing_cell->type;
RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
@@ -913,8 +1322,26 @@ void reintegrate(RTLIL::Module *module)
SigSpec outputs = std::move(jt->second);
mapped_cell->connections_.erase(jt);
- auto abc9_flop = box_module->attributes.count(ID::abc9_flop);
- if (!abc9_flop) {
+ auto abc9_flop = box_module->get_bool_attribute(ID::abc9_flop);
+ if (abc9_flop) {
+ // Link this sole flop box output to the output of the existing
+ // flop box, so that any (public) signal it drives will be
+ // preserved
+ SigBit old_q;
+ for (const auto &port_name : box_ports.at(existing_cell->type)) {
+ RTLIL::Wire *w = box_module->wire(port_name);
+ log_assert(w);
+ if (!w->port_output)
+ continue;
+ log_assert(old_q == SigBit());
+ log_assert(GetSize(w) == 1);
+ old_q = existing_cell->getPort(port_name);
+ }
+ auto new_q = outputs[0];
+ new_q.wire = module->wires_.at(remap_name(new_q.wire->name));
+ module->connect(old_q, new_q);
+ }
+ else {
for (const auto &i : inputs)
bit_users[i].insert(mapped_cell->name);
for (const auto &i : outputs)
@@ -924,7 +1351,7 @@ void reintegrate(RTLIL::Module *module)
}
int input_count = 0, output_count = 0;
- for (const auto &port_name : box_ports.at(derived_type)) {
+ for (const auto &port_name : box_ports.at(existing_cell->type)) {
RTLIL::Wire *w = box_module->wire(port_name);
log_assert(w);
@@ -947,11 +1374,12 @@ void reintegrate(RTLIL::Module *module)
c.wire = module->wires_.at(remap_name(c.wire->name));
newsig.append(c);
}
- cell->setPort(port_name, newsig);
if (w->port_input && !abc9_flop)
for (const auto &i : newsig)
bit2sinks[i].push_back(cell);
+
+ cell->setPort(port_name, std::move(newsig));
}
}
@@ -988,7 +1416,7 @@ void reintegrate(RTLIL::Module *module)
RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
RTLIL::Wire *wire = module->wire(port);
log_assert(wire);
- wire->attributes.erase(ID::abc9_scc);
+ wire->attributes.erase(ID::abc9_keep);
RTLIL::Wire *remap_wire = module->wire(remap_name(port));
RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire));
@@ -1013,7 +1441,7 @@ void reintegrate(RTLIL::Module *module)
// treated as being "free"), in particular driving primary
// outputs (real primary outputs, or cells treated as blackboxes)
// or driving box inputs.
- // Instead of just mapping those $_NOT_ gates into 2-input $lut-s
+ // Instead of just mapping those $_NOT_ gates into 1-input $lut-s
// at an area and delay cost, see if it is possible to push
// this $_NOT_ into the driving LUT, or into all sink LUTs.
// When this is not possible, (i.e. this signal drives two primary
@@ -1025,7 +1453,7 @@ void reintegrate(RTLIL::Module *module)
for (auto driver_cell : bit_drivers.at(it.first))
for (auto user_cell : it.second)
toposort.edge(driver_cell, user_cell);
- bool no_loops YS_ATTRIBUTE(unused) = toposort.sort();
+ bool no_loops = toposort.sort();
log_assert(no_loops);
for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
@@ -1102,7 +1530,7 @@ clone_lut:
struct Abc9OpsPass : public Pass {
Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1116,6 +1544,37 @@ struct Abc9OpsPass : public Pass {
log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n");
log(" (* abc9_carry *) is only given for one input/output port, etc.\n");
log("\n");
+ log(" -prep_hier\n");
+ log(" derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)\n");
+ log(" whitebox modules. with (* abc9_flop *) modules, only those containing\n");
+ log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation\n");
+ log(" -- will be derived.\n");
+ log("\n");
+ log(" -prep_bypass\n");
+ log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n");
+ log(" bypassing sequential (* abc9_box *) modules using a combinatorial box\n");
+ log(" (named *_$abc9_byp). bypassing is necessary if sequential elements (e.g.\n");
+ log(" $dff, $mem, etc.) are discovered inside so that any combinatorial paths\n");
+ log(" will be correctly captured. this bypass box will only contain ports that\n");
+ log(" are referenced by a simple path declaration ($specify2 cell) inside a\n");
+ log(" specify block.\n");
+ log("\n");
+ log(" -prep_dff\n");
+ log(" select all (* abc9_flop *) modules instantiated in the design and store\n");
+ log(" in the named selection '$abc9_flops'.\n");
+ log("\n");
+ log(" -prep_dff_submod\n");
+ log(" within (* abc9_flop *) modules, rewrite all edge-sensitive path\n");
+ log(" declarations and $setup() timing checks ($specify3 and $specrule cells)\n");
+ log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n");
+ log(" the DFF's 'D' port. this is to prepare such specify cells to be moved\n");
+ log(" into the flop box.\n");
+ log("\n");
+ log(" -prep_dff_unmap\n");
+ log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n");
+ log(" cells back into their derived cell types (where the rules created by\n");
+ log(" -prep_hier will then map back to the original cell with parameters).\n");
+ log("\n");
log(" -prep_delays\n");
log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
log(" certain required times.\n");
@@ -1128,18 +1587,13 @@ struct Abc9OpsPass : public Pass {
log("\n");
log(" -prep_xaiger\n");
log(" prepare the design for XAIGER output. this includes computing the\n");
- log(" topological ordering of ABC9 boxes, as well as preparing the\n");
- log(" '<module-name>$holes' module that contains the logic behaviour of ABC9\n");
- log(" whiteboxes.\n");
+ log(" topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'\n");
+ log(" design that contains the logic behaviour of ABC9 whiteboxes.\n");
log("\n");
log(" -dff\n");
log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n");
log(" during -prep_{delays,xaiger,box}.\n");
log("\n");
- log(" -prep_dff\n");
- log(" compute the clock domain and initial value of each flop in the design.\n");
- log(" process the '$holes' module to support clock-enable functionality.\n");
- log("\n");
log(" -prep_lut <maxlut>\n");
log(" pre-compute the lut library by analysing all modules marked with\n");
log(" (* abc9_lut=<area> *).\n");
@@ -1160,14 +1614,16 @@ struct Abc9OpsPass : public Pass {
log(" inputs and outputs.\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) override
{
log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
bool check_mode = false;
bool prep_delays_mode = false;
bool mark_scc_mode = false;
- bool prep_dff_mode = false;
+ bool prep_hier_mode = false;
+ bool prep_bypass_mode = false;
+ bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false;
bool prep_xaiger_mode = false;
bool prep_lut_mode = false;
bool prep_box_mode = false;
@@ -1177,53 +1633,81 @@ struct Abc9OpsPass : public Pass {
int maxlut = 0;
std::string write_box_dst;
+ bool valid = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-check") {
check_mode = true;
+ valid = true;
continue;
}
if (arg == "-mark_scc") {
mark_scc_mode = true;
+ valid = true;
+ continue;
+ }
+ if (arg == "-prep_hier") {
+ prep_hier_mode = true;
+ valid = true;
+ continue;
+ }
+ if (arg == "-prep_bypass") {
+ prep_bypass_mode = true;
+ valid = true;
continue;
}
if (arg == "-prep_dff") {
prep_dff_mode = true;
+ valid = true;
+ continue;
+ }
+ if (arg == "-prep_dff_submod") {
+ prep_dff_submod_mode = true;
+ valid = true;
+ continue;
+ }
+ if (arg == "-prep_dff_unmap") {
+ prep_dff_unmap_mode = true;
+ valid = true;
continue;
}
if (arg == "-prep_xaiger") {
prep_xaiger_mode = true;
+ valid = true;
continue;
}
if (arg == "-prep_delays") {
prep_delays_mode = true;
+ valid = true;
continue;
}
if (arg == "-prep_lut" && argidx+1 < args.size()) {
prep_lut_mode = true;
maxlut = atoi(args[++argidx].c_str());
- continue;
- }
- if (arg == "-maxlut" && argidx+1 < args.size()) {
+ valid = true;
continue;
}
if (arg == "-write_lut" && argidx+1 < args.size()) {
write_lut_dst = args[++argidx];
rewrite_filename(write_lut_dst);
+ valid = true;
continue;
}
if (arg == "-prep_box") {
prep_box_mode = true;
+ valid = true;
continue;
}
if (arg == "-write_box" && argidx+1 < args.size()) {
write_box_dst = args[++argidx];
rewrite_filename(write_box_dst);
+ valid = true;
continue;
}
if (arg == "-reintegrate") {
reintegrate_mode = true;
+ valid = true;
continue;
}
if (arg == "-dff") {
@@ -1234,25 +1718,32 @@ struct Abc9OpsPass : public Pass {
}
extra_args(args, argidx, design);
- if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || prep_box_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode))
- log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
+ if (!valid)
+ log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
- if (dff_mode && !prep_delays_mode && !prep_xaiger_mode && !prep_box_mode)
- log_cmd_error("'-dff' option is only relevant for -prep_{delay,xaiger,box}.\n");
+ if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode)
+ log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n");
if (check_mode)
- check(design);
+ check(design, dff_mode);
+ if (prep_hier_mode)
+ prep_hier(design, dff_mode);
+ if (prep_bypass_mode)
+ prep_bypass(design);
+ if (prep_dff_mode)
+ prep_dff(design);
+ if (prep_dff_submod_mode)
+ prep_dff_submod(design);
+ if (prep_dff_unmap_mode)
+ prep_dff_unmap(design);
if (prep_delays_mode)
prep_delays(design, dff_mode);
if (prep_lut_mode)
prep_lut(design, maxlut);
if (prep_box_mode)
- prep_box(design, dff_mode);
+ prep_box(design);
for (auto mod : design->selected_modules()) {
- if (mod->get_bool_attribute(ID::abc9_holes))
- continue;
-
if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod));
continue;
@@ -1267,12 +1758,10 @@ struct Abc9OpsPass : public Pass {
write_box(mod, write_box_dst);
if (mark_scc_mode)
mark_scc(mod);
- if (prep_dff_mode)
- prep_dff(mod);
if (prep_xaiger_mode)
prep_xaiger(mod, dff_mode);
if (reintegrate_mode)
- reintegrate(mod);
+ reintegrate(mod, dff_mode);
}
}
} Abc9OpsPass;
diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc
index 2ecb2f35a..ce151c7f3 100644
--- a/passes/techmap/aigmap.cc
+++ b/passes/techmap/aigmap.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct AigmapPass : public Pass {
AigmapPass() : Pass("aigmap", "map logic to and-inverter-graph circuit") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -43,7 +43,7 @@ struct AigmapPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
bool nand_mode = false, select_mode = false;
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index 1925145d3..b16e9750e 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -550,7 +550,7 @@ struct AlumaccWorker
struct AlumaccPass : public Pass {
AlumaccPass() : Pass("alumacc", "extract ALU and MACC cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -560,7 +560,7 @@ struct AlumaccPass : public Pass {
log("and $macc cells.\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) override
{
log_header(design, "Executing ALUMACC pass (create $alu and $macc cells).\n");
diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc
index 5f30817d4..8643543c8 100644
--- a/passes/techmap/attrmap.cc
+++ b/passes/techmap/attrmap.cc
@@ -81,7 +81,7 @@ struct AttrmapAction {
struct AttrmapTocase : AttrmapAction {
string name;
- bool apply(IdString &id, Const&) YS_OVERRIDE {
+ bool apply(IdString &id, Const&) override {
if (match_name(name, id, true))
id = RTLIL::escape_id(name);
return true;
@@ -90,7 +90,7 @@ struct AttrmapTocase : AttrmapAction {
struct AttrmapRename : AttrmapAction {
string old_name, new_name;
- bool apply(IdString &id, Const&) YS_OVERRIDE {
+ bool apply(IdString &id, Const&) override {
if (match_name(old_name, id))
id = RTLIL::escape_id(new_name);
return true;
@@ -101,7 +101,7 @@ struct AttrmapMap : AttrmapAction {
bool imap;
string old_name, new_name;
string old_value, new_value;
- bool apply(IdString &id, Const &val) YS_OVERRIDE {
+ bool apply(IdString &id, Const &val) override {
if (match_name(old_name, id) && match_value(old_value, val, true)) {
id = RTLIL::escape_id(new_name);
val = make_value(new_value);
@@ -113,7 +113,7 @@ struct AttrmapMap : AttrmapAction {
struct AttrmapRemove : AttrmapAction {
bool has_value;
string name, value;
- bool apply(IdString &id, Const &val) YS_OVERRIDE {
+ bool apply(IdString &id, Const &val) override {
return !(match_name(name, id) && (!has_value || match_value(value, val)));
}
};
@@ -221,7 +221,7 @@ bool parse_attrmap_paramap_options(size_t &argidx, std::vector<std::string> &arg
struct AttrmapPass : public Pass {
AttrmapPass() : Pass("attrmap", "renaming attributes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -241,7 +241,7 @@ struct AttrmapPass : public Pass {
log(" -imap keep=\"false\" keep=0 -remove keep=0\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) override
{
log_header(design, "Executing ATTRMAP pass (move or copy attributes).\n");
@@ -301,7 +301,7 @@ struct AttrmapPass : public Pass {
struct ParamapPass : public Pass {
ParamapPass() : Pass("paramap", "renaming cell parameters") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -317,7 +317,7 @@ struct ParamapPass : public Pass {
log(" paramap -tocase INIT t:LUT4\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) override
{
log_header(design, "Executing PARAMAP pass (move or copy cell parameters).\n");
diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc
index e59aa6518..b3202c587 100644
--- a/passes/techmap/attrmvcp.cc
+++ b/passes/techmap/attrmvcp.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct AttrmvcpPass : public Pass {
AttrmvcpPass() : Pass("attrmvcp", "move or copy attributes from wires to driving cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" attrmvcp [options] [selection]\n");
@@ -53,7 +53,7 @@ struct AttrmvcpPass : public Pass {
log(" multiple times.\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) override
{
log_header(design, "Executing ATTRMVCP pass (move or copy attributes).\n");
diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc
index 3f4b6aa66..451325fee 100644
--- a/passes/techmap/clkbufmap.cc
+++ b/passes/techmap/clkbufmap.cc
@@ -35,7 +35,7 @@ void split_portname_pair(std::string &port1, std::string &port2)
struct ClkbufmapPass : public Pass {
ClkbufmapPass() : Pass("clkbufmap", "insert global buffers on clock networks") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -76,7 +76,7 @@ struct ClkbufmapPass : public Pass {
modules_processed.insert(module);
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing CLKBUFMAP pass (inserting global clock buffers).\n");
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index a7dce9c81..9a23cb90e 100644
--- a/passes/techmap/deminout.cc
+++ b/passes/techmap/deminout.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct DeminoutPass : public Pass {
DeminoutPass() : Pass("deminout", "demote inout ports to input or output") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" deminout [options] [selection]\n");
@@ -33,7 +33,7 @@ struct DeminoutPass : public Pass {
log("\"Demote\" inout ports to input or output ports, if possible.\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) override
{
log_header(design, "Executing DEMINOUT pass (demote inout ports to input or output).\n");
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
index aa9bbfe17..62ee3fea6 100644
--- a/passes/techmap/dff2dffe.cc
+++ b/passes/techmap/dff2dffe.cc
@@ -253,7 +253,7 @@ struct Dff2dffeWorker
struct Dff2dffePass : public Pass {
Dff2dffePass() : Pass("dff2dffe", "transform $dff cells to $dffe cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -282,13 +282,13 @@ struct Dff2dffePass : public Pass {
log("\n");
log(" -direct-match <pattern>\n");
log(" like -direct for all DFF cell types matching the expression.\n");
- log(" this will use $__DFFE_* as <external_gate_type> matching the\n");
- log(" internal gate type $_DFF_*_, and $__DFFSE_* for those matching\n");
- log(" $_DFFS_*_, except for $_DFF_[NP]_, which is converted to \n");
+ log(" this will use $_DFFE_* as <external_gate_type> matching the\n");
+ log(" internal gate type $_DFF_*_, and $_SDFFE_* for those matching\n");
+ log(" $_SDFF_*_, except for $_DFF_[NP]_, which is converted to \n");
log(" $_DFFE_[NP]_.\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) override
{
log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
@@ -318,23 +318,23 @@ struct Dff2dffePass : public Pass {
const char *pattern = args[++argidx].c_str();
if (patmatch(pattern, "$_DFF_P_" )) found_match = true, direct_dict[ID($_DFF_P_) ] = ID($_DFFE_PP_);
if (patmatch(pattern, "$_DFF_N_" )) found_match = true, direct_dict[ID($_DFF_N_) ] = ID($_DFFE_NP_);
- if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($__DFFE_NN0);
- if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($__DFFE_NN1);
- if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($__DFFE_NP0);
- if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($__DFFE_NP1);
- if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($__DFFE_PN0);
- if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($__DFFE_PN1);
- if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($__DFFE_PP0);
- if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($__DFFE_PP1);
-
- if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict[ID($__DFFS_NN0_)] = ID($__DFFSE_NN0);
- if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict[ID($__DFFS_NN1_)] = ID($__DFFSE_NN1);
- if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict[ID($__DFFS_NP0_)] = ID($__DFFSE_NP0);
- if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict[ID($__DFFS_NP1_)] = ID($__DFFSE_NP1);
- if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict[ID($__DFFS_PN0_)] = ID($__DFFSE_PN0);
- if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict[ID($__DFFS_PN1_)] = ID($__DFFSE_PN1);
- if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict[ID($__DFFS_PP0_)] = ID($__DFFSE_PP0);
- if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict[ID($__DFFS_PP1_)] = ID($__DFFSE_PP1);
+ if (patmatch(pattern, "$_DFF_NN0_")) found_match = true, direct_dict[ID($_DFF_NN0_)] = ID($_DFFE_NN0P_);
+ if (patmatch(pattern, "$_DFF_NN1_")) found_match = true, direct_dict[ID($_DFF_NN1_)] = ID($_DFFE_NN1P_);
+ if (patmatch(pattern, "$_DFF_NP0_")) found_match = true, direct_dict[ID($_DFF_NP0_)] = ID($_DFFE_NP0P_);
+ if (patmatch(pattern, "$_DFF_NP1_")) found_match = true, direct_dict[ID($_DFF_NP1_)] = ID($_DFFE_NP1P_);
+ if (patmatch(pattern, "$_DFF_PN0_")) found_match = true, direct_dict[ID($_DFF_PN0_)] = ID($_DFFE_PN0P_);
+ if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict[ID($_DFF_PN1_)] = ID($_DFFE_PN1P_);
+ if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict[ID($_DFF_PP0_)] = ID($_DFFE_PP0P_);
+ if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict[ID($_DFF_PP1_)] = ID($_DFFE_PP1P_);
+
+ if (patmatch(pattern, "$_SDFF_NN0_")) found_match = true, direct_dict[ID($_SDFF_NN0_)] = ID($_SDFFE_NN0P_);
+ if (patmatch(pattern, "$_SDFF_NN1_")) found_match = true, direct_dict[ID($_SDFF_NN1_)] = ID($_SDFFE_NN1P_);
+ if (patmatch(pattern, "$_SDFF_NP0_")) found_match = true, direct_dict[ID($_SDFF_NP0_)] = ID($_SDFFE_NP0P_);
+ if (patmatch(pattern, "$_SDFF_NP1_")) found_match = true, direct_dict[ID($_SDFF_NP1_)] = ID($_SDFFE_NP1P_);
+ if (patmatch(pattern, "$_SDFF_PN0_")) found_match = true, direct_dict[ID($_SDFF_PN0_)] = ID($_SDFFE_PN0P_);
+ if (patmatch(pattern, "$_SDFF_PN1_")) found_match = true, direct_dict[ID($_SDFF_PN1_)] = ID($_SDFFE_PN1P_);
+ if (patmatch(pattern, "$_SDFF_PP0_")) found_match = true, direct_dict[ID($_SDFF_PP0_)] = ID($_SDFFE_PP0P_);
+ if (patmatch(pattern, "$_SDFF_PP1_")) found_match = true, direct_dict[ID($_SDFF_PP1_)] = ID($_SDFFE_PP1P_);
if (!found_match)
log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
continue;
diff --git a/passes/techmap/dff2dffs.cc b/passes/techmap/dff2dffs.cc
index c155297d9..6c2cca4bc 100644
--- a/passes/techmap/dff2dffs.cc
+++ b/passes/techmap/dff2dffs.cc
@@ -26,12 +26,12 @@ PRIVATE_NAMESPACE_BEGIN
struct Dff2dffsPass : public Pass {
Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" dff2dffs [options] [selection]\n");
log("\n");
- log("Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before\n");
+ log("Merge synchronous set/reset $_MUX_ cells to create $_SDFF_[NP][NP][01]_, to be run before\n");
log("dff2dffe for SR over CE priority.\n");
log("\n");
log(" -match-init\n");
@@ -39,7 +39,7 @@ struct Dff2dffsPass : public Pass {
log(" output wire's init attribute (if any).\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) override
{
log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
@@ -138,21 +138,21 @@ struct Dff2dffsPass : public Pass {
if (sr_val == State::S1) {
if (cell->type == ID($_DFF_N_)) {
- if (invert_sr) cell->type = ID($__DFFS_NN1_);
- else cell->type = ID($__DFFS_NP1_);
+ if (invert_sr) cell->type = ID($_SDFF_NN1_);
+ else cell->type = ID($_SDFF_NP1_);
} else {
log_assert(cell->type == ID($_DFF_P_));
- if (invert_sr) cell->type = ID($__DFFS_PN1_);
- else cell->type = ID($__DFFS_PP1_);
+ if (invert_sr) cell->type = ID($_SDFF_PN1_);
+ else cell->type = ID($_SDFF_PP1_);
}
} else {
if (cell->type == ID($_DFF_N_)) {
- if (invert_sr) cell->type = ID($__DFFS_NN0_);
- else cell->type = ID($__DFFS_NP0_);
+ if (invert_sr) cell->type = ID($_SDFF_NN0_);
+ else cell->type = ID($_SDFF_NP0_);
} else {
log_assert(cell->type == ID($_DFF_P_));
- if (invert_sr) cell->type = ID($__DFFS_PN0_);
- else cell->type = ID($__DFFS_PP0_);
+ if (invert_sr) cell->type = ID($_SDFF_PN0_);
+ else cell->type = ID($_SDFF_PP0_);
}
}
cell->setPort(ID::R, sr_sig);
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index 35645582b..c60a901c1 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct DffinitPass : public Pass {
DffinitPass() : Pass("dffinit", "set INIT param on FF cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -54,7 +54,7 @@ struct DffinitPass : public Pass {
log(" the already defined initial 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) override
{
log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n");
diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc
new file mode 100644
index 000000000..013f2d974
--- /dev/null
+++ b/passes/techmap/dfflegalize.cc
@@ -0,0 +1,1356 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+enum FfType {
+ FF_DFF,
+ FF_DFFE,
+ FF_ADFF0,
+ FF_ADFF1,
+ FF_ADFFE0,
+ FF_ADFFE1,
+ FF_DFFSR,
+ FF_DFFSRE,
+ FF_SDFF0,
+ FF_SDFF1,
+ FF_SDFFE0,
+ FF_SDFFE1,
+ FF_SDFFCE0,
+ FF_SDFFCE1,
+ FF_SR,
+ FF_DLATCH,
+ FF_ADLATCH0,
+ FF_ADLATCH1,
+ FF_DLATCHSR,
+ NUM_FFTYPES,
+};
+
+enum FfNeg {
+ NEG_R = 0x1,
+ NEG_S = 0x2,
+ NEG_E = 0x4,
+ NEG_C = 0x8,
+ NUM_NEG = 0x10,
+};
+
+enum FfInit {
+ INIT_X = 0x1,
+ INIT_0 = 0x2,
+ INIT_1 = 0x4,
+};
+
+struct DffLegalizePass : public Pass {
+ DffLegalizePass() : Pass("dfflegalize", "convert FFs to types supported by the target") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" dfflegalize [options] [selection]\n");
+ log("\n");
+ log("Converts FFs to types supported by the target.\n");
+ log("\n");
+ log(" -cell <cell_type_pattern> <init_values>\n");
+ log(" specifies a supported group of FF cells. <cell_type_pattern>\n");
+ log(" is a yosys internal fine cell name, where ? characters can be\n");
+ log(" as a wildcard matching any character. <init_values> specifies\n");
+ log(" which initialization values these FF cells can support, and can\n");
+ log(" be one of:\n");
+ log("\n");
+ log(" - x (no init value supported)\n");
+ log(" - 0\n");
+ log(" - 1\n");
+ log(" - r (init value has to match reset value, only for some FF types)\n");
+ log(" - 01 (both 0 and 1 supported).\n");
+ log("\n");
+ log(" -mince <num>\n");
+ log(" specifies a minimum number of FFs that should be using any given\n");
+ log(" clock enable signal. If a clock enable signal doesn't meet this\n");
+ log(" threshold, it is unmapped into soft logic.\n");
+ log("\n");
+ log(" -minsrst <num>\n");
+ log(" specifies a minimum number of FFs that should be using any given\n");
+ log(" sync set/reset signal. If a sync set/reset signal doesn't meet this\n");
+ log(" threshold, it is unmapped into soft logic.\n");
+ log("\n");
+ log("The following cells are supported by this pass (ie. will be ingested,\n");
+ log("and can be specified as allowed targets):\n");
+ log("\n");
+ log("- $_DFF_[NP]_\n");
+ log("- $_DFFE_[NP][NP]_\n");
+ log("- $_DFF_[NP][NP][01]_\n");
+ log("- $_DFFE_[NP][NP][01][NP]_\n");
+ log("- $_DFFSR_[NP][NP][NP]_\n");
+ log("- $_DFFSRE_[NP][NP][NP][NP]_\n");
+ log("- $_SDFF_[NP][NP][01]_\n");
+ log("- $_SDFFE_[NP][NP][01][NP]_\n");
+ log("- $_SDFFCE_[NP][NP][01][NP]_\n");
+ log("- $_SR_[NP][NP]_\n");
+ log("- $_DLATCH_[NP]_\n");
+ log("- $_DLATCH_[NP][NP][01]_\n");
+ log("- $_DLATCHSR_[NP][NP][NP]_\n");
+ log("\n");
+ log("The following transformations are performed by this pass:");
+ log("");
+ log("- upconversion from a less capable cell to a more capable cell, if the less");
+ log(" capable cell is not supported (eg. dff -> dffe, or adff -> dffsr)");
+ log("");
+ log("- unmapping FFs with clock enable (due to unsupported cell type or -mince)");
+ log("");
+ log("- unmapping FFs with sync reset (due to unsupported cell type or -minsrst)");
+ log("");
+ log("- adding inverters on the control pins (due to unsupported polarity)");
+ log("");
+ log("- adding inverters on the D and Q pins and inverting the init/reset values\n");
+ log(" (due to unsupported init or reset value)");
+ log("");
+ log("- converting sr into adlatch (by tying D to 1 and using E as set input)");
+ log("");
+ log("- emulating unsupported dffsr cell by adff + adff + sr + mux");
+ log("");
+ log("- emulating unsupported dlatchsr cell by adlatch + adlatch + sr + mux");
+ log("");
+ log("- emulating adff when the (reset, init) value combination is unsupported by\n");
+ log(" dff + adff + dlatch + mux");
+ log("");
+ log("- emulating adlatch when the (reset, init) value combination is unsupported by\n");
+ log("- dlatch + adlatch + dlatch + mux");
+ log("");
+ log("If the pass is unable to realize a given cell type (eg. adff when only plain dff");
+ log("is available), an error is raised.");
+ }
+
+ // Table of all supported cell types.
+ // First index in the array is one of the FF_* values, second
+ // index is the set of negative-polarity inputs (OR of NEG_*
+ // values), and the value is the set of supported init values
+ // (OR of INIT_* values).
+ int supported_cells_neg[NUM_FFTYPES][NUM_NEG];
+ // Aggregated table ignoring signal polarity.
+ int supported_cells[NUM_FFTYPES];
+ // Aggregated for all *dff* cells.
+ int supported_dff;
+ // Aggregated for all dffsr* cells.
+ int supported_dffsr;
+ // Aggregated for all adff* cells.
+ int supported_adff0;
+ int supported_adff1;
+ // Aggregated for all sdff* cells.
+ int supported_sdff0;
+ int supported_sdff1;
+ // Aggregated for all ways to obtain a SR latch.
+ int supported_sr;
+ // Aggregated for all *dlatch* cells.
+ int supported_dlatch;
+
+ int mince;
+ int minsrst;
+
+ dict<SigBit, int> ce_used;
+ dict<SigBit, int> srst_used;
+
+ SigMap sigmap;
+ dict<SigBit, std::pair<State,SigBit>> initbits;
+
+ int flip_initmask(int mask) {
+ int res = mask & INIT_X;
+ if (mask & INIT_0)
+ res |= INIT_1;
+ if (mask & INIT_1)
+ res |= INIT_0;
+ return res;
+ }
+
+ void handle_ff(Cell *cell) {
+ std::string type_str = cell->type.str();
+
+ FfType ff_type;
+ int ff_neg = 0;
+ SigSpec sig_d;
+ SigSpec sig_q;
+ SigSpec sig_c;
+ SigSpec sig_e;
+ SigSpec sig_r;
+ SigSpec sig_s;
+ bool has_srst = false;
+
+ if (cell->hasPort(ID::D))
+ sig_d = cell->getPort(ID::D);
+ if (cell->hasPort(ID::Q))
+ sig_q = cell->getPort(ID::Q);
+ if (cell->hasPort(ID::C))
+ sig_c = cell->getPort(ID::C);
+ if (cell->hasPort(ID::E))
+ sig_e = cell->getPort(ID::E);
+ if (cell->hasPort(ID::R))
+ sig_r = cell->getPort(ID::R);
+ if (cell->hasPort(ID::S))
+ sig_s = cell->getPort(ID::S);
+
+ if (type_str.substr(0, 5) == "$_SR_") {
+ ff_type = FF_SR;
+ if (type_str[5] == 'N')
+ ff_neg |= NEG_S;
+ if (type_str[6] == 'N')
+ ff_neg |= NEG_R;
+ } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
+ ff_type = FF_DFF;
+ if (type_str[6] == 'N')
+ ff_neg |= NEG_C;
+ } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
+ ff_type = FF_DFFE;
+ if (type_str[7] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[8] == 'N')
+ ff_neg |= NEG_E;
+ } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
+ ff_type = type_str[8] == '1' ? FF_ADFF1 : FF_ADFF0;
+ if (type_str[6] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[7] == 'N')
+ ff_neg |= NEG_R;
+ } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
+ ff_type = type_str[9] == '1' ? FF_ADFFE1 : FF_ADFFE0;
+ if (type_str[7] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[8] == 'N')
+ ff_neg |= NEG_R;
+ if (type_str[10] == 'N')
+ ff_neg |= NEG_E;
+ } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
+ ff_type = FF_DFFSR;
+ if (type_str[8] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[9] == 'N')
+ ff_neg |= NEG_S;
+ if (type_str[10] == 'N')
+ ff_neg |= NEG_R;
+ } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
+ ff_type = FF_DFFSRE;
+ if (type_str[9] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[10] == 'N')
+ ff_neg |= NEG_S;
+ if (type_str[11] == 'N')
+ ff_neg |= NEG_R;
+ if (type_str[12] == 'N')
+ ff_neg |= NEG_E;
+ } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
+ ff_type = type_str[9] == '1' ? FF_SDFF1 : FF_SDFF0;
+ if (type_str[7] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[8] == 'N')
+ ff_neg |= NEG_R;
+ has_srst = true;
+ } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
+ ff_type = type_str[10] == '1' ? FF_SDFFE1 : FF_SDFFE0;
+ if (type_str[8] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[9] == 'N')
+ ff_neg |= NEG_R;
+ if (type_str[11] == 'N')
+ ff_neg |= NEG_E;
+ has_srst = true;
+ } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
+ ff_type = type_str[11] == '1' ? FF_SDFFCE1 : FF_SDFFCE0;
+ if (type_str[9] == 'N')
+ ff_neg |= NEG_C;
+ if (type_str[10] == 'N')
+ ff_neg |= NEG_R;
+ if (type_str[12] == 'N')
+ ff_neg |= NEG_E;
+ has_srst = true;
+ } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
+ ff_type = FF_DLATCH;
+ if (type_str[9] == 'N')
+ ff_neg |= NEG_E;
+ } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
+ ff_type = type_str[11] == '1' ? FF_ADLATCH1 : FF_ADLATCH0;
+ if (type_str[9] == 'N')
+ ff_neg |= NEG_E;
+ if (type_str[10] == 'N')
+ ff_neg |= NEG_R;
+ } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
+ ff_type = FF_DLATCHSR;
+ if (type_str[11] == 'N')
+ ff_neg |= NEG_E;
+ if (type_str[12] == 'N')
+ ff_neg |= NEG_S;
+ if (type_str[13] == 'N')
+ ff_neg |= NEG_R;
+ } else {
+ log_warning("Ignoring unknown ff type %s [%s.%s].\n", log_id(cell->type), log_id(cell->module->name), log_id(cell->name));
+ return;
+ }
+
+ State initval = State::Sx;
+ SigBit initbit;
+ if (GetSize(sig_q) > 0 && initbits.count(sigmap(sig_q[0]))) {
+ const auto &d = initbits.at(sigmap(sig_q[0]));
+ initval = d.first;
+ initbit = d.second;
+ }
+
+ FfInit initmask = INIT_X;
+ if (initval == State::S0)
+ initmask = INIT_0;
+ else if (initval == State::S1)
+ initmask = INIT_1;
+ const char *reason;
+
+ bool kill_ce = mince && GetSize(sig_c) && GetSize(sig_e) && sig_e[0].wire && ce_used[sig_e[0]] < mince;
+ bool kill_srst = minsrst && has_srst && sig_r[0].wire && srst_used[sig_r[0]] < minsrst;
+
+ while (!(supported_cells[ff_type] & initmask) || kill_ce || kill_srst) {
+ // Well, cell is not directly supported. Decide how to deal with it.
+
+ if (ff_type == FF_DFF || ff_type == FF_DFFE) {
+ if (kill_ce) {
+ ff_type = FF_DFF;
+ goto unmap_enable;
+ }
+ if (!(supported_dff & initmask)) {
+ // This init value is not supported at all...
+ if (supported_dff & flip_initmask(initmask)) {
+ // The other one is, though. Negate D, Q, and init.
+flip_dqi:
+ if (initval == State::S0) {
+ initval = State::S1;
+ initmask = INIT_1;
+ } else if (initval == State::S1) {
+ initval = State::S0;
+ initmask = INIT_0;
+ }
+ if (ff_type != FF_SR)
+ sig_d = cell->module->NotGate(NEW_ID, sig_d[0]);
+ SigBit new_q = SigSpec(cell->module->addWire(NEW_ID))[0];
+ cell->module->addNotGate(NEW_ID, new_q, sig_q[0]);
+ if (initbit.wire) {
+ initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ initbit = new_q;
+ new_q.wire->attributes[ID::init] = initval;
+ initbits[new_q] = std::make_pair(initval, new_q);
+ }
+ sig_q = new_q;
+ continue;
+ }
+ if (!supported_dff)
+ reason = "dffs are not supported";
+ else
+ reason = "initialized dffs are not supported";
+ goto error;
+ }
+
+ // Some DFF is supported with this init val. Just pick a type.
+ if (ff_type == FF_DFF) {
+ // Try adding a set or reset pin.
+ for (auto new_type: {FF_ADFF0, FF_ADFF1, FF_SDFF0, FF_SDFF1})
+ if (supported_cells[new_type] & initmask) {
+ ff_type = new_type;
+ sig_r = State::S0;
+ goto cell_ok;
+ }
+ // Try adding both.
+ if (supported_cells[FF_DFFSR] & initmask) {
+ ff_type = FF_DFFSR;
+ sig_r = State::S0;
+ sig_s = State::S0;
+ break;
+ }
+ // Nope. Will need to add enable and go the DFFE route.
+ sig_e = State::S1;
+ if (supported_cells[FF_DFFE] & initmask) {
+ ff_type = FF_DFFE;
+ break;
+ }
+ }
+ // Try adding a set or reset pin.
+ for (auto new_type: {FF_SDFFE0, FF_SDFFE1, FF_SDFFCE0, FF_SDFFCE1, FF_ADFFE0, FF_ADFFE1})
+ if (supported_cells[new_type] & initmask) {
+ ff_type = new_type;
+ sig_r = State::S0;
+ goto cell_ok;
+ }
+ // Try adding both.
+ if (supported_cells[FF_DFFSRE] & initmask) {
+ ff_type = FF_DFFSRE;
+ sig_r = State::S0;
+ sig_s = State::S0;
+ break;
+ }
+
+ // Seems that no DFFs with enable are supported.
+ // The enable input needs to be unmapped.
+ // This should not be reached if we started from plain DFF.
+ log_assert(ff_type == FF_DFFE);
+ ff_type = FF_DFF;
+unmap_enable:
+ if (ff_neg & NEG_E)
+ sig_d = cell->module->MuxGate(NEW_ID, sig_d[0], sig_q[0], sig_e[0]);
+ else
+ sig_d = cell->module->MuxGate(NEW_ID, sig_q[0], sig_d[0], sig_e[0]);
+ ff_neg &= ~NEG_E;
+ sig_e = SigSpec();
+ kill_ce = false;
+ // Now try again as plain DFF.
+ continue;
+ } else if (ff_type == FF_ADFF0 || ff_type == FF_ADFF1 || ff_type == FF_ADFFE0 || ff_type == FF_ADFFE1) {
+ bool has_set = ff_type == FF_ADFF1 || ff_type == FF_ADFFE1;
+ bool has_en = ff_type == FF_ADFFE0 || ff_type == FF_ADFFE1;
+ if (kill_ce) {
+ ff_type = has_set ? FF_ADFF1 : FF_ADFF0;
+ goto unmap_enable;
+ }
+ if (!has_en && (supported_cells[has_set ? FF_ADFFE1 : FF_ADFFE0] & initmask)) {
+ // Just add enable.
+ sig_e = State::S1;
+ ff_type = has_set ? FF_ADFFE1 : FF_ADFFE0;
+ break;
+ }
+ if (supported_dffsr & initmask) {
+ // Throw in a set/reset, retry in DFFSR/DFFSRE branch.
+ if (has_set) {
+ sig_s = sig_r;
+ sig_r = State::S0;
+ if (ff_neg & NEG_R) {
+ ff_neg &= ~NEG_R;
+ ff_neg |= NEG_S;
+ }
+ } else {
+ sig_s = State::S0;
+ }
+ if (has_en)
+ ff_type = FF_DFFSRE;
+ else
+ ff_type = FF_DFFSR;
+ continue;
+ }
+ if (has_en && (supported_cells[has_set ? FF_ADFF1 : FF_ADFF0] & initmask)) {
+ // Unmap enable.
+ ff_type = has_set ? FF_ADFF1 : FF_ADFF0;
+ goto unmap_enable;
+ }
+ log_assert(!((has_set ? supported_adff1 : supported_adff0) & initmask));
+ // Alright, so this particular combination of initval and
+ // resetval is not natively supported. First, try flipping
+ // them both to see whether this helps.
+ int flipmask = flip_initmask(initmask);
+ if ((has_set ? supported_adff0 : supported_adff1) & flipmask) {
+ // Checks out, do it.
+ ff_type = has_en ? (has_set ? FF_ADFFE0 : FF_ADFFE1) : (has_set ? FF_ADFF0 : FF_ADFF1);
+ goto flip_dqi;
+ }
+
+ if (!supported_adff0 && !supported_adff1) {
+ reason = "dffs with async set or reset are not supported";
+ goto error;
+ }
+ if (!(supported_dff & ~INIT_X)) {
+ reason = "initialized dffs are not supported";
+ goto error;
+ }
+ // If we got here, initialized dff is supported, but not this
+ // particular reset+init combination (nor its negation).
+ // The only hope left is breaking down to adff + dff + dlatch + mux.
+ if (!(supported_dlatch & ~INIT_X)) {
+ reason = "unsupported initial value and async reset value combination";
+ goto error;
+ }
+
+ // If we have to unmap enable anyway, do it before breakdown.
+ if (has_en && !supported_cells[FF_ADFFE0] && !supported_cells[FF_ADFFE1]) {
+ ff_type = has_set ? FF_ADFF1 : FF_ADFF0;
+ goto unmap_enable;
+ }
+
+ log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
+ if (initbit.wire)
+ initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ Wire *adff_q = cell->module->addWire(NEW_ID);
+ Wire *dff_q = cell->module->addWire(NEW_ID);
+ Wire *sel_q = cell->module->addWire(NEW_ID);
+ dff_q->attributes[ID::init] = initval;
+ initbits[SigBit(dff_q, 0)] = std::make_pair(initval, SigBit(dff_q, 0));
+ sel_q->attributes[ID::init] = State::S0;
+ initbits[SigBit(sel_q, 0)] = std::make_pair(State::S0, SigBit(sel_q, 0));
+ Cell *cell_dff;
+ Cell *cell_adff;
+ Cell *cell_sel;
+ if (!has_en) {
+ cell_dff = cell->module->addDffGate(NEW_ID, sig_c, sig_d, dff_q, !(ff_neg & NEG_C));
+ cell_adff = cell->module->addAdffGate(NEW_ID, sig_c, sig_r, sig_d, adff_q, has_set, !(ff_neg & NEG_C), !(ff_neg & NEG_R));
+ } else {
+ cell_dff = cell->module->addDffeGate(NEW_ID, sig_c, sig_e, sig_d, dff_q, !(ff_neg & NEG_C), !(ff_neg & NEG_E));
+ cell_adff = cell->module->addAdffeGate(NEW_ID, sig_c, sig_e, sig_r, sig_d, adff_q, has_set, !(ff_neg & NEG_C), !(ff_neg & NEG_E), !(ff_neg & NEG_R));
+ }
+ cell_sel = cell->module->addDlatchGate(NEW_ID, sig_r, State::S1, sel_q, !(ff_neg & NEG_R));
+ cell->module->addMuxGate(NEW_ID, dff_q, adff_q, sel_q, sig_q);
+
+ // Bye, cell.
+ cell->module->remove(cell);
+ handle_ff(cell_dff);
+ handle_ff(cell_adff);
+ handle_ff(cell_sel);
+ return;
+ } else if (ff_type == FF_DFFSR || ff_type == FF_DFFSRE) {
+ if (kill_ce) {
+ ff_type = FF_DFFSR;
+ goto unmap_enable;
+ }
+ // First, see if mapping/unmapping enable will help.
+ if (supported_cells[FF_DFFSRE] & initmask) {
+ ff_type = FF_DFFSRE;
+ sig_e = State::S1;
+ break;
+ }
+ if (supported_cells[FF_DFFSR] & initmask) {
+ ff_type = FF_DFFSR;
+ goto unmap_enable;
+ }
+ if (supported_dffsr & flip_initmask(initmask)) {
+flip_dqisr:;
+ log_warning("Flipping D/Q/init and inseerting set/reset fixup to handle init value on %s.%s [%s]\n", log_id(cell->module->name), log_id(cell->name), log_id(cell->type));
+ SigSpec new_r;
+ bool neg_r = (ff_neg & NEG_R);
+ bool neg_s = (ff_neg & NEG_S);
+ if (!(ff_neg & NEG_S)) {
+ if (!(ff_neg & NEG_R))
+ new_r = cell->module->AndnotGate(NEW_ID, sig_s, sig_r);
+ else
+ new_r = cell->module->AndGate(NEW_ID, sig_s, sig_r);
+ } else {
+ if (!(ff_neg & NEG_R))
+ new_r = cell->module->OrGate(NEW_ID, sig_s, sig_r);
+ else
+ new_r = cell->module->OrnotGate(NEW_ID, sig_s, sig_r);
+ }
+ ff_neg &= ~(NEG_R | NEG_S);
+ if (neg_r)
+ ff_neg |= NEG_S;
+ if (neg_s)
+ ff_neg |= NEG_R;
+ sig_s = sig_r;
+ sig_r = new_r;
+ goto flip_dqi;
+ }
+ // No native DFFSR. However, if we can conjure
+ // a SR latch and ADFF, it can still be emulated.
+ int flipmask = flip_initmask(initmask);
+ bool init0 = true;
+ bool init1 = true;
+ State initsel = State::Sx;
+ if (((supported_adff0 & initmask) || (supported_adff1 & flipmask)) && ((supported_adff1 & initmask) || (supported_adff0 & flipmask)) && supported_sr) {
+ // OK
+ } else if (((supported_adff0 & initmask) || (supported_adff1 & flipmask)) && (supported_sr & INIT_0)) {
+ init1 = false;
+ initsel = State::S0;
+ } else if (((supported_adff1 & initmask) || (supported_adff0 & flipmask)) && (supported_sr & INIT_1)) {
+ init0 = false;
+ initsel = State::S1;
+ } else if (((supported_adff0 & initmask) || (supported_adff1 & flipmask)) && (supported_sr & INIT_1)) {
+ init1 = false;
+ initsel = State::S0;
+ } else if (((supported_adff1 & initmask) || (supported_adff0 & flipmask)) && (supported_sr & INIT_0)) {
+ init0 = false;
+ initsel = State::S1;
+ } else {
+ if (!supported_dffsr)
+ reason = "dffs with async set and reset are not supported";
+ else
+ reason = "initialized dffs with async set and reset are not supported";
+ goto error;
+ }
+
+ // If we have to unmap enable anyway, do it before breakdown.
+ if (ff_type == FF_DFFSRE && !supported_cells[FF_ADFFE0] && !supported_cells[FF_ADFFE1]) {
+ ff_type = FF_DFFSR;
+ goto unmap_enable;
+ }
+
+ log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
+ if (initbit.wire)
+ initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ Wire *adff0_q = cell->module->addWire(NEW_ID);
+ Wire *adff1_q = cell->module->addWire(NEW_ID);
+ Wire *sel_q = cell->module->addWire(NEW_ID);
+ if (init0) {
+ adff0_q->attributes[ID::init] = initval;
+ initbits[SigBit(adff0_q, 0)] = std::make_pair(initval, SigBit(adff0_q, 0));
+ }
+ if (init1) {
+ adff1_q->attributes[ID::init] = initval;
+ initbits[SigBit(adff1_q, 0)] = std::make_pair(initval, SigBit(adff1_q, 0));
+ }
+ sel_q->attributes[ID::init] = initsel;
+ initbits[SigBit(sel_q, 0)] = std::make_pair(initsel, SigBit(sel_q, 0));
+ Cell *cell_adff0;
+ Cell *cell_adff1;
+ Cell *cell_sel;
+ if (ff_type == FF_DFFSR) {
+ cell_adff0 = cell->module->addAdffGate(NEW_ID, sig_c, sig_r, sig_d, adff0_q, false, !(ff_neg & NEG_C), !(ff_neg & NEG_R));
+ cell_adff1 = cell->module->addAdffGate(NEW_ID, sig_c, sig_s, sig_d, adff1_q, true, !(ff_neg & NEG_C), !(ff_neg & NEG_S));
+ } else {
+ cell_adff0 = cell->module->addAdffeGate(NEW_ID, sig_c, sig_e, sig_r, sig_d, adff0_q, false, !(ff_neg & NEG_C), !(ff_neg & NEG_E), !(ff_neg & NEG_R));
+ cell_adff1 = cell->module->addAdffeGate(NEW_ID, sig_c, sig_e, sig_s, sig_d, adff1_q, true, !(ff_neg & NEG_C), !(ff_neg & NEG_E), !(ff_neg & NEG_S));
+ }
+ cell_sel = cell->module->addSrGate(NEW_ID, sig_s, sig_r, sel_q, !(ff_neg & NEG_S), !(ff_neg & NEG_R));
+ cell->module->addMuxGate(NEW_ID, adff0_q, adff1_q, sel_q, sig_q);
+
+ // Bye, cell.
+ cell->module->remove(cell);
+ handle_ff(cell_adff0);
+ handle_ff(cell_adff1);
+ handle_ff(cell_sel);
+ return;
+ } else if (ff_type == FF_SR) {
+ if (supported_cells[FF_ADLATCH0] & initmask || supported_cells[FF_ADLATCH1] & flip_initmask(initmask)) {
+ // Convert to ADLATCH0. May get converted to ADLATCH1.
+ ff_type = FF_ADLATCH0;
+ sig_e = sig_s;
+ sig_d = State::S1;
+ if (ff_neg & NEG_S) {
+ ff_neg &= ~NEG_S;
+ ff_neg |= NEG_E;
+ }
+ continue;
+ } else if (supported_cells[FF_DLATCHSR] & initmask) {
+ // Upgrade to DLATCHSR.
+ ff_type = FF_DLATCHSR;
+ sig_e = State::S0;
+ sig_d = State::Sx;
+ break;
+ } else if (supported_dffsr & initmask) {
+ // Upgrade to DFFSR. May get further upgraded to DFFSRE.
+ ff_type = FF_DFFSR;
+ sig_c = State::S0;
+ sig_d = State::Sx;
+ continue;
+ } else if (supported_sr & flip_initmask(initmask)) {
+ goto flip_dqisr;
+ } else {
+ if (!supported_sr)
+ reason = "sr latches are not supported";
+ else
+ reason = "initialized sr latches are not supported";
+ goto error;
+ }
+ } else if (ff_type == FF_DLATCH) {
+ if (!(supported_dlatch & initmask)) {
+ // This init value is not supported at all...
+ if (supported_dlatch & flip_initmask(initmask))
+ goto flip_dqi;
+ if (!supported_dlatch)
+ reason = "dlatch are not supported";
+ else
+ reason = "initialized dlatch are not supported";
+ goto error;
+ }
+
+ // Some DLATCH is supported with this init val. Just pick a type.
+ if (supported_cells[FF_ADLATCH0] & initmask) {
+ ff_type = FF_ADLATCH0;
+ sig_r = State::S0;
+ break;
+ }
+ if (supported_cells[FF_ADLATCH1] & initmask) {
+ ff_type = FF_ADLATCH1;
+ sig_r = State::S0;
+ break;
+ }
+ if (supported_cells[FF_DLATCHSR] & initmask) {
+ ff_type = FF_DLATCHSR;
+ sig_r = State::S0;
+ sig_s = State::S0;
+ break;
+ }
+ log_assert(0);
+ } else if (ff_type == FF_ADLATCH0 || ff_type == FF_ADLATCH1) {
+ if (supported_cells[FF_DLATCHSR] & initmask) {
+ if (ff_type == FF_ADLATCH1) {
+ sig_s = sig_r;
+ sig_r = State::S0;
+ if (ff_neg & NEG_R) {
+ ff_neg &= ~NEG_R;
+ ff_neg |= NEG_S;
+ }
+ } else {
+ sig_s = State::S0;
+ }
+ ff_type = FF_DLATCHSR;
+ break;
+ }
+ FfType flip_type = ff_type == FF_ADLATCH0 ? FF_ADLATCH1 : FF_ADLATCH0;
+ if ((supported_cells[flip_type] | supported_cells[FF_DLATCHSR]) & flip_initmask(initmask)) {
+ ff_type = flip_type;
+ goto flip_dqi;
+ }
+
+ if (!supported_cells[FF_ADLATCH0] && !supported_cells[FF_ADLATCH1] && !supported_cells[FF_DLATCHSR]) {
+ reason = "dlatch with async set or reset are not supported";
+ goto error;
+ }
+ if (!(supported_dlatch & ~INIT_X)) {
+ reason = "initialized dlatch are not supported";
+ goto error;
+ }
+
+ if (!(supported_dlatch & ~INIT_X)) {
+ reason = "initialized dlatch are not supported";
+ goto error;
+ }
+ // If we got here, initialized dlatch is supported, but not this
+ // particular reset+init combination (nor its negation).
+ // The only hope left is breaking down to adff + dff + dlatch + mux.
+
+ log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
+ if (initbit.wire)
+ initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ Wire *adlatch_q = cell->module->addWire(NEW_ID);
+ Wire *dlatch_q = cell->module->addWire(NEW_ID);
+ Wire *sel_q = cell->module->addWire(NEW_ID);
+ dlatch_q->attributes[ID::init] = initval;
+ initbits[SigBit(dlatch_q, 0)] = std::make_pair(initval, SigBit(dlatch_q, 0));
+ sel_q->attributes[ID::init] = State::S0;
+ initbits[SigBit(sel_q, 0)] = std::make_pair(State::S0, SigBit(sel_q, 0));
+ Cell *cell_dlatch;
+ Cell *cell_adlatch;
+ Cell *cell_sel;
+ cell_dlatch = cell->module->addDlatchGate(NEW_ID, sig_e, sig_d, dlatch_q, !(ff_neg & NEG_E));
+ cell_adlatch = cell->module->addAdlatchGate(NEW_ID, sig_e, sig_r, sig_d, adlatch_q, ff_type == FF_ADLATCH1, !(ff_neg & NEG_E), !(ff_neg & NEG_R));
+ cell_sel = cell->module->addDlatchGate(NEW_ID, sig_r, State::S1, sel_q, !(ff_neg & NEG_R));
+ cell->module->addMuxGate(NEW_ID, dlatch_q, adlatch_q, sel_q, sig_q);
+
+ // Bye, cell.
+ cell->module->remove(cell);
+ handle_ff(cell_dlatch);
+ handle_ff(cell_adlatch);
+ handle_ff(cell_sel);
+ return;
+ } else if (ff_type == FF_DLATCHSR) {
+ if (supported_cells[FF_DLATCHSR] & flip_initmask(initmask)) {
+ goto flip_dqisr;
+ }
+ // No native DFFSR. However, if we can conjure
+ // a SR latch and ADFF, it can still be emulated.
+ int flipmask = flip_initmask(initmask);
+ bool init0 = true;
+ bool init1 = true;
+ State initsel = State::Sx;
+ if (((supported_cells[FF_ADLATCH0] & initmask) || (supported_cells[FF_ADLATCH1] & flipmask)) && ((supported_cells[FF_ADLATCH1] & initmask) || (supported_cells[FF_ADLATCH0] & flipmask)) && supported_sr) {
+ // OK
+ } else if (((supported_cells[FF_ADLATCH0] & initmask) || (supported_cells[FF_ADLATCH1] & flipmask)) && (supported_sr & INIT_0)) {
+ init1 = false;
+ initsel = State::S0;
+ } else if (((supported_cells[FF_ADLATCH1] & initmask) || (supported_cells[FF_ADLATCH0] & flipmask)) && (supported_sr & INIT_1)) {
+ init0 = false;
+ initsel = State::S1;
+ } else if (((supported_cells[FF_ADLATCH0] & initmask) || (supported_cells[FF_ADLATCH1] & flipmask)) && (supported_sr & INIT_1)) {
+ init1 = false;
+ initsel = State::S0;
+ } else if (((supported_cells[FF_ADLATCH1] & initmask) || (supported_cells[FF_ADLATCH0] & flipmask)) && (supported_sr & INIT_0)) {
+ init0 = false;
+ initsel = State::S1;
+ } else {
+ if (!supported_cells[FF_DLATCHSR])
+ reason = "dlatch with async set and reset are not supported";
+ else
+ reason = "initialized dlatch with async set and reset are not supported";
+ goto error;
+ }
+
+ log_warning("Emulating async set + reset with several latches and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
+ if (initbit.wire)
+ initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ Wire *adlatch0_q = cell->module->addWire(NEW_ID);
+ Wire *adlatch1_q = cell->module->addWire(NEW_ID);
+ Wire *sel_q = cell->module->addWire(NEW_ID);
+ if (init0) {
+ adlatch0_q->attributes[ID::init] = initval;
+ initbits[SigBit(adlatch0_q, 0)] = std::make_pair(initval, SigBit(adlatch0_q, 0));
+ }
+ if (init1) {
+ adlatch1_q->attributes[ID::init] = initval;
+ initbits[SigBit(adlatch1_q, 0)] = std::make_pair(initval, SigBit(adlatch1_q, 0));
+ }
+ sel_q->attributes[ID::init] = initsel;
+ initbits[SigBit(sel_q, 0)] = std::make_pair(initsel, SigBit(sel_q, 0));
+ Cell *cell_adlatch0;
+ Cell *cell_adlatch1;
+ Cell *cell_sel;
+ cell_adlatch0 = cell->module->addAdlatchGate(NEW_ID, sig_e, sig_r, sig_d, adlatch0_q, false, !(ff_neg & NEG_E), !(ff_neg & NEG_R));
+ cell_adlatch1 = cell->module->addAdlatchGate(NEW_ID, sig_e, sig_s, sig_d, adlatch1_q, true, !(ff_neg & NEG_E), !(ff_neg & NEG_S));
+ cell_sel = cell->module->addSrGate(NEW_ID, sig_s, sig_r, sel_q, !(ff_neg & NEG_S), !(ff_neg & NEG_R));
+ cell->module->addMuxGate(NEW_ID, adlatch0_q, adlatch1_q, sel_q, sig_q);
+
+ // Bye, cell.
+ cell->module->remove(cell);
+ handle_ff(cell_adlatch0);
+ handle_ff(cell_adlatch1);
+ handle_ff(cell_sel);
+ return;
+ } else if (ff_type == FF_SDFF0 || ff_type == FF_SDFF1 || ff_type == FF_SDFFE0 || ff_type == FF_SDFFE1 || ff_type == FF_SDFFCE0 || ff_type == FF_SDFFCE1) {
+ bool has_set = ff_type == FF_SDFF1 || ff_type == FF_SDFFE1 || ff_type == FF_SDFFCE1;
+ bool has_en = ff_type == FF_SDFFE0 || ff_type == FF_SDFFE1;
+ bool has_ce = ff_type == FF_SDFFCE0 || ff_type == FF_SDFFCE1;
+
+ if (has_en) {
+ if (kill_ce || kill_srst) {
+ ff_type = has_set ? FF_SDFF1 : FF_SDFF0;
+ goto unmap_enable;
+ }
+ } else if (has_ce) {
+ if (kill_ce || kill_srst)
+ goto unmap_srst;
+ } else {
+ log_assert(!kill_ce);
+ if (kill_srst)
+ goto unmap_srst;
+ }
+
+ if (!has_ce) {
+ if (!has_en && (supported_cells[has_set ? FF_SDFFE1 : FF_SDFFE0] & initmask)) {
+ // Just add enable.
+ sig_e = State::S1;
+ ff_type = has_set ? FF_SDFFE1 : FF_SDFFE0;
+ break;
+ }
+ if (!has_en && (supported_cells[has_set ? FF_SDFFCE1 : FF_SDFFCE0] & initmask)) {
+ // Just add enable.
+ sig_e = State::S1;
+ ff_type = has_set ? FF_SDFFCE1 : FF_SDFFCE0;
+ break;
+ }
+ if (has_en && (supported_cells[has_set ? FF_SDFFCE1 : FF_SDFFCE0] & initmask)) {
+ // Convert sdffe to sdffce
+ if (!(ff_neg & NEG_E)) {
+ if (!(ff_neg & NEG_R))
+ sig_e = cell->module->OrGate(NEW_ID, sig_e, sig_r);
+ else
+ sig_e = cell->module->OrnotGate(NEW_ID, sig_e, sig_r);
+ } else {
+ if (!(ff_neg & NEG_R))
+ sig_e = cell->module->AndnotGate(NEW_ID, sig_e, sig_r);
+ else
+ sig_e = cell->module->AndGate(NEW_ID, sig_e, sig_r);
+ }
+ ff_type = has_set ? FF_SDFFCE1 : FF_SDFFCE0;
+ break;
+ }
+ if (has_en && (supported_cells[has_set ? FF_SDFF1 : FF_SDFF0] & initmask)) {
+ // Unmap enable.
+ ff_type = has_set ? FF_SDFF1 : FF_SDFF0;
+ goto unmap_enable;
+ }
+ log_assert(!((has_set ? supported_sdff1 : supported_sdff0) & initmask));
+ } else {
+ if ((has_set ? supported_sdff1 : supported_sdff0) & initmask) {
+ // Convert sdffce to sdffe, which may be further converted to sdff.
+ if (!(ff_neg & NEG_R)) {
+ if (!(ff_neg & NEG_E))
+ sig_r = cell->module->AndGate(NEW_ID, sig_r, sig_e);
+ else
+ sig_r = cell->module->AndnotGate(NEW_ID, sig_r, sig_e);
+ } else {
+ if (!(ff_neg & NEG_E))
+ sig_r = cell->module->OrnotGate(NEW_ID, sig_r, sig_e);
+ else
+ sig_r = cell->module->OrGate(NEW_ID, sig_r, sig_e);
+ }
+ ff_type = has_set ? FF_SDFFE1 : FF_SDFFE0;
+ continue;
+ }
+ }
+ // Alright, so this particular combination of initval and
+ // resetval is not natively supported. First, try flipping
+ // them both to see whether this helps.
+ if ((has_set ? supported_sdff0 : supported_sdff1) & flip_initmask(initmask)) {
+ // Checks out, do it.
+ ff_type = has_ce ? (has_set ? FF_SDFFCE0 : FF_SDFFCE1) : has_en ? (has_set ? FF_SDFFE0 : FF_SDFFE1) : (has_set ? FF_SDFF0 : FF_SDFF1);
+ goto flip_dqi;
+ }
+
+ // Nope. No way to get SDFF* of the right kind, so unmap it.
+ // For SDFFE, the enable has to be unmapped first.
+ if (has_en) {
+ ff_type = has_set ? FF_SDFF1 : FF_SDFF0;
+ goto unmap_enable;
+ }
+unmap_srst:
+ if (has_ce)
+ ff_type = FF_DFFE;
+ else
+ ff_type = FF_DFF;
+ if (ff_neg & NEG_R)
+ sig_d = cell->module->MuxGate(NEW_ID, has_set ? State::S1 : State::S0, sig_d[0], sig_r[0]);
+ else
+ sig_d = cell->module->MuxGate(NEW_ID, sig_d[0], has_set ? State::S1 : State::S0, sig_r[0]);
+ ff_neg &= ~NEG_R;
+ sig_r = SigSpec();
+ kill_srst = false;
+ continue;
+ } else {
+ log_assert(0);
+ }
+ }
+cell_ok:
+
+ if (!(supported_cells_neg[ff_type][ff_neg] & initmask)) {
+ // Cell is supported, but not with those polarities.
+ // Will need to add some inverters.
+
+ // Find the smallest value that xored with the neg mask
+ // results in a supported one — this results in preferentially
+ // inverting resets before clocks, etc.
+ int xneg;
+ for (xneg = 0; xneg < NUM_NEG; xneg++)
+ if (supported_cells_neg[ff_type][ff_neg ^ xneg] & initmask)
+ break;
+ log_assert(xneg < NUM_NEG);
+ if (xneg & NEG_R)
+ sig_r = cell->module->NotGate(NEW_ID, sig_r[0]);
+ if (xneg & NEG_S)
+ sig_s = cell->module->NotGate(NEW_ID, sig_s[0]);
+ if (xneg & NEG_E)
+ sig_e = cell->module->NotGate(NEW_ID, sig_e[0]);
+ if (xneg & NEG_C)
+ sig_c = cell->module->NotGate(NEW_ID, sig_c[0]);
+ ff_neg ^= xneg;
+ }
+
+ cell->unsetPort(ID::D);
+ cell->unsetPort(ID::Q);
+ cell->unsetPort(ID::C);
+ cell->unsetPort(ID::E);
+ cell->unsetPort(ID::S);
+ cell->unsetPort(ID::R);
+ switch (ff_type) {
+ case FF_DFF:
+ cell->type = IdString(stringf("$_DFF_%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ break;
+ case FF_DFFE:
+ cell->type = IdString(stringf("$_DFFE_%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_E) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::E, sig_e);
+ break;
+ case FF_ADFF0:
+ case FF_ADFF1:
+ cell->type = IdString(stringf("$_DFF_%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_type == FF_ADFF1) ? '1' : '0'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_ADFFE0:
+ case FF_ADFFE1:
+ cell->type = IdString(stringf("$_DFFE_%c%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_type == FF_ADFFE1) ? '1' : '0',
+ (ff_neg & NEG_E) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::E, sig_e);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_DFFSR:
+ cell->type = IdString(stringf("$_DFFSR_%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_S) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::S, sig_s);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_DFFSRE:
+ cell->type = IdString(stringf("$_DFFSRE_%c%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_S) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_neg & NEG_E) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::E, sig_e);
+ cell->setPort(ID::S, sig_s);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_SDFF0:
+ case FF_SDFF1:
+ cell->type = IdString(stringf("$_SDFF_%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_type == FF_SDFF1) ? '1' : '0'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_SDFFE0:
+ case FF_SDFFE1:
+ cell->type = IdString(stringf("$_SDFFE_%c%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_type == FF_SDFFE1) ? '1' : '0',
+ (ff_neg & NEG_E) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::E, sig_e);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_SDFFCE0:
+ case FF_SDFFCE1:
+ cell->type = IdString(stringf("$_SDFFCE_%c%c%c%c_",
+ (ff_neg & NEG_C) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_type == FF_SDFFCE1) ? '1' : '0',
+ (ff_neg & NEG_E) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::C, sig_c);
+ cell->setPort(ID::E, sig_e);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_DLATCH:
+ cell->type = IdString(stringf("$_DLATCH_%c_",
+ (ff_neg & NEG_E) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::E, sig_e);
+ break;
+ case FF_ADLATCH0:
+ case FF_ADLATCH1:
+ cell->type = IdString(stringf("$_DLATCH_%c%c%c_",
+ (ff_neg & NEG_E) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P',
+ (ff_type == FF_ADLATCH1) ? '1' : '0'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::E, sig_e);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_DLATCHSR:
+ cell->type = IdString(stringf("$_DLATCHSR_%c%c%c_",
+ (ff_neg & NEG_E) ? 'N' : 'P',
+ (ff_neg & NEG_S) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::E, sig_e);
+ cell->setPort(ID::S, sig_s);
+ cell->setPort(ID::R, sig_r);
+ break;
+ case FF_SR:
+ cell->type = IdString(stringf("$_SR_%c%c_",
+ (ff_neg & NEG_S) ? 'N' : 'P',
+ (ff_neg & NEG_R) ? 'N' : 'P'
+ ));
+ cell->setPort(ID::Q, sig_q);
+ cell->setPort(ID::S, sig_s);
+ cell->setPort(ID::R, sig_r);
+ break;
+ default:
+ log_assert(0);
+ }
+ return;
+
+error:
+ log_error("FF %s.%s (type %s) cannot be legalized: %s\n", log_id(cell->module->name), log_id(cell->name), log_id(cell->type), reason);
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+
+ log_header(design, "Executing DFFLEGALIZE pass (convert FFs to types supported by the target).\n");
+
+ for (int i = 0; i < NUM_FFTYPES; i++) {
+ for (int j = 0; j < NUM_NEG; j++)
+ supported_cells_neg[i][j] = 0;
+ supported_cells[i] = 0;
+ }
+ mince = 0;
+ minsrst = 0;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-cell" && argidx + 2 < args.size()) {
+ std::string celltype = args[++argidx];
+ std::string inittype = args[++argidx];
+ enum FfType ff_type[2] = {NUM_FFTYPES, NUM_FFTYPES};
+ char pol_c = 0;
+ char pol_e = 0;
+ char pol_s = 0;
+ char pol_r = 0;
+ char srval = 0;
+ if (celltype.substr(0, 5) == "$_SR_" && celltype.size() == 8 && celltype[7] == '_') {
+ ff_type[0] = FF_SR;
+ pol_s = celltype[5];
+ pol_r = celltype[6];
+ } else if (celltype.substr(0, 6) == "$_DFF_" && celltype.size() == 8 && celltype[7] == '_') {
+ ff_type[0] = FF_DFF;
+ pol_c = celltype[6];
+ } else if (celltype.substr(0, 7) == "$_DFFE_" && celltype.size() == 10 && celltype[9] == '_') {
+ ff_type[0] = FF_DFFE;
+ pol_c = celltype[7];
+ pol_e = celltype[8];
+ } else if (celltype.substr(0, 6) == "$_DFF_" && celltype.size() == 10 && celltype[9] == '_') {
+ ff_type[0] = FF_ADFF0;
+ ff_type[1] = FF_ADFF1;
+ pol_c = celltype[6];
+ pol_r = celltype[7];
+ srval = celltype[8];
+ } else if (celltype.substr(0, 7) == "$_DFFE_" && celltype.size() == 12 && celltype[11] == '_') {
+ ff_type[0] = FF_ADFFE0;
+ ff_type[1] = FF_ADFFE1;
+ pol_c = celltype[7];
+ pol_r = celltype[8];
+ srval = celltype[9];
+ pol_e = celltype[10];
+ } else if (celltype.substr(0, 8) == "$_DFFSR_" && celltype.size() == 12 && celltype[11] == '_') {
+ ff_type[0] = FF_DFFSR;
+ pol_c = celltype[8];
+ pol_s = celltype[9];
+ pol_r = celltype[10];
+ } else if (celltype.substr(0, 9) == "$_DFFSRE_" && celltype.size() == 14 && celltype[13] == '_') {
+ ff_type[0] = FF_DFFSRE;
+ pol_c = celltype[9];
+ pol_s = celltype[10];
+ pol_r = celltype[11];
+ pol_e = celltype[12];
+ } else if (celltype.substr(0, 7) == "$_SDFF_" && celltype.size() == 11 && celltype[10] == '_') {
+ ff_type[0] = FF_SDFF0;
+ ff_type[1] = FF_SDFF1;
+ pol_c = celltype[7];
+ pol_r = celltype[8];
+ srval = celltype[9];
+ } else if (celltype.substr(0, 8) == "$_SDFFE_" && celltype.size() == 13 && celltype[12] == '_') {
+ ff_type[0] = FF_SDFFE0;
+ ff_type[1] = FF_SDFFE1;
+ pol_c = celltype[8];
+ pol_r = celltype[9];
+ srval = celltype[10];
+ pol_e = celltype[11];
+ } else if (celltype.substr(0, 9) == "$_SDFFCE_" && celltype.size() == 14 && celltype[13] == '_') {
+ ff_type[0] = FF_SDFFCE0;
+ ff_type[1] = FF_SDFFCE1;
+ pol_c = celltype[9];
+ pol_r = celltype[10];
+ srval = celltype[11];
+ pol_e = celltype[12];
+ } else if (celltype.substr(0, 9) == "$_DLATCH_" && celltype.size() == 11 && celltype[10] == '_') {
+ ff_type[0] = FF_DLATCH;
+ pol_e = celltype[9];
+ } else if (celltype.substr(0, 9) == "$_DLATCH_" && celltype.size() == 13 && celltype[12] == '_') {
+ ff_type[0] = FF_ADLATCH0;
+ ff_type[1] = FF_ADLATCH1;
+ pol_e = celltype[9];
+ pol_r = celltype[10];
+ srval = celltype[11];
+ } else if (celltype.substr(0, 11) == "$_DLATCHSR_" && celltype.size() == 15 && celltype[14] == '_') {
+ ff_type[0] = FF_DLATCHSR;
+ pol_e = celltype[11];
+ pol_s = celltype[12];
+ pol_r = celltype[13];
+ } else {
+unrecognized:
+ log_error("unrecognized cell type %s.\n", celltype.c_str());
+ }
+ int mask = 0;
+ int match = 0;
+ for (auto pair : {
+ std::make_pair(pol_c, NEG_C),
+ std::make_pair(pol_e, NEG_E),
+ std::make_pair(pol_s, NEG_S),
+ std::make_pair(pol_r, NEG_R),
+ }) {
+ if (pair.first == 'N') {
+ mask |= pair.second;
+ match |= pair.second;
+ } else if (pair.first == 'P' || pair.first == 0) {
+ mask |= pair.second;
+ } else if (pair.first != '?') {
+ goto unrecognized;
+ }
+ }
+ if (srval == '0') {
+ ff_type[1] = NUM_FFTYPES;
+ } else if (srval == '1') {
+ ff_type[0] = NUM_FFTYPES;
+ } else if (srval != 0 && srval != '?') {
+ goto unrecognized;
+ }
+ for (int i = 0; i < 2; i++) {
+ if (ff_type[i] == NUM_FFTYPES)
+ continue;
+ int initmask;
+ if (inittype == "x") {
+ initmask = INIT_X;
+ } else if (inittype == "0") {
+ initmask = INIT_X | INIT_0;
+ } else if (inittype == "1") {
+ initmask = INIT_X | INIT_1;
+ } else if (inittype == "r") {
+ if (srval == 0)
+ log_error("init type r not valid for cell type %s.\n", celltype.c_str());
+ if (i == 0)
+ initmask = INIT_X | INIT_0;
+ else
+ initmask = INIT_X | INIT_1;
+ } else if (inittype == "01") {
+ initmask = INIT_X | INIT_0 | INIT_1;
+ } else {
+ log_error("unrecognized init type %s for cell type %s.\n", inittype.c_str(), celltype.c_str());
+ }
+ for (int neg = 0; neg < NUM_NEG; neg++)
+ if ((neg & mask) == match)
+ supported_cells_neg[ff_type[i]][neg] |= initmask;
+ supported_cells[ff_type[i]] |= initmask;
+ }
+ continue;
+ } else if (args[argidx] == "-mince" && argidx + 1 < args.size()) {
+ mince = atoi(args[++argidx].c_str());
+ continue;
+ } else if (args[argidx] == "-minsrst" && argidx + 1 < args.size()) {
+ minsrst = atoi(args[++argidx].c_str());
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+ supported_dffsr = supported_cells[FF_DFFSR] | supported_cells[FF_DFFSRE];
+ supported_adff0 = supported_cells[FF_ADFF0] | supported_cells[FF_ADFFE0] | supported_dffsr;
+ supported_adff1 = supported_cells[FF_ADFF1] | supported_cells[FF_ADFFE1] | supported_dffsr;
+ supported_sdff0 = supported_cells[FF_SDFF0] | supported_cells[FF_SDFFE0] | supported_cells[FF_SDFFCE0];
+ supported_sdff1 = supported_cells[FF_SDFF1] | supported_cells[FF_SDFFE1] | supported_cells[FF_SDFFCE1];
+ supported_dff = supported_cells[FF_DFF] | supported_cells[FF_DFFE] | supported_dffsr | supported_adff0 | supported_adff1 | supported_sdff0 | supported_sdff1;
+ supported_sr = supported_dffsr | supported_cells[FF_DLATCHSR] | supported_cells[FF_SR] | supported_cells[FF_ADLATCH0] | flip_initmask(supported_cells[FF_ADLATCH1]);
+ supported_dlatch = supported_cells[FF_DLATCH] | supported_cells[FF_ADLATCH0] | supported_cells[FF_ADLATCH1] | supported_cells[FF_DLATCHSR];
+
+ for (auto module : design->selected_modules())
+ {
+ sigmap.set(module);
+ initbits.clear();
+
+ for (auto wire : module->selected_wires())
+ {
+ if (wire->attributes.count(ID::init) == 0)
+ continue;
+
+ SigSpec wirebits = sigmap(wire);
+ Const initval = wire->attributes.at(ID::init);
+
+ for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
+ {
+ SigBit bit = wirebits[i];
+ State val = initval[i];
+
+ if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
+ continue;
+
+ if (initbits.count(bit)) {
+ 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).first));
+ continue;
+ }
+
+ initbits[bit] = std::make_pair(val,SigBit(wire,i));
+ }
+ }
+
+ if (mince || minsrst) {
+ ce_used.clear();
+ srst_used.clear();
+
+ for (auto cell : module->cells()) {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+
+ if (cell->hasPort(ID::C) && cell->hasPort(ID::E)) {
+ SigSpec sig = cell->getPort(ID::E);
+ // Do not count const enable signals.
+ if (GetSize(sig) == 1 && sig[0].wire)
+ ce_used[sig[0]]++;
+ }
+ if (cell->type.str().substr(0, 6) == "$_SDFF") {
+ SigSpec sig = cell->getPort(ID::R);
+ // Do not count const srst signals.
+ if (GetSize(sig) == 1 && sig[0].wire)
+ srst_used[sig[0]]++;
+ }
+ }
+ }
+
+ // First gather FF cells, then iterate over them later.
+ // We may need to split an FF into several cells.
+ std::vector<Cell *> ff_cells;
+
+ for (auto cell : module->selected_cells())
+ {
+ // Early exit for non-FFs.
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+
+ ff_cells.push_back(cell);
+ }
+
+ for (auto cell: ff_cells)
+ handle_ff(cell);
+ }
+
+ sigmap.clear();
+ initbits.clear();
+ ce_used.clear();
+ srst_used.clear();
+ }
+} DffLegalizePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index aa344cf8a..c189d649b 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -409,11 +409,11 @@ static void map_sr_to_arst(IdString from, IdString to)
if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
return;
- char from_clk_pol YS_ATTRIBUTE(unused) = from[8];
+ char from_clk_pol = from[8];
char from_set_pol = from[9];
char from_clr_pol = from[10];
- char to_clk_pol YS_ATTRIBUTE(unused) = to[6];
- char to_rst_pol YS_ATTRIBUTE(unused) = to[7];
+ char to_clk_pol = to[6];
+ char to_rst_pol = to[7];
char to_rst_val = to[8];
log_assert(from_clk_pol == to_clk_pol);
@@ -455,9 +455,9 @@ static void map_adff_to_dff(IdString from, IdString to)
if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
return;
- char from_clk_pol YS_ATTRIBUTE(unused) = from[6];
+ char from_clk_pol = from[6];
char from_rst_pol = from[7];
- char to_clk_pol YS_ATTRIBUTE(unused) = to[6];
+ char to_clk_pol = to[6];
log_assert(from_clk_pol == to_clk_pol);
@@ -549,7 +549,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare
struct DfflibmapPass : public Pass {
DfflibmapPass() : Pass("dfflibmap", "technology mapping of flip-flops") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" dfflibmap [-prepare] -liberty <file> [selection]\n");
@@ -565,7 +565,7 @@ struct DfflibmapPass : public Pass {
log("liberty file.\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) override
{
log_header(design, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index f29044790..7278cb680 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -345,7 +345,7 @@ bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
struct ExtractPass : public Pass {
ExtractPass() : Pass("extract", "find subcircuits and replace them with cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -433,7 +433,7 @@ struct ExtractPass : public Pass {
log("See 'help techmap' for a pass that does the opposite thing.\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) override
{
log_header(design, "Executing EXTRACT pass (map subcircuits to cells).\n");
log_push();
diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc
index 68b338143..56b2ea584 100644
--- a/passes/techmap/extract_counter.cc
+++ b/passes/techmap/extract_counter.cc
@@ -760,7 +760,7 @@ void counter_worker(
struct ExtractCounterPass : public Pass {
ExtractCounterPass() : Pass("extract_counter", "Extract GreenPak4 counter cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -788,18 +788,18 @@ struct ExtractCounterPass : public Pass {
log("\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) override
{
log_header(design, "Executing EXTRACT_COUNTER pass (find counters in netlist).\n");
pool<RTLIL::IdString> _parallel_cells;
CounterExtractionSettings settings
{
- .parallel_cells = _parallel_cells,
- .maxwidth = 64,
- .minwidth = 2,
- .allow_arst = true,
- .allowed_dirs = 0,
+ _parallel_cells, // parallel_cells
+ 64, // maxwidth
+ 2, // minwidth
+ true, // allow_arst
+ 0, // allowed_dirs
};
size_t argidx;
diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc
index 9023d8687..3fcff01c3 100644
--- a/passes/techmap/extract_fa.cc
+++ b/passes/techmap/extract_fa.cc
@@ -539,7 +539,7 @@ struct ExtractFaWorker
struct ExtractFaPass : public Pass {
ExtractFaPass() : Pass("extract_fa", "find and extract full/half adders") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -561,7 +561,7 @@ struct ExtractFaPass : public Pass {
log(" Verbose output\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) override
{
ExtractFaConfig config;
diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc
index 2d63e413f..07b4200cc 100644
--- a/passes/techmap/extract_reduce.cc
+++ b/passes/techmap/extract_reduce.cc
@@ -34,7 +34,7 @@ struct ExtractReducePass : public Pass
ExtractReducePass() : Pass("extract_reduce", "converts gate chains into $reduce_* cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -63,7 +63,7 @@ struct ExtractReducePass : public Pass
(cell->type == ID($_XOR_) && gt == GateType::Xor);
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing EXTRACT_REDUCE pass.\n");
log_push();
diff --git a/passes/techmap/extractinv.cc b/passes/techmap/extractinv.cc
index 269fe5c6c..9b350456f 100644
--- a/passes/techmap/extractinv.cc
+++ b/passes/techmap/extractinv.cc
@@ -35,7 +35,7 @@ void split_portname_pair(std::string &port1, std::string &port2)
struct ExtractinvPass : public Pass {
ExtractinvPass() : Pass("extractinv", "extract explicit inverter cells for invertible cell pins") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -57,7 +57,7 @@ struct ExtractinvPass : public Pass {
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing EXTRACTINV pass (extracting pin inverters).\n");
diff --git a/passes/techmap/flatten.cc b/passes/techmap/flatten.cc
new file mode 100644
index 000000000..b5f55cffa
--- /dev/null
+++ b/passes/techmap/flatten.cc
@@ -0,0 +1,333 @@
+/*
+ * 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/utils.h"
+#include "kernel/sigtools.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+IdString concat_name(RTLIL::Cell *cell, IdString object_name)
+{
+ if (object_name[0] == '\\')
+ return stringf("%s.%s", cell->name.c_str(), object_name.c_str() + 1);
+ else {
+ std::string object_name_str = object_name.str();
+ if (object_name_str.substr(0, 8) == "$flatten")
+ object_name_str.erase(0, 8);
+ return stringf("$flatten%s.%s", cell->name.c_str(), object_name_str.c_str());
+ }
+}
+
+template<class T>
+IdString map_name(RTLIL::Cell *cell, T *object)
+{
+ return cell->module->uniquify(concat_name(cell, object->name));
+}
+
+template<class T>
+void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name)
+{
+ if (object->has_attribute(ID::src))
+ object->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+
+ // Preserve original names via the hdlname attribute, but only for objects with a fully public name.
+ if (cell->name[0] == '\\' && (object->has_attribute(ID::hdlname) || orig_object_name[0] == '\\')) {
+ std::vector<std::string> hierarchy;
+ if (object->has_attribute(ID::hdlname))
+ hierarchy = object->get_hdlname_attribute();
+ else
+ hierarchy.push_back(orig_object_name.str().substr(1));
+ hierarchy.insert(hierarchy.begin(), cell->name.str().substr(1));
+ object->set_hdlname_attribute(hierarchy);
+ }
+}
+
+void map_sigspec(const dict<RTLIL::Wire*, RTLIL::Wire*> &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr)
+{
+ vector<SigChunk> chunks = sig;
+ for (auto &chunk : chunks)
+ if (chunk.wire != nullptr && chunk.wire->module != into)
+ chunk.wire = map.at(chunk.wire);
+ sig = chunks;
+}
+
+struct FlattenWorker
+{
+ bool ignore_wb = false;
+
+ void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, std::vector<RTLIL::Cell*> &new_cells)
+ {
+ // Copy the contents of the flattened cell
+
+ dict<IdString, IdString> memory_map;
+ for (auto &tpl_memory_it : tpl->memories) {
+ RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second), tpl_memory_it.second);
+ map_attributes(cell, new_memory, tpl_memory_it.second->name);
+ memory_map[tpl_memory_it.first] = new_memory->name;
+ design->select(module, new_memory);
+ }
+
+ dict<RTLIL::Wire*, RTLIL::Wire*> wire_map;
+ dict<IdString, IdString> positional_ports;
+ for (auto tpl_wire : tpl->wires()) {
+ if (tpl_wire->port_id > 0)
+ positional_ports.emplace(stringf("$%d", tpl_wire->port_id), tpl_wire->name);
+
+ RTLIL::Wire *new_wire = nullptr;
+ if (tpl_wire->name[0] == '\\') {
+ RTLIL::Wire *hier_wire = module->wire(concat_name(cell, tpl_wire->name));
+ if (hier_wire != nullptr && hier_wire->get_bool_attribute(ID::hierconn)) {
+ hier_wire->attributes.erase(ID::hierconn);
+ if (GetSize(hier_wire) < GetSize(tpl_wire)) {
+ log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n",
+ log_id(module), log_id(hier_wire), log_id(tpl), log_id(tpl_wire), log_id(module), log_id(cell));
+ hier_wire->width = GetSize(tpl_wire);
+ }
+ new_wire = hier_wire;
+ }
+ }
+ if (new_wire == nullptr) {
+ new_wire = module->addWire(map_name(cell, tpl_wire), tpl_wire);
+ new_wire->port_input = new_wire->port_output = false;
+ new_wire->port_id = false;
+ }
+
+ map_attributes(cell, new_wire, tpl_wire->name);
+ wire_map[tpl_wire] = new_wire;
+ design->select(module, new_wire);
+ }
+
+ for (auto &tpl_proc_it : tpl->processes) {
+ RTLIL::Process *new_proc = module->addProcess(map_name(cell, tpl_proc_it.second), tpl_proc_it.second);
+ map_attributes(cell, new_proc, tpl_proc_it.second->name);
+ auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); };
+ new_proc->rewrite_sigspecs(rewriter);
+ design->select(module, new_proc);
+ }
+
+ for (auto tpl_cell : tpl->cells()) {
+ RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell), tpl_cell);
+ map_attributes(cell, new_cell, tpl_cell->name);
+ if (new_cell->type.in(ID($memrd), ID($memwr), ID($meminit))) {
+ IdString memid = new_cell->getParam(ID::MEMID).decode_string();
+ new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str()));
+ } else if (new_cell->type == ID($mem)) {
+ IdString memid = new_cell->getParam(ID::MEMID).decode_string();
+ new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid).str()));
+ }
+ auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); };
+ new_cell->rewrite_sigspecs(rewriter);
+ design->select(module, new_cell);
+ new_cells.push_back(new_cell);
+ }
+
+ for (auto &tpl_conn_it : tpl->connections()) {
+ RTLIL::SigSig new_conn = tpl_conn_it;
+ map_sigspec(wire_map, new_conn.first);
+ map_sigspec(wire_map, new_conn.second);
+ module->connect(new_conn);
+ }
+
+ // Attach port connections of the flattened cell
+
+ SigMap tpl_sigmap(tpl);
+ pool<SigBit> tpl_driven;
+ for (auto tpl_cell : tpl->cells())
+ for (auto &tpl_conn : tpl_cell->connections())
+ if (tpl_cell->output(tpl_conn.first))
+ for (auto bit : tpl_sigmap(tpl_conn.second))
+ tpl_driven.insert(bit);
+ for (auto &tpl_conn : tpl->connections())
+ for (auto bit : tpl_sigmap(tpl_conn.first))
+ tpl_driven.insert(bit);
+
+ SigMap sigmap(module);
+ for (auto &port_it : cell->connections())
+ {
+ IdString port_name = port_it.first;
+ if (positional_ports.count(port_name) > 0)
+ port_name = positional_ports.at(port_name);
+ if (tpl->wire(port_name) == nullptr || tpl->wire(port_name)->port_id == 0) {
+ if (port_name.begins_with("$"))
+ log_error("Can't map port `%s' of cell `%s' to template `%s'!\n",
+ port_name.c_str(), cell->name.c_str(), tpl->name.c_str());
+ continue;
+ }
+
+ if (GetSize(port_it.second) == 0)
+ continue;
+
+ RTLIL::Wire *tpl_wire = tpl->wire(port_name);
+ RTLIL::SigSig new_conn;
+ if (tpl_wire->port_output && !tpl_wire->port_input) {
+ new_conn.first = port_it.second;
+ new_conn.second = tpl_wire;
+ } else if (!tpl_wire->port_output && tpl_wire->port_input) {
+ new_conn.first = tpl_wire;
+ new_conn.second = port_it.second;
+ } else {
+ SigSpec sig_tpl = tpl_wire, sig_mod = port_it.second;
+ for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
+ if (tpl_driven.count(tpl_sigmap(sig_tpl[i]))) {
+ new_conn.first.append(sig_mod[i]);
+ new_conn.second.append(sig_tpl[i]);
+ } else {
+ new_conn.first.append(sig_tpl[i]);
+ new_conn.second.append(sig_mod[i]);
+ }
+ }
+ }
+ map_sigspec(wire_map, new_conn.first, module);
+ map_sigspec(wire_map, new_conn.second, module);
+
+ if (new_conn.second.size() > new_conn.first.size())
+ new_conn.second.remove(new_conn.first.size(), new_conn.second.size() - new_conn.first.size());
+ if (new_conn.second.size() < new_conn.first.size())
+ new_conn.second.append(RTLIL::SigSpec(RTLIL::State::S0, new_conn.first.size() - new_conn.second.size()));
+ log_assert(new_conn.first.size() == new_conn.second.size());
+
+ if (sigmap(new_conn.first).has_const())
+ log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n",
+ log_id(module), log_id(cell), log_id(port_it.first), log_signal(new_conn.first), log_signal(new_conn.second));
+
+ module->connect(new_conn);
+ }
+
+ module->remove(cell);
+ }
+
+ void flatten_module(RTLIL::Design *design, RTLIL::Module *module, pool<RTLIL::Module*> &used_modules)
+ {
+ if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb))
+ return;
+
+ std::vector<RTLIL::Cell*> worklist = module->selected_cells();
+ while (!worklist.empty())
+ {
+ RTLIL::Cell *cell = worklist.back();
+ worklist.pop_back();
+
+ if (!design->has(cell->type))
+ continue;
+
+ RTLIL::Module *tpl = design->module(cell->type);
+ if (tpl->get_blackbox_attribute(ignore_wb))
+ continue;
+
+ if (cell->get_bool_attribute(ID::keep_hierarchy) || tpl->get_bool_attribute(ID::keep_hierarchy)) {
+ log("Keeping %s.%s (found keep_hierarchy attribute).\n", log_id(module), log_id(cell));
+ used_modules.insert(tpl);
+ continue;
+ }
+
+ log_debug("Flattening %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
+ // If a design is fully selected and has a top module defined, topological sorting ensures that all cells
+ // added during flattening are black boxes, and flattening is finished in one pass. However, when flattening
+ // individual modules, this isn't the case, and the newly added cells might have to be flattened further.
+ flatten_cell(design, module, cell, tpl, worklist);
+ }
+ }
+};
+
+struct FlattenPass : public Pass {
+ FlattenPass() : Pass("flatten", "flatten design") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" flatten [options] [selection]\n");
+ log("\n");
+ log("This pass flattens the design by replacing cells by their implementation. This\n");
+ log("pass is very similar to the 'techmap' pass. The only difference is that this\n");
+ log("pass is using the current design as mapping library.\n");
+ log("\n");
+ log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n");
+ log("flattened by this command.\n");
+ log("\n");
+ log(" -wb\n");
+ log(" Ignore the 'whitebox' attribute on cell implementations.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing FLATTEN pass (flatten design).\n");
+ log_push();
+
+ FlattenWorker worker;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-wb") {
+ worker.ignore_wb = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ RTLIL::Module *top = nullptr;
+ if (design->full_selection())
+ for (auto module : design->modules())
+ if (module->get_bool_attribute(ID::top))
+ top = module;
+
+ pool<RTLIL::Module*> used_modules;
+ if (top == nullptr)
+ used_modules = design->modules();
+ else
+ used_modules.insert(top);
+
+ TopoSort<RTLIL::Module*, IdString::compare_ptr_by_name<RTLIL::Module>> topo_modules;
+ pool<RTLIL::Module*> worklist = used_modules;
+ while (!worklist.empty()) {
+ RTLIL::Module *module = worklist.pop();
+ for (auto cell : module->selected_cells()) {
+ RTLIL::Module *tpl = design->module(cell->type);
+ if (tpl != nullptr) {
+ if (topo_modules.database.count(tpl) == 0)
+ worklist.insert(tpl);
+ topo_modules.edge(tpl, module);
+ }
+ }
+ }
+
+ if (!topo_modules.sort())
+ log_error("Cannot flatten a design containing recursive instantiations.\n");
+
+ for (auto module : topo_modules.sorted)
+ worker.flatten_module(design, module, used_modules);
+
+ if (top != nullptr)
+ for (auto module : design->modules().to_vector())
+ if (!used_modules[module] && !module->get_blackbox_attribute(worker.ignore_wb)) {
+ log("Deleting now unused module %s.\n", log_id(module));
+ design->remove(module);
+ }
+
+ log_pop();
+ }
+} FlattenPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc
index 72947237b..dfdbe6b88 100644
--- a/passes/techmap/flowmap.cc
+++ b/passes/techmap/flowmap.cc
@@ -1470,7 +1470,7 @@ static void split(std::vector<std::string> &tokens, const std::string &text, cha
struct FlowmapPass : public Pass {
FlowmapPass() : Pass("flowmap", "pack LUTs with FlowMap") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1511,7 +1511,7 @@ struct FlowmapPass : public Pass {
log(" explain decisions performed during depth relaxation.\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) override
{
int order = 3;
int minlut = 1;
diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc
index 5aeb5ea79..b808a8d8e 100644
--- a/passes/techmap/hilomap.cc
+++ b/passes/techmap/hilomap.cc
@@ -55,7 +55,7 @@ void hilomap_worker(RTLIL::SigSpec &sig)
struct HilomapPass : public Pass {
HilomapPass() : Pass("hilomap", "technology mapping of constant hi- and/or lo-drivers") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" hilomap [options] [selection]\n");
@@ -74,7 +74,7 @@ struct HilomapPass : public Pass {
log(" each constant bit.\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) override
{
log_header(design, "Executing HILOMAP pass (mapping to constant drivers).\n");
diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc
index 0686c0f2b..a3b5b698d 100644
--- a/passes/techmap/insbuf.cc
+++ b/passes/techmap/insbuf.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct InsbufPass : public Pass {
InsbufPass() : Pass("insbuf", "insert buffer cells for connected wires") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" insbuf [options] [selection]\n");
@@ -37,7 +37,7 @@ struct InsbufPass : public Pass {
log(" call to \"clean\" will remove all $_BUF_ in the design.)\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) override
{
log_header(design, "Executing INSBUF pass (insert buffer cells for connected wires).\n");
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index a18d02652..e8530a034 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -34,7 +34,7 @@ void split_portname_pair(std::string &port1, std::string &port2)
struct IopadmapPass : public Pass {
IopadmapPass() : Pass("iopadmap", "technology mapping of i/o pads (or buffers)") { }
- void help() YS_OVERRIDE
+ void help() override
{
log("\n");
log(" iopadmap [options] [selection]\n");
@@ -97,7 +97,7 @@ struct IopadmapPass : public Pass {
modules_processed.insert(module);
}
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing IOPADMAP pass (mapping inputs/outputs to IO-PAD cells).\n");
diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc
index 703bf6ff6..f56eff3e5 100644
--- a/passes/techmap/lut2mux.cc
+++ b/passes/techmap/lut2mux.cc
@@ -56,7 +56,7 @@ int lut2mux(Cell *cell)
struct Lut2muxPass : public Pass {
Lut2muxPass() : Pass("lut2mux", "convert $lut to $_MUX_") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -65,7 +65,7 @@ struct Lut2muxPass : public Pass {
log("This pass converts $lut cells to $_MUX_ gates.\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) override
{
log_header(design, "Executing LUT2MUX pass (convert $lut to $_MUX_).\n");
diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc
index 3bb929009..43f2d97f5 100644
--- a/passes/techmap/maccmap.cc
+++ b/passes/techmap/maccmap.cc
@@ -365,7 +365,7 @@ PRIVATE_NAMESPACE_BEGIN
struct MaccmapPass : public Pass {
MaccmapPass() : Pass("maccmap", "mapping macc cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -375,7 +375,7 @@ struct MaccmapPass : public Pass {
log("is used then the $macc cell is mapped to $add, $sub, etc. cells instead.\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) override
{
bool unmap_mode = false;
diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc
index bd049d86d..24109b579 100644
--- a/passes/techmap/muxcover.cc
+++ b/passes/techmap/muxcover.cc
@@ -623,7 +623,7 @@ struct MuxcoverWorker
struct MuxcoverPass : public Pass {
MuxcoverPass() : Pass("muxcover", "cover trees of MUX cells with wider MUXes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -656,7 +656,7 @@ struct MuxcoverPass : public Pass {
log(" than <N> different signals.\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) override
{
log_header(design, "Executing MUXCOVER pass (mapping to wider MUXes).\n");
diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc
index 798d82248..e1ebfcad8 100644
--- a/passes/techmap/nlutmap.cc
+++ b/passes/techmap/nlutmap.cc
@@ -129,7 +129,7 @@ struct NlutmapWorker
struct NlutmapPass : public Pass {
NlutmapPass() : Pass("nlutmap", "map to LUTs of different sizes") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -149,7 +149,7 @@ struct NlutmapPass : public Pass {
log("to generic logic gates ($_AND_, etc.).\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) override
{
NlutmapConfig config;
diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc
index 2810b7f2d..b937d3fb0 100644
--- a/passes/techmap/pmuxtree.cc
+++ b/passes/techmap/pmuxtree.cc
@@ -67,7 +67,7 @@ static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data,
struct PmuxtreePass : public Pass {
PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -76,7 +76,7 @@ struct PmuxtreePass : public Pass {
log("This pass transforms $pmux cells to trees of $mux cells.\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) override
{
log_header(design, "Executing PMUXTREE pass.\n");
diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc
index d7a381e0a..237c261ae 100644
--- a/passes/techmap/shregmap.cc
+++ b/passes/techmap/shregmap.cc
@@ -403,7 +403,7 @@ struct ShregmapWorker
struct ShregmapPass : public Pass {
ShregmapPass() : Pass("shregmap", "map shift registers") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -461,7 +461,7 @@ struct ShregmapPass : public Pass {
log(" map to greenpak4 shift registers.\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) override
{
ShregmapOptions opts;
string clkpol, enpol;
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index b65b3e972..b9d337da4 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -474,29 +474,93 @@ void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_dffsre(RTLIL::Module *module, RTLIL::Cell *cell)
{
int width = cell->parameters.at(ID::WIDTH).as_int();
char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
- char rst_pol = cell->parameters.at(ID::ARST_POLARITY).as_bool() ? 'P' : 'N';
+ char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N';
+ char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N';
+ char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
- std::vector<RTLIL::State> rst_val = cell->parameters.at(ID::ARST_VALUE).bits;
+ RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
+ RTLIL::SigSpec sig_s = cell->getPort(ID::SET);
+ RTLIL::SigSpec sig_r = cell->getPort(ID::CLR);
+ RTLIL::SigSpec sig_e = cell->getPort(ID::EN);
+ RTLIL::SigSpec sig_d = cell->getPort(ID::D);
+ RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
+
+ IdString gate_type = stringf("$_DFFSRE_%c%c%c%c_", clk_pol, set_pol, clr_pol, en_pol);
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::C, sig_clk);
+ gate->setPort(ID::S, sig_s[i]);
+ gate->setPort(ID::R, sig_r[i]);
+ gate->setPort(ID::E, sig_e);
+ gate->setPort(ID::D, sig_d[i]);
+ gate->setPort(ID::Q, sig_q[i]);
+ }
+}
+
+void simplemap_adff_sdff(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ int width = cell->parameters.at(ID::WIDTH).as_int();
+ bool is_async = cell->type == ID($adff);
+ char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
+ char rst_pol = cell->parameters.at(is_async ? ID::ARST_POLARITY : ID::SRST_POLARITY).as_bool() ? 'P' : 'N';
+ const char *type = is_async ? "DFF" : "SDFF";
+
+ std::vector<RTLIL::State> rst_val = cell->parameters.at(is_async ? ID::ARST_VALUE : ID::SRST_VALUE).bits;
while (int(rst_val.size()) < width)
rst_val.push_back(RTLIL::State::S0);
RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_rst = cell->getPort(ID::ARST);
+ RTLIL::SigSpec sig_rst = cell->getPort(is_async ? ID::ARST : ID::SRST);
+ RTLIL::SigSpec sig_d = cell->getPort(ID::D);
+ RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
+
+ IdString gate_type_0 = stringf("$_%s_%c%c0_", type, clk_pol, rst_pol);
+ IdString gate_type_1 = stringf("$_%s_%c%c1_", type, clk_pol, rst_pol);
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::C, sig_clk);
+ gate->setPort(ID::R, sig_rst);
+ gate->setPort(ID::D, sig_d[i]);
+ gate->setPort(ID::Q, sig_q[i]);
+ }
+}
+
+void simplemap_adffe_sdffe_sdffce(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ int width = cell->parameters.at(ID::WIDTH).as_int();
+ bool is_async = cell->type == ID($adffe);
+ char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
+ char rst_pol = cell->parameters.at(is_async ? ID::ARST_POLARITY : ID::SRST_POLARITY).as_bool() ? 'P' : 'N';
+ char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
+ const char *type = is_async ? "DFFE" : cell->type == ID($sdffe) ? "SDFFE" : "SDFFCE";
+
+ std::vector<RTLIL::State> rst_val = cell->parameters.at(is_async ? ID::ARST_VALUE : ID::SRST_VALUE).bits;
+ while (int(rst_val.size()) < width)
+ rst_val.push_back(RTLIL::State::S0);
+
+ RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
+ RTLIL::SigSpec sig_rst = cell->getPort(is_async ? ID::ARST : ID::SRST);
+ RTLIL::SigSpec sig_e = cell->getPort(ID::EN);
RTLIL::SigSpec sig_d = cell->getPort(ID::D);
RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
- IdString gate_type_0 = stringf("$_DFF_%c%c0_", clk_pol, rst_pol);
- IdString gate_type_1 = stringf("$_DFF_%c%c1_", clk_pol, rst_pol);
+ IdString gate_type_0 = stringf("$_%s_%c%c0%c_", type, clk_pol, rst_pol, en_pol);
+ IdString gate_type_1 = stringf("$_%s_%c%c1%c_", type, clk_pol, rst_pol, en_pol);
for (int i = 0; i < width; i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
gate->setPort(ID::C, sig_clk);
gate->setPort(ID::R, sig_rst);
+ gate->setPort(ID::E, sig_e);
gate->setPort(ID::D, sig_d[i]);
gate->setPort(ID::Q, sig_q[i]);
}
@@ -522,7 +586,61 @@ void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
+void simplemap_adlatch(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ int width = cell->parameters.at(ID::WIDTH).as_int();
+ char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
+ char rst_pol = cell->parameters.at(ID::ARST_POLARITY).as_bool() ? 'P' : 'N';
+
+ std::vector<RTLIL::State> rst_val = cell->parameters.at(ID::ARST_VALUE).bits;
+ while (int(rst_val.size()) < width)
+ rst_val.push_back(RTLIL::State::S0);
+
+ RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
+ RTLIL::SigSpec sig_rst = cell->getPort(ID::ARST);
+ RTLIL::SigSpec sig_d = cell->getPort(ID::D);
+ RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
+
+ IdString gate_type_0 = stringf("$_DLATCH_%c%c0_", en_pol, rst_pol);
+ IdString gate_type_1 = stringf("$_DLATCH_%c%c1_", en_pol, rst_pol);
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::E, sig_en);
+ gate->setPort(ID::R, sig_rst);
+ gate->setPort(ID::D, sig_d[i]);
+ gate->setPort(ID::Q, sig_q[i]);
+ }
+}
+
+void simplemap_dlatchsr(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ int width = cell->parameters.at(ID::WIDTH).as_int();
+ char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
+ char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N';
+ char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N';
+
+ RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
+ RTLIL::SigSpec sig_s = cell->getPort(ID::SET);
+ RTLIL::SigSpec sig_r = cell->getPort(ID::CLR);
+ RTLIL::SigSpec sig_d = cell->getPort(ID::D);
+ RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
+
+ IdString gate_type = stringf("$_DLATCHSR_%c%c%c_", en_pol, set_pol, clr_pol);
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::E, sig_en);
+ gate->setPort(ID::S, sig_s[i]);
+ gate->setPort(ID::R, sig_r[i]);
+ gate->setPort(ID::D, sig_d[i]);
+ gate->setPort(ID::Q, sig_q[i]);
+ }
+}
+
+void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers)
{
mappers[ID($not)] = simplemap_not;
mappers[ID($pos)] = simplemap_pos;
@@ -553,13 +671,20 @@ void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTL
mappers[ID($dff)] = simplemap_dff;
mappers[ID($dffe)] = simplemap_dffe;
mappers[ID($dffsr)] = simplemap_dffsr;
- mappers[ID($adff)] = simplemap_adff;
+ mappers[ID($dffsre)] = simplemap_dffsre;
+ mappers[ID($adff)] = simplemap_adff_sdff;
+ mappers[ID($sdff)] = simplemap_adff_sdff;
+ mappers[ID($adffe)] = simplemap_adffe_sdffe_sdffce;
+ mappers[ID($sdffe)] = simplemap_adffe_sdffe_sdffce;
+ mappers[ID($sdffce)] = simplemap_adffe_sdffe_sdffce;
mappers[ID($dlatch)] = simplemap_dlatch;
+ mappers[ID($adlatch)] = simplemap_adlatch;
+ mappers[ID($dlatchsr)] = simplemap_dlatchsr;
}
void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)
{
- static std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
+ static dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
static bool initialized_mappers = false;
if (!initialized_mappers) {
@@ -575,7 +700,7 @@ PRIVATE_NAMESPACE_BEGIN
struct SimplemapPass : public Pass {
SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -587,15 +712,15 @@ struct SimplemapPass : public Pass {
log(" $not, $pos, $and, $or, $xor, $xnor\n");
log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n");
- log(" $sr, $ff, $dff, $dffsr, $adff, $dlatch\n");
+ log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\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) override
{
log_header(design, "Executing SIMPLEMAP pass (map simple cells to gate primitives).\n");
extra_args(args, 1, design);
- std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
+ dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
simplemap_get_mappers(mappers);
for (auto mod : design->modules()) {
diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h
index c2d73ea79..5091050a1 100644
--- a/passes/techmap/simplemap.h
+++ b/passes/techmap/simplemap.h
@@ -42,7 +42,7 @@ extern void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
+extern void simplemap_get_mappers(dict<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
YOSYS_NAMESPACE_END
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index a554be257..f98d1564a 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -27,7 +27,6 @@
#include <string.h>
#include "simplemap.h"
-#include "passes/techmap/techmap.inc"
YOSYS_NAMESPACE_BEGIN
@@ -51,27 +50,23 @@ void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
{
vector<SigChunk> chunks = sig;
for (auto &chunk : chunks)
- if (chunk.wire != NULL) {
+ if (chunk.wire != nullptr) {
IdString wire_name = chunk.wire->name;
apply_prefix(prefix, wire_name);
- log_assert(module->wires_.count(wire_name) > 0);
- chunk.wire = module->wires_[wire_name];
+ log_assert(module->wire(wire_name) != nullptr);
+ chunk.wire = module->wire(wire_name);
}
sig = chunks;
}
struct TechmapWorker
{
- std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> simplemap_mappers;
- std::map<std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache;
- std::map<RTLIL::Module*, bool> techmap_do_cache;
- std::set<RTLIL::Module*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Module>> module_queue;
+ dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> simplemap_mappers;
+ dict<std::pair<IdString, dict<IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache;
+ dict<RTLIL::Module*, bool> techmap_do_cache;
+ pool<RTLIL::Module*> module_queue;
dict<Module*, SigMap> sigmaps;
- pool<IdString> flatten_do_list;
- pool<IdString> flatten_done_list;
- pool<Cell*> flatten_keep_list;
-
pool<string> log_msg_cache;
struct TechmapWireData {
@@ -79,31 +74,20 @@ struct TechmapWorker
RTLIL::SigSpec value;
};
- typedef std::map<std::string, std::vector<TechmapWireData>> TechmapWires;
+ typedef dict<IdString, std::vector<TechmapWireData>> TechmapWires;
- bool extern_mode;
- bool assert_mode;
- bool flatten_mode;
- bool recursive_mode;
- bool autoproc_mode;
- bool ignore_wb;
-
- TechmapWorker()
- {
- extern_mode = false;
- assert_mode = false;
- flatten_mode = false;
- recursive_mode = false;
- autoproc_mode = false;
- ignore_wb = false;
- }
+ bool extern_mode = false;
+ bool assert_mode = false;
+ bool recursive_mode = false;
+ bool autoproc_mode = false;
+ bool ignore_wb = false;
std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose)
{
std::string constmap_info;
- std::map<RTLIL::SigBit, std::pair<RTLIL::IdString, int>> connbits_map;
+ dict<RTLIL::SigBit, std::pair<IdString, int>> connbits_map;
- for (auto conn : cell->connections())
+ for (auto &conn : cell->connections())
for (int i = 0; i < GetSize(conn.second); i++) {
RTLIL::SigBit bit = sigmap(conn.second[i]);
if (bit.wire == nullptr) {
@@ -117,7 +101,7 @@ struct TechmapWorker
constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i,
log_id(connbits_map.at(bit).first), connbits_map.at(bit).second);
} else {
- connbits_map[bit] = std::pair<RTLIL::IdString, int>(conn.first, i);
+ connbits_map.emplace(bit, std::make_pair(conn.first, i));
constmap_info += stringf("|%s %d", log_id(conn.first), i);
}
}
@@ -129,24 +113,25 @@ struct TechmapWorker
{
TechmapWires result;
- if (module == NULL)
+ if (module == nullptr)
return result;
- for (auto &it : module->wires_) {
- const char *p = it.first.c_str();
+ for (auto w : module->wires()) {
+ const char *p = w->name.c_str();
if (*p == '$')
continue;
const char *q = strrchr(p+1, '.');
- p = q ? q+1 : p+1;
+ if (q)
+ p = q;
- if (!strncmp(p, "_TECHMAP_", 9)) {
+ if (!strncmp(p, "\\_TECHMAP_", 10)) {
TechmapWireData record;
- record.wire = it.second;
- record.value = it.second;
+ record.wire = w;
+ record.value = w;
result[p].push_back(record);
- it.second->attributes[ID::keep] = RTLIL::Const(1);
- it.second->attributes[ID::_techmap_special_] = RTLIL::Const(1);
+ w->set_bool_attribute(ID::keep);
+ w->set_bool_attribute(ID::_techmap_special_);
}
}
@@ -165,7 +150,7 @@ struct TechmapWorker
if (tpl->processes.size() != 0) {
log("Technology map yielded processes:");
for (auto &it : tpl->processes)
- log(" %s",RTLIL::id2cstr(it.first));
+ log(" %s",log_id(it.first));
log("\n");
if (autoproc_mode) {
Pass::call_on_module(tpl->design, tpl, "proc");
@@ -178,89 +163,71 @@ struct TechmapWorker
pool<string> extra_src_attrs = cell->get_strpool_attribute(ID::src);
orig_cell_name = cell->name.str();
- if (!flatten_mode) {
- for (auto &it : tpl->cells_)
- if (it.first == ID::_TECHMAP_REPLACE_) {
- module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str());
- break;
- }
- }
+ for (auto tpl_cell : tpl->cells())
+ if (tpl_cell->name == ID::_TECHMAP_REPLACE_) {
+ module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str());
+ break;
+ }
dict<IdString, IdString> memory_renames;
for (auto &it : tpl->memories) {
IdString m_name = it.first;
apply_prefix(cell->name, m_name);
- RTLIL::Memory *m = new RTLIL::Memory;
- m->name = m_name;
- m->width = it.second->width;
- m->start_offset = it.second->start_offset;
- m->size = it.second->size;
- m->attributes = it.second->attributes;
+ RTLIL::Memory *m = module->addMemory(m_name, it.second);
if (m->attributes.count(ID::src))
m->add_strpool_attribute(ID::src, extra_src_attrs);
- module->memories[m->name] = m;
memory_renames[it.first] = m->name;
design->select(module, m);
}
- std::map<RTLIL::IdString, RTLIL::IdString> positional_ports;
+ dict<IdString, IdString> positional_ports;
dict<Wire*, IdString> temp_renamed_wires;
pool<SigBit> autopurge_tpl_bits;
- for (auto &it : tpl->wires_)
+ for (auto tpl_w : tpl->wires())
{
- if (it.second->port_id > 0)
+ if (tpl_w->port_id > 0)
{
- IdString posportname = stringf("$%d", it.second->port_id);
- positional_ports[posportname] = it.first;
+ IdString posportname = stringf("$%d", tpl_w->port_id);
+ positional_ports.emplace(posportname, tpl_w->name);
- if (!flatten_mode && it.second->get_bool_attribute(ID::techmap_autopurge) &&
- (!cell->hasPort(it.second->name) || !GetSize(cell->getPort(it.second->name))) &&
+ if (tpl_w->get_bool_attribute(ID::techmap_autopurge) &&
+ (!cell->hasPort(tpl_w->name) || !GetSize(cell->getPort(tpl_w->name))) &&
(!cell->hasPort(posportname) || !GetSize(cell->getPort(posportname))))
{
if (sigmaps.count(tpl) == 0)
sigmaps[tpl].set(tpl);
- for (auto bit : sigmaps.at(tpl)(it.second))
+ for (auto bit : sigmaps.at(tpl)(tpl_w))
if (bit.wire != nullptr)
autopurge_tpl_bits.insert(bit);
}
}
- IdString w_name = it.second->name;
+ IdString w_name = tpl_w->name;
apply_prefix(cell->name, w_name);
RTLIL::Wire *w = module->wire(w_name);
if (w != nullptr) {
- if (!flatten_mode || !w->get_bool_attribute(ID::hierconn)) {
- temp_renamed_wires[w] = w->name;
- module->rename(w, NEW_ID);
- w = nullptr;
- } else {
- w->attributes.erase(ID::hierconn);
- if (GetSize(w) < GetSize(it.second)) {
- log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", log_id(module), log_id(w),
- log_id(tpl), log_id(it.second), log_id(module), log_id(cell));
- w->width = GetSize(it.second);
- }
- }
+ temp_renamed_wires[w] = w->name;
+ module->rename(w, NEW_ID);
+ w = nullptr;
}
if (w == nullptr) {
- w = module->addWire(w_name, it.second);
+ w = module->addWire(w_name, tpl_w);
w->port_input = false;
w->port_output = false;
w->port_id = 0;
- if (!flatten_mode)
- w->attributes.erase(ID::techmap_autopurge);
- if (it.second->get_bool_attribute(ID::_techmap_special_))
+ w->attributes.erase(ID::techmap_autopurge);
+ if (tpl_w->get_bool_attribute(ID::_techmap_special_))
w->attributes.clear();
if (w->attributes.count(ID::src))
w->add_strpool_attribute(ID::src, extra_src_attrs);
}
design->select(module, w);
- if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) {
- IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
- Wire *replace_w = module->addWire(replace_name, it.second);
+ if (tpl_w->name.begins_with("\\_TECHMAP_REPLACE_.")) {
+ IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), tpl_w->name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
+ Wire *replace_w = module->addWire(replace_name, tpl_w);
module->connect(replace_w, w);
}
}
@@ -268,24 +235,23 @@ struct TechmapWorker
SigMap tpl_sigmap(tpl);
pool<SigBit> tpl_written_bits;
- for (auto &it1 : tpl->cells_)
- for (auto &it2 : it1.second->connections_)
- if (it1.second->output(it2.first))
- for (auto bit : tpl_sigmap(it2.second))
+ for (auto tpl_cell : tpl->cells())
+ for (auto &conn : tpl_cell->connections())
+ if (tpl_cell->output(conn.first))
+ for (auto bit : tpl_sigmap(conn.second))
tpl_written_bits.insert(bit);
- for (auto &it1 : tpl->connections_)
- for (auto bit : tpl_sigmap(it1.first))
+ for (auto &conn : tpl->connections())
+ for (auto bit : tpl_sigmap(conn.first))
tpl_written_bits.insert(bit);
SigMap port_signal_map;
- SigSig port_signal_assign;
for (auto &it : cell->connections())
{
- RTLIL::IdString portname = it.first;
+ IdString portname = it.first;
if (positional_ports.count(portname) > 0)
portname = positional_ports.at(portname);
- if (tpl->wires_.count(portname) == 0 || tpl->wires_.at(portname)->port_id == 0) {
+ if (tpl->wire(portname) == nullptr || tpl->wire(portname)->port_id == 0) {
if (portname.begins_with("$"))
log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname.c_str(), cell->name.c_str(), tpl->name.c_str());
continue;
@@ -294,7 +260,7 @@ struct TechmapWorker
if (GetSize(it.second) == 0)
continue;
- RTLIL::Wire *w = tpl->wires_.at(portname);
+ RTLIL::Wire *w = tpl->wire(portname);
RTLIL::SigSig c, extra_connect;
if (w->port_output && !w->port_input) {
@@ -333,76 +299,58 @@ struct TechmapWorker
log_assert(c.first.size() == c.second.size());
- if (flatten_mode)
- {
- // more conservative approach:
- // connect internal and external wires
-
- if (sigmaps.count(module) == 0)
- sigmaps[module].set(module);
-
- if (sigmaps.at(module)(c.first).has_const())
- log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n",
- log_id(module), log_id(cell), log_id(it.first), log_signal(c.first), log_signal(c.second));
+ // replace internal wires that are connected to external wires
+ if (w->port_output && !w->port_input) {
+ port_signal_map.add(c.second, c.first);
+ } else
+ if (!w->port_output && w->port_input) {
+ port_signal_map.add(c.first, c.second);
+ } else {
module->connect(c);
+ extra_connect = SigSig();
}
- else
- {
- // approach that yields nicer outputs:
- // replace internal wires that are connected to external wires
-
- if (w->port_output && !w->port_input) {
- port_signal_map.add(c.second, c.first);
- } else
- if (!w->port_output && w->port_input) {
- port_signal_map.add(c.first, c.second);
- } else {
- module->connect(c);
- extra_connect = SigSig();
- }
- for (auto &attr : w->attributes) {
- if (attr.first == ID::src)
- continue;
- auto lhs = GetSize(extra_connect.first);
- auto rhs = GetSize(extra_connect.second);
- if (lhs > rhs)
- extra_connect.first.remove(rhs, lhs-rhs);
- else if (rhs > lhs)
- extra_connect.second.remove(lhs, rhs-lhs);
- module->connect(extra_connect);
- break;
- }
+ for (auto &attr : w->attributes) {
+ if (attr.first == ID::src)
+ continue;
+ auto lhs = GetSize(extra_connect.first);
+ auto rhs = GetSize(extra_connect.second);
+ if (lhs > rhs)
+ extra_connect.first.remove(rhs, lhs-rhs);
+ else if (rhs > lhs)
+ extra_connect.second.remove(lhs, rhs-lhs);
+ module->connect(extra_connect);
+ break;
}
}
- for (auto &it : tpl->cells_)
+ for (auto tpl_cell : tpl->cells())
{
- IdString c_name = it.second->name.str();
- bool techmap_replace_cell = (!flatten_mode) && (c_name == ID::_TECHMAP_REPLACE_);
+ IdString c_name = tpl_cell->name;
+ bool techmap_replace_cell = (c_name == ID::_TECHMAP_REPLACE_);
if (techmap_replace_cell)
c_name = orig_cell_name;
- else if (it.second->name.begins_with("\\_TECHMAP_REPLACE_."))
+ else if (tpl_cell->name.begins_with("\\_TECHMAP_REPLACE_."))
c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_"));
else
apply_prefix(cell->name, c_name);
- RTLIL::Cell *c = module->addCell(c_name, it.second);
+ RTLIL::Cell *c = module->addCell(c_name, tpl_cell);
design->select(module, c);
- if (!flatten_mode && c->type.begins_with("\\$"))
+ if (c->type.begins_with("\\$"))
c->type = c->type.substr(1);
vector<IdString> autopurge_ports;
- for (auto &it2 : c->connections_)
+ for (auto &conn : c->connections())
{
bool autopurge = false;
if (!autopurge_tpl_bits.empty()) {
- autopurge = GetSize(it2.second) != 0;
- for (auto &bit : sigmaps.at(tpl)(it2.second))
+ autopurge = GetSize(conn.second) != 0;
+ for (auto &bit : sigmaps.at(tpl)(conn.second))
if (!autopurge_tpl_bits.count(bit)) {
autopurge = false;
break;
@@ -410,10 +358,12 @@ struct TechmapWorker
}
if (autopurge) {
- autopurge_ports.push_back(it2.first);
+ autopurge_ports.push_back(conn.first);
} else {
- apply_prefix(cell->name, it2.second, module);
- port_signal_map.apply(it2.second);
+ RTLIL::SigSpec new_conn = conn.second;
+ apply_prefix(cell->name, new_conn, module);
+ port_signal_map.apply(new_conn);
+ c->setPort(conn.first, std::move(new_conn));
}
}
@@ -463,8 +413,8 @@ struct TechmapWorker
}
}
- bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set<RTLIL::Cell*> &handled_cells,
- const std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> &celltypeMap, bool in_recursion)
+ bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, pool<RTLIL::Cell*> &handled_cells,
+ const dict<IdString, pool<IdString>> &celltypeMap, bool in_recursion)
{
std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping";
@@ -489,13 +439,13 @@ struct TechmapWorker
}
}
- TopoSort<RTLIL::Cell*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
- std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_inbit;
- std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> outbit_to_cell;
+ TopoSort<RTLIL::Cell*, IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
+ dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_to_inbit;
+ dict<RTLIL::SigBit, pool<RTLIL::Cell*>> outbit_to_cell;
- for (auto cell : module->cells())
+ for (auto cell : module->selected_cells())
{
- if (!design->selected(module, cell) || handled_cells.count(cell) > 0)
+ if (handled_cells.count(cell) > 0)
continue;
std::string cell_type = cell->type.str();
@@ -508,22 +458,6 @@ struct TechmapWorker
continue;
}
- if (flatten_mode) {
- bool keepit = cell->get_bool_attribute(ID::keep_hierarchy);
- for (auto &tpl_name : celltypeMap.at(cell_type))
- if (map->modules_[tpl_name]->get_bool_attribute(ID::keep_hierarchy))
- keepit = true;
- if (keepit) {
- if (!flatten_keep_list[cell]) {
- log("Keeping %s.%s (found keep_hierarchy property).\n", log_id(module), log_id(cell));
- flatten_keep_list.insert(cell);
- }
- if (!flatten_done_list[cell->type])
- flatten_do_list.insert(cell->type);
- continue;
- }
- }
-
for (auto &conn : cell->connections())
{
RTLIL::SigSpec sig = sigmap(conn.second);
@@ -533,7 +467,7 @@ struct TechmapWorker
continue;
for (auto &tpl_name : celltypeMap.at(cell_type)) {
- RTLIL::Module *tpl = map->modules_[tpl_name];
+ RTLIL::Module *tpl = map->module(tpl_name);
RTLIL::Wire *port = tpl->wire(conn.first);
if (port && port->port_input)
cell_to_inbit[cell].insert(sig.begin(), sig.end());
@@ -566,189 +500,188 @@ struct TechmapWorker
for (auto &tpl_name : celltypeMap.at(cell_type))
{
- RTLIL::IdString derived_name = tpl_name;
- RTLIL::Module *tpl = map->modules_[tpl_name];
- std::map<RTLIL::IdString, RTLIL::Const> parameters(cell->parameters.begin(), cell->parameters.end());
+ IdString derived_name = tpl_name;
+ RTLIL::Module *tpl = map->module(tpl_name);
+ dict<IdString, RTLIL::Const> parameters(cell->parameters);
if (tpl->get_blackbox_attribute(ignore_wb))
continue;
- if (!flatten_mode)
- {
- std::string extmapper_name;
+ std::string extmapper_name;
- if (tpl->get_bool_attribute(ID::techmap_simplemap))
- extmapper_name = "simplemap";
+ if (tpl->get_bool_attribute(ID::techmap_simplemap))
+ extmapper_name = "simplemap";
- if (tpl->get_bool_attribute(ID::techmap_maccmap))
- extmapper_name = "maccmap";
+ if (tpl->get_bool_attribute(ID::techmap_maccmap))
+ extmapper_name = "maccmap";
- if (tpl->attributes.count(ID::techmap_wrap))
- extmapper_name = "wrap";
+ if (tpl->attributes.count(ID::techmap_wrap))
+ extmapper_name = "wrap";
- if (!extmapper_name.empty())
- {
- cell->type = cell_type;
-
- if ((extern_mode && !in_recursion) || extmapper_name == "wrap")
- {
- std::string m_name = stringf("$extern:%s:%s", extmapper_name.c_str(), log_id(cell->type));
-
- for (auto &c : cell->parameters)
- m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second));
-
- if (extmapper_name == "wrap")
- m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string());
-
- RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design;
- RTLIL::Module *extmapper_module = extmapper_design->module(m_name);
+ if (!extmapper_name.empty())
+ {
+ cell->type = cell_type;
- if (extmapper_module == nullptr)
- {
- extmapper_module = extmapper_design->addModule(m_name);
- RTLIL::Cell *extmapper_cell = extmapper_module->addCell(cell->type, cell);
-
- extmapper_cell->set_src_attribute(cell->get_src_attribute());
-
- int port_counter = 1;
- for (auto &c : extmapper_cell->connections_) {
- RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second));
- if (w->name.in(ID::Y, ID::Q))
- w->port_output = true;
- else
- w->port_input = true;
- w->port_id = port_counter++;
- c.second = w;
- }
+ if ((extern_mode && !in_recursion) || extmapper_name == "wrap")
+ {
+ std::string m_name = stringf("$extern:%s:%s", extmapper_name.c_str(), log_id(cell->type));
- extmapper_module->fixup_ports();
- extmapper_module->check();
+ for (auto &c : cell->parameters)
+ m_name += stringf(":%s=%s", log_id(c.first), log_signal(c.second));
- if (extmapper_name == "simplemap") {
- log("Creating %s with simplemap.\n", log_id(extmapper_module));
- if (simplemap_mappers.count(extmapper_cell->type) == 0)
- log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type));
- simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell);
- extmapper_module->remove(extmapper_cell);
- }
+ if (extmapper_name == "wrap")
+ m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string());
- if (extmapper_name == "maccmap") {
- log("Creating %s with maccmap.\n", log_id(extmapper_module));
- if (extmapper_cell->type != ID($macc))
- log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type));
- maccmap(extmapper_module, extmapper_cell);
- extmapper_module->remove(extmapper_cell);
- }
+ RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design;
+ RTLIL::Module *extmapper_module = extmapper_design->module(m_name);
- if (extmapper_name == "wrap") {
- std::string cmd_string = tpl->attributes.at(ID::techmap_wrap).decode_string();
- log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module));
- mkdebug.on();
- Pass::call_on_module(extmapper_design, extmapper_module, cmd_string);
- log_continue = true;
- }
+ if (extmapper_module == nullptr)
+ {
+ extmapper_module = extmapper_design->addModule(m_name);
+ RTLIL::Cell *extmapper_cell = extmapper_module->addCell(cell->type, cell);
+
+ extmapper_cell->set_src_attribute(cell->get_src_attribute());
+
+ int port_counter = 1;
+ for (auto &c : extmapper_cell->connections_) {
+ RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second));
+ if (w->name.in(ID::Y, ID::Q))
+ w->port_output = true;
+ else
+ w->port_input = true;
+ w->port_id = port_counter++;
+ c.second = w;
}
- cell->type = extmapper_module->name;
- cell->parameters.clear();
+ extmapper_module->fixup_ports();
+ extmapper_module->check();
- if (!extern_mode || in_recursion) {
- tpl = extmapper_module;
- goto use_wrapper_tpl;
+ if (extmapper_name == "simplemap") {
+ log("Creating %s with simplemap.\n", log_id(extmapper_module));
+ if (simplemap_mappers.count(extmapper_cell->type) == 0)
+ log_error("No simplemap mapper for cell type %s found!\n", log_id(extmapper_cell->type));
+ simplemap_mappers.at(extmapper_cell->type)(extmapper_module, extmapper_cell);
+ extmapper_module->remove(extmapper_cell);
}
- auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type));
- if (!log_msg_cache.count(msg)) {
- log_msg_cache.insert(msg);
- log("%s\n", msg.c_str());
- }
- log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
- }
- else
- {
- auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type));
- if (!log_msg_cache.count(msg)) {
- log_msg_cache.insert(msg);
- log("%s\n", msg.c_str());
+ if (extmapper_name == "maccmap") {
+ log("Creating %s with maccmap.\n", log_id(extmapper_module));
+ if (extmapper_cell->type != ID($macc))
+ log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(extmapper_cell->type));
+ maccmap(extmapper_module, extmapper_cell);
+ extmapper_module->remove(extmapper_cell);
}
- log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
- if (extmapper_name == "simplemap") {
- if (simplemap_mappers.count(cell->type) == 0)
- log_error("No simplemap mapper for cell type %s found!\n", RTLIL::id2cstr(cell->type));
- simplemap_mappers.at(cell->type)(module, cell);
+ if (extmapper_name == "wrap") {
+ std::string cmd_string = tpl->attributes.at(ID::techmap_wrap).decode_string();
+ log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module));
+ mkdebug.on();
+ Pass::call_on_module(extmapper_design, extmapper_module, cmd_string);
+ log_continue = true;
}
+ }
- if (extmapper_name == "maccmap") {
- if (cell->type != ID($macc))
- log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type));
- maccmap(module, cell);
- }
+ cell->type = extmapper_module->name;
+ cell->parameters.clear();
- module->remove(cell);
- cell = NULL;
+ if (!extern_mode || in_recursion) {
+ tpl = extmapper_module;
+ goto use_wrapper_tpl;
}
- did_something = true;
- mapped_cell = true;
- break;
+ auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type));
+ if (!log_msg_cache.count(msg)) {
+ log_msg_cache.insert(msg);
+ log("%s\n", msg.c_str());
+ }
+ log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module));
}
+ else
+ {
+ auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type));
+ if (!log_msg_cache.count(msg)) {
+ log_msg_cache.insert(msg);
+ log("%s\n", msg.c_str());
+ }
+ log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str());
+
+ if (extmapper_name == "simplemap") {
+ if (simplemap_mappers.count(cell->type) == 0)
+ log_error("No simplemap mapper for cell type %s found!\n", log_id(cell->type));
+ simplemap_mappers.at(cell->type)(module, cell);
+ }
- for (auto conn : cell->connections()) {
- if (conn.first.begins_with("$"))
- continue;
- if (tpl->wires_.count(conn.first) > 0 && tpl->wires_.at(conn.first)->port_id > 0)
- continue;
- if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0)
- goto next_tpl;
- parameters[conn.first] = conn.second.as_const();
+ if (extmapper_name == "maccmap") {
+ if (cell->type != ID($macc))
+ log_error("The maccmap mapper can only map $macc (not %s) cells!\n", log_id(cell->type));
+ maccmap(module, cell);
+ }
+
+ module->remove(cell);
+ cell = nullptr;
}
- if (0) {
- next_tpl:
+ did_something = true;
+ mapped_cell = true;
+ break;
+ }
+
+ for (auto &conn : cell->connections()) {
+ if (conn.first.begins_with("$"))
continue;
- }
+ if (tpl->wire(conn.first) != nullptr && tpl->wire(conn.first)->port_id > 0)
+ continue;
+ if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0)
+ goto next_tpl;
+ parameters[conn.first] = conn.second.as_const();
+ }
+
+ if (0) {
+ next_tpl:
+ continue;
+ }
- if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0)
- parameters[ID::_TECHMAP_CELLTYPE_] = RTLIL::unescape_id(cell->type);
+ if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0)
+ parameters.emplace(ID::_TECHMAP_CELLTYPE_, RTLIL::unescape_id(cell->type));
- for (auto conn : cell->connections()) {
- if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))) != 0) {
- std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector();
- for (auto &bit : v)
- bit = RTLIL::SigBit(bit.wire == NULL ? RTLIL::State::S1 : RTLIL::State::S0);
- parameters[stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))] = RTLIL::SigSpec(v).as_const();
- }
- if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", RTLIL::id2cstr(conn.first))) != 0) {
- std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector();
- for (auto &bit : v)
- if (bit.wire != NULL)
- bit = RTLIL::SigBit(RTLIL::State::Sx);
- parameters[stringf("\\_TECHMAP_CONSTVAL_%s_", RTLIL::id2cstr(conn.first))] = RTLIL::SigSpec(v).as_const();
- }
- if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", RTLIL::id2cstr(conn.first))) != 0) {
- auto sig = sigmap(conn.second);
- RTLIL::Const value(State::Sx, sig.size());
- for (int i = 0; i < sig.size(); i++) {
- auto it = init_bits.find(sig[i]);
- if (it != init_bits.end()) {
- value[i] = it->second;
- }
+ for (auto &conn : cell->connections()) {
+ if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) {
+ std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector();
+ for (auto &bit : v)
+ bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0);
+ parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const());
+ }
+ if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first))) != 0) {
+ std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector();
+ for (auto &bit : v)
+ if (bit.wire != nullptr)
+ bit = RTLIL::SigBit(RTLIL::State::Sx);
+ parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const());
+ }
+ if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) {
+ auto sig = sigmap(conn.second);
+ RTLIL::Const value(State::Sx, sig.size());
+ for (int i = 0; i < sig.size(); i++) {
+ auto it = init_bits.find(sig[i]);
+ if (it != init_bits.end()) {
+ value[i] = it->second;
}
- parameters[stringf("\\_TECHMAP_WIREINIT_%s_", RTLIL::id2cstr(conn.first))] = value;
}
+ parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), value);
}
+ }
+ {
int unique_bit_id_counter = 0;
- std::map<RTLIL::SigBit, int> unique_bit_id;
+ dict<RTLIL::SigBit, int> unique_bit_id;
unique_bit_id[RTLIL::State::S0] = unique_bit_id_counter++;
unique_bit_id[RTLIL::State::S1] = unique_bit_id_counter++;
unique_bit_id[RTLIL::State::Sx] = unique_bit_id_counter++;
unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++;
- for (auto conn : cell->connections())
- if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) {
- for (auto &bit : sigmap(conn.second).to_sigbit_vector())
+ for (auto &conn : cell->connections())
+ if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) {
+ for (auto &bit : sigmap(conn.second))
if (unique_bit_id.count(bit) == 0)
unique_bit_id[bit] = unique_bit_id_counter++;
}
@@ -763,14 +696,17 @@ struct TechmapWorker
if (tpl->avail_parameters.count(ID::_TECHMAP_BITS_CONNMAP_))
parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits;
- for (auto conn : cell->connections())
- if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) {
+ for (auto &conn : cell->connections())
+ if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) {
RTLIL::Const value;
- for (auto &bit : sigmap(conn.second).to_sigbit_vector()) {
- RTLIL::Const chunk(unique_bit_id.at(bit), bits);
- value.bits.insert(value.bits.end(), chunk.bits.begin(), chunk.bits.end());
+ for (auto &bit : sigmap(conn.second)) {
+ int val = unique_bit_id.at(bit);
+ for (int i = 0; i < bits; i++) {
+ value.bits.push_back((val & 1) != 0 ? State::S1 : State::S0);
+ val = val >> 1;
+ }
}
- parameters[stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))] = value;
+ parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), value);
}
}
@@ -778,34 +714,31 @@ struct TechmapWorker
use_wrapper_tpl:;
// do not register techmap_wrap modules with techmap_cache
} else {
- std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>> key(tpl_name, parameters);
- if (techmap_cache.count(key) > 0) {
- tpl = techmap_cache[key];
+ std::pair<IdString, dict<IdString, RTLIL::Const>> key(tpl_name, parameters);
+ auto it = techmap_cache.find(key);
+ if (it != techmap_cache.end()) {
+ tpl = it->second;
} else {
if (parameters.size() != 0) {
mkdebug.on();
- derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end()));
+ derived_name = tpl->derive(map, parameters);
tpl = map->module(derived_name);
log_continue = true;
}
- techmap_cache[key] = tpl;
+ techmap_cache.emplace(std::move(key), tpl);
}
}
- if (flatten_mode) {
- techmap_do_cache[tpl] = true;
- } else {
- RTLIL::Module *constmapped_tpl = map->module(constmap_tpl_name(sigmap, tpl, cell, false));
- if (constmapped_tpl != nullptr)
- tpl = constmapped_tpl;
- }
+ RTLIL::Module *constmapped_tpl = map->module(constmap_tpl_name(sigmap, tpl, cell, false));
+ if (constmapped_tpl != nullptr)
+ tpl = constmapped_tpl;
if (techmap_do_cache.count(tpl) == 0)
{
bool keep_running = true;
techmap_do_cache[tpl] = true;
- std::set<std::string> techmap_wire_names;
+ pool<IdString> techmap_wire_names;
while (keep_running)
{
@@ -815,11 +748,11 @@ struct TechmapWorker
for (auto &it : twd)
techmap_wire_names.insert(it.first);
- for (auto &it : twd["_TECHMAP_FAIL_"]) {
+ for (auto &it : twd[ID::_TECHMAP_FAIL_]) {
RTLIL::SigSpec value = it.value;
if (value.is_fully_const() && value.as_bool()) {
log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n",
- derived_name.c_str(), RTLIL::id2cstr(it.wire->name), log_signal(value));
+ derived_name.c_str(), log_id(it.wire->name), log_signal(value));
techmap_do_cache[tpl] = false;
}
}
@@ -829,13 +762,13 @@ struct TechmapWorker
for (auto &it : twd)
{
- if (it.first.compare(0, 12, "_TECHMAP_DO_") != 0 || it.second.empty())
+ if (!it.first.begins_with("\\_TECHMAP_DO_") || it.second.empty())
continue;
auto &data = it.second.front();
if (!data.value.is_fully_const())
- log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(data.wire->name), log_signal(data.value));
+ log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(data.wire->name), log_signal(data.value));
techmap_wire_names.erase(it.first);
@@ -851,7 +784,7 @@ struct TechmapWorker
cmd_string = cmd_string.substr(strlen("CONSTMAP; "));
log("Analyzing pattern of constant bits for this cell:\n");
- RTLIL::IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true);
+ IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true);
log("Creating constmapped module `%s'.\n", log_id(new_tpl_name));
log_assert(map->module(new_tpl_name) == nullptr);
@@ -862,16 +795,16 @@ struct TechmapWorker
techmap_do_cache[new_tpl] = true;
tpl = new_tpl;
- std::map<RTLIL::SigBit, RTLIL::SigBit> port_new2old_map;
- std::map<RTLIL::SigBit, RTLIL::SigBit> port_connmap;
- std::map<RTLIL::SigBit, RTLIL::SigBit> cellbits_to_tplbits;
+ dict<RTLIL::SigBit, RTLIL::SigBit> port_new2old_map;
+ dict<RTLIL::SigBit, RTLIL::SigBit> port_connmap;
+ dict<RTLIL::SigBit, RTLIL::SigBit> cellbits_to_tplbits;
for (auto wire : tpl->wires().to_vector())
{
if (!wire->port_input || wire->port_output)
continue;
- RTLIL::IdString port_name = wire->name;
+ IdString port_name = wire->name;
tpl->rename(wire, NEW_ID);
RTLIL::Wire *new_wire = tpl->addWire(port_name, wire);
@@ -879,12 +812,12 @@ struct TechmapWorker
wire->port_id = 0;
for (int i = 0; i < wire->width; i++) {
- port_new2old_map[RTLIL::SigBit(new_wire, i)] = RTLIL::SigBit(wire, i);
- port_connmap[RTLIL::SigBit(wire, i)] = RTLIL::SigBit(new_wire, i);
+ port_new2old_map.emplace(RTLIL::SigBit(new_wire, i), RTLIL::SigBit(wire, i));
+ port_connmap.emplace(RTLIL::SigBit(wire, i), RTLIL::SigBit(new_wire, i));
}
}
- for (auto conn : cell->connections())
+ for (auto &conn : cell->connections())
for (int i = 0; i < GetSize(conn.second); i++)
{
RTLIL::SigBit bit = sigmap(conn.second[i]);
@@ -926,7 +859,7 @@ struct TechmapWorker
log_assert(!strncmp(q, "_TECHMAP_DO_", 12));
std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12);
- while (tpl->wires_.count(new_name))
+ while (tpl->wire(new_name) != nullptr)
new_name += "_";
tpl->rename(data.wire->name, new_name);
@@ -937,17 +870,17 @@ struct TechmapWorker
TechmapWires twd = techmap_find_special_wires(tpl);
for (auto &it : twd) {
- if (it.first != "_TECHMAP_FAIL_" && (it.first.substr(0, 20) != "_TECHMAP_REMOVEINIT_" || it.first[it.first.size()-1] != '_') && it.first.substr(0, 12) != "_TECHMAP_DO_" && it.first.substr(0, 14) != "_TECHMAP_DONE_")
- log_error("Techmap yielded unknown config wire %s.\n", it.first.c_str());
+ if (it.first != ID::_TECHMAP_FAIL_ && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.begins_with("\\_TECHMAP_DO_") && !it.first.begins_with("\\_TECHMAP_DONE_"))
+ log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first));
if (techmap_do_cache[tpl])
for (auto &it2 : it.second)
if (!it2.value.is_fully_const())
- log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(it2.wire->name), log_signal(it2.value));
+ log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(it2.wire->name), log_signal(it2.value));
techmap_wire_names.erase(it.first);
}
for (auto &it : techmap_wire_names)
- log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", RTLIL::id2cstr(it));
+ log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", log_id(it));
if (recursive_mode) {
if (log_continue) {
@@ -970,10 +903,10 @@ struct TechmapWorker
TechmapWires twd = techmap_find_special_wires(tpl);
for (auto &it : twd) {
- if (it.first.substr(0, 20) == "_TECHMAP_REMOVEINIT_") {
+ if (it.first.begins_with("\\_TECHMAP_REMOVEINIT_")) {
for (auto &it2 : it.second) {
auto val = it2.value.as_const();
- auto wirename = RTLIL::escape_id(it.first.substr(20, it.first.size() - 20 - 1));
+ auto wirename = RTLIL::escape_id(it.first.substr(21, it.first.size() - 21 - 1));
auto it = cell->connections().find(wirename);
if (it != cell->connections().end()) {
auto sig = sigmap(it->second);
@@ -1015,7 +948,7 @@ struct TechmapWorker
}
log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl));
techmap_module_worker(design, module, cell, tpl);
- cell = NULL;
+ cell = nullptr;
}
did_something = true;
mapped_cell = true;
@@ -1059,7 +992,7 @@ struct TechmapWorker
struct TechmapPass : public Pass {
TechmapPass() : Pass("techmap", "generic technology mapper") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1219,7 +1152,7 @@ struct TechmapPass : public Pass {
log("essentially techmap but using the design itself as map library).\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) override
{
log_header(design, "Executing TECHMAP pass (map to technology primitives).\n");
log_push();
@@ -1275,8 +1208,7 @@ struct TechmapPass : public Pass {
RTLIL::Design *map = new RTLIL::Design;
if (map_files.empty()) {
- std::istringstream f(stdcells_code);
- Frontend::frontend_call(map, &f, "<techmap.v>", verilog_frontend);
+ Frontend::frontend_call(map, nullptr, "+/techmap.v", verilog_frontend);
} else {
for (auto &fn : map_files)
if (fn.compare(0, 1, "%") == 0) {
@@ -1285,35 +1217,30 @@ struct TechmapPass : public Pass {
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))
+ if (!map->module(mod->name))
map->add(mod->clone());
} else {
- std::ifstream f;
- rewrite_filename(fn);
- f.open(fn.c_str());
- yosys_input_files.insert(fn);
- if (f.fail())
- log_cmd_error("Can't open map file `%s'\n", fn.c_str());
- Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend));
+ Frontend::frontend_call(map, nullptr, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend));
}
}
log_header(design, "Continuing TECHMAP pass.\n");
- std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
- for (auto &it : map->modules_) {
- if (it.second->attributes.count(ID::techmap_celltype) && !it.second->attributes.at(ID::techmap_celltype).bits.empty()) {
- char *p = strdup(it.second->attributes.at(ID::techmap_celltype).decode_string().c_str());
- for (char *q = strtok(p, " \t\r\n"); q; q = strtok(NULL, " \t\r\n"))
- celltypeMap[RTLIL::escape_id(q)].insert(it.first);
+ dict<IdString, pool<IdString>> celltypeMap;
+ for (auto module : map->modules()) {
+ if (module->attributes.count(ID::techmap_celltype) && !module->attributes.at(ID::techmap_celltype).bits.empty()) {
+ char *p = strdup(module->attributes.at(ID::techmap_celltype).decode_string().c_str());
+ for (char *q = strtok(p, " \t\r\n"); q; q = strtok(nullptr, " \t\r\n"))
+ celltypeMap[RTLIL::escape_id(q)].insert(module->name);
free(p);
} else {
- string module_name = it.first.str();
- if (it.first.begins_with("\\$"))
- module_name = module_name.substr(1);
- celltypeMap[module_name].insert(it.first);
+ IdString module_name = module->name.begins_with("\\$") ?
+ module->name.substr(1) : module->name.str();
+ celltypeMap[module_name].insert(module->name);
}
}
+ for (auto &i : celltypeMap)
+ i.second.sort(RTLIL::sort_by_id_str());
for (auto module : design->modules())
worker.module_queue.insert(module);
@@ -1325,7 +1252,7 @@ struct TechmapPass : public Pass {
int module_max_iter = max_iter;
bool did_something = true;
- std::set<RTLIL::Cell*> handled_cells;
+ pool<RTLIL::Cell*> handled_cells;
while (did_something) {
did_something = false;
if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false))
@@ -1344,100 +1271,4 @@ struct TechmapPass : public Pass {
}
} TechmapPass;
-struct FlattenPass : public Pass {
- FlattenPass() : Pass("flatten", "flatten design") { }
- void help() YS_OVERRIDE
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" flatten [options] [selection]\n");
- log("\n");
- log("This pass flattens the design by replacing cells by their implementation. This\n");
- log("pass is very similar to the 'techmap' pass. The only difference is that this\n");
- log("pass is using the current design as mapping library.\n");
- log("\n");
- log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n");
- log("flattened by this command.\n");
- log("\n");
- log(" -wb\n");
- log(" Ignore the 'whitebox' attribute on cell implementations.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
- {
- log_header(design, "Executing FLATTEN pass (flatten design).\n");
- log_push();
-
- TechmapWorker worker;
- worker.flatten_mode = true;
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++) {
- if (args[argidx] == "-wb") {
- worker.ignore_wb = true;
- continue;
- }
- break;
- }
- extra_args(args, argidx, design);
-
-
- std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
- for (auto module : design->modules())
- celltypeMap[module->name].insert(module->name);
-
- RTLIL::Module *top_mod = NULL;
- if (design->full_selection())
- for (auto mod : design->modules())
- if (mod->get_bool_attribute(ID::top))
- top_mod = mod;
-
- std::set<RTLIL::Cell*> handled_cells;
- if (top_mod != NULL) {
- worker.flatten_do_list.insert(top_mod->name);
- while (!worker.flatten_do_list.empty()) {
- auto mod = design->module(*worker.flatten_do_list.begin());
- while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { }
- worker.flatten_done_list.insert(mod->name);
- worker.flatten_do_list.erase(mod->name);
- }
- } else {
- for (auto mod : vector<Module*>(design->modules())) {
- while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { }
- }
- }
-
- log_suppressed();
- log("No more expansions possible.\n");
-
- if (top_mod != NULL)
- {
- pool<RTLIL::IdString> used_modules, new_used_modules;
- new_used_modules.insert(top_mod->name);
- while (!new_used_modules.empty()) {
- pool<RTLIL::IdString> queue;
- queue.swap(new_used_modules);
- for (auto modname : queue)
- used_modules.insert(modname);
- for (auto modname : queue)
- for (auto cell : design->module(modname)->cells())
- if (design->module(cell->type) && !used_modules[cell->type])
- new_used_modules.insert(cell->type);
- }
-
- dict<RTLIL::IdString, RTLIL::Module*> new_modules;
- for (auto mod : vector<Module*>(design->modules()))
- if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) {
- new_modules[mod->name] = mod;
- } else {
- log("Deleting now unused module %s.\n", log_id(mod));
- delete mod;
- }
- design->modules_.swap(new_modules);
- }
-
- log_pop();
- }
-} FlattenPass;
-
PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc
index 90f3a9d6f..79ddb4bd7 100644
--- a/passes/techmap/tribuf.cc
+++ b/passes/techmap/tribuf.cc
@@ -143,7 +143,7 @@ struct TribufWorker {
struct TribufPass : public Pass {
TribufPass() : Pass("tribuf", "infer tri-state buffers") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -160,7 +160,7 @@ struct TribufPass : public Pass {
log(" to non-tristate logic. this option implies -merge.\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) override
{
TribufConfig config;
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index 74604ba3b..cc0b26bcc 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
struct ZinitPass : public Pass {
ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -37,7 +37,7 @@ struct ZinitPass : public Pass {
log(" also add zero initialization to uninitialized FFs\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) override
{
bool all_mode = false;
@@ -91,20 +91,29 @@ struct ZinitPass : public Pass {
// 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($dff), ID($dffe), /*ID($dffsr),*/ ID($adff), ID($adffe),
+ ID($sdff), ID($sdffe), ID($sdffce),
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($_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_),
// 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),
+ ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
+ ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
+ ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
+ ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_),
// 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)
+ ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
+ ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_),
+ ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
+ ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
+ ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
+ ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_),
+ ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
+ ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
+ ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
+ ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)
};
for (auto cell : module->selected_cells())
@@ -151,13 +160,20 @@ struct ZinitPass : public Pass {
cell->setPort(ID::D, sig_d);
cell->setPort(ID::Q, initwire);
- if (cell->type == ID($adff)) {
+ if (cell->type.in(ID($adff), ID($adffe))) {
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 (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
+ auto val = cell->getParam(ID::SRST_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::SRST_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_),
@@ -165,15 +181,29 @@ struct ZinitPass : public Pass {
{
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_)))
+ else if (cell->type.in(ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
+ ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_)))
+ {
+ t[9] = (t[9] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
+ ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
+ ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
+ ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_)))
+ {
+ t[9] = (t[9] == '0' ? '1' : '0');
+ }
+ else if (cell->type.in(ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
+ ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
+ ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
+ ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_)))
{
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)))
+ else if (cell->type.in(ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
+ ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
+ ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
+ ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)))
{
t[11] = (t[11] == '0' ? '1' : '0');
}
diff --git a/passes/tests/test_abcloop.cc b/passes/tests/test_abcloop.cc
index 894610e2b..2d80e66e4 100644
--- a/passes/tests/test_abcloop.cc
+++ b/passes/tests/test_abcloop.cc
@@ -132,7 +132,7 @@ static void test_abcloop()
SatGen satgen(ez.get(), &sigmap);
for (auto c : module->cells()) {
- bool ok YS_ATTRIBUTE(unused) = satgen.importCell(c);
+ bool ok = satgen.importCell(c);
log_assert(ok);
}
@@ -182,7 +182,7 @@ static void test_abcloop()
SatGen satgen(ez.get(), &sigmap);
for (auto c : module->cells()) {
- bool ok YS_ATTRIBUTE(unused) = satgen.importCell(c);
+ bool ok = satgen.importCell(c);
log_assert(ok);
}
@@ -244,7 +244,7 @@ static void test_abcloop()
struct TestAbcloopPass : public Pass {
TestAbcloopPass() : Pass("test_abcloop", "automatically test handling of loops in abc command") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -259,7 +259,7 @@ struct TestAbcloopPass : public Pass {
log(" use this value as rng seed value (default = unix time).\n");
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design*) override
{
int num_iter = 100;
xorshift32_state = 0;
diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc
index 19f21493d..4ab46014d 100644
--- a/passes/tests/test_autotb.cc
+++ b/passes/tests/test_autotb.cc
@@ -327,7 +327,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s
struct TestAutotbBackend : public Backend {
TestAutotbBackend() : Backend("=test_autotb", "generate simple test benches") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -360,7 +360,7 @@ struct TestAutotbBackend : public Backend {
log(" the current system time.\n");
log("\n");
}
- void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
int num_iter = 1000;
int seed = 0;
diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc
index cdbe922b2..bdb475d3b 100644
--- a/passes/tests/test_cell.cc
+++ b/passes/tests/test_cell.cc
@@ -264,7 +264,11 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->setPort(ID::Y, wire);
}
- if (muxdiv && cell_type.in(ID($div), ID($mod))) {
+ if (cell_type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
+ cell->parameters[ID::B_SIGNED] = false;
+ }
+
+ if (muxdiv && cell_type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor))) {
auto b_not_zero = module->ReduceBool(NEW_ID, cell->getPort(ID::B));
auto div_out = module->addWire(NEW_ID, GetSize(cell->getPort(ID::Y)));
module->addMux(NEW_ID, RTLIL::SigSpec(0, GetSize(div_out)), div_out, b_not_zero, cell->getPort(ID::Y));
@@ -652,7 +656,7 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std::
struct TestCellPass : public Pass {
TestCellPass() : Pass("test_cell", "automatically test the implementation of a cell type") { }
- void help() YS_OVERRIDE
+ void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -712,7 +716,7 @@ struct TestCellPass : public Pass {
log(" create a Verilog test bench to test simlib and write_verilog\n");
log("\n");
}
- void execute(std::vector<std::string> args, RTLIL::Design*) YS_OVERRIDE
+ void execute(std::vector<std::string> args, RTLIL::Design*) override
{
int num_iter = 100;
std::string techmap_cmd = "techmap -assert";
@@ -839,6 +843,8 @@ struct TestCellPass : public Pass {
cell_types[ID($mul)] = "ABSY";
cell_types[ID($div)] = "ABSY";
cell_types[ID($mod)] = "ABSY";
+ cell_types[ID($divfloor)] = "ABSY";
+ cell_types[ID($modfloor)] = "ABSY";
// cell_types[ID($pow)] = "ABsY";
cell_types[ID($logic_not)] = "ASY";
@@ -903,7 +909,7 @@ struct TestCellPass : public Pass {
if (!ilang_file.empty()) {
if (!selected_cell_types.empty())
log_cmd_error("Do not specify any cell types when using -f.\n");
- selected_cell_types.push_back("ilang");
+ selected_cell_types.push_back(ID(ilang));
}
if (selected_cell_types.empty())
@@ -915,7 +921,7 @@ struct TestCellPass : public Pass {
for (int i = 0; i < num_iter; i++)
{
RTLIL::Design *design = new RTLIL::Design;
- if (cell_type == "ilang")
+ if (cell_type == ID(ilang))
Frontend::frontend_call(design, NULL, std::string(), "ilang " + ilang_file);
else
create_gold_module(design, cell_type, cell_types.at(cell_type), constmode, muxdiv);