aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--backends/aiger/aiger.cc20
-rw-r--r--backends/smt2/smtbmc.py53
-rw-r--r--kernel/driver.cc49
-rw-r--r--kernel/log.cc4
-rw-r--r--kernel/log.h1
-rw-r--r--passes/cmds/Makefile.inc1
-rw-r--r--passes/cmds/chtype.cc83
-rw-r--r--passes/cmds/design.cc97
-rw-r--r--passes/opt/opt_expr.cc4
-rw-r--r--passes/opt/opt_merge.cc2
-rw-r--r--passes/techmap/abc.cc359
-rw-r--r--techlibs/greenpak4/greenpak4_counters.cc24
13 files changed, 502 insertions, 203 deletions
diff --git a/Makefile b/Makefile
index 2868ba1e5..ffb5db823 100644
--- a/Makefile
+++ b/Makefile
@@ -504,6 +504,14 @@ clean:
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]*
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
+ rm -rf tests/asicworld/*.out tests/asicworld/*.log
+ rm -rf tests/hana/*.out tests/hana/*.log
+ rm -rf tests/simple/*.out tests/simple/*.log
+ rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp
+ rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log
+ rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp
+ rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
+ rm -f tests/tools/cmp_tbdata
clean-abc:
$(MAKE) -C abc DEP= clean
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index 5bf5a4c58..de0509930 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -112,10 +112,20 @@ struct AigerWriter
init_map[initsig[i]] = initval[i] == State::S1;
}
+ int index = 0;
for (auto bit : sigmap(wire))
{
if (bit.wire == nullptr)
+ {
+ if (wire->port_output) {
+ SigBit wirebit(wire, index);
+ aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
+ output_bits.insert(wirebit);
+ }
+
+ index++;
continue;
+ }
undriven_bits.insert(bit);
unused_bits.insert(bit);
@@ -125,6 +135,8 @@ struct AigerWriter
if (wire->port_output)
output_bits.insert(bit);
+
+ index++;
}
}
@@ -495,8 +507,12 @@ struct AigerWriter
for (int i = 0; i < GetSize(wire); i++)
{
- if (sig[i].wire == nullptr)
- continue;
+ if (sig[i].wire == nullptr) {
+ if (wire->port_output)
+ sig[i] = SigBit(wire, i);
+ else
+ continue;
+ }
if (wire->port_input) {
int a = aig_map.at(sig[i]);
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index ceca5b3f8..adf747034 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -33,6 +33,7 @@ aimfile = None
aiwfile = None
aigheader = True
vlogtbfile = None
+vlogtbtop = None
inconstr = list()
outconstr = None
gentrace = False
@@ -107,6 +108,11 @@ yosys-smtbmc [options] <yosys_smt2_output>
--dump-vlogtb <verilog_filename>
write trace as Verilog test bench
+ --vlogtb-top <hierarchical_name>
+ use the given entity as top module for the generated
+ Verilog test bench. The <hierarchical_name> is relative
+ to the design top module without the top module name.
+
--dump-smtc <constr_filename>
write trace as constraints file
@@ -126,7 +132,7 @@ yosys-smtbmc [options] <yosys_smt2_output>
try:
opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts +
["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader",
- "dump-vcd=", "dump-vlogtb=", "dump-smtc=", "dump-all", "noinfo", "append="])
+ "dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append="])
except:
usage()
@@ -165,6 +171,8 @@ for o, a in opts:
vcdfile = a
elif o == "--dump-vlogtb":
vlogtbfile = a
+ elif o == "--vlogtb-top":
+ vlogtbtop = a
elif o == "--dump-smtc":
outconstr = a
elif o == "--dump-all":
@@ -661,6 +669,15 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
filename = vlogtbfile.replace("%", index)
print_msg("Writing trace to Verilog testbench: %s" % (filename))
+ vlogtb_topmod = topmod
+ vlogtb_state = "s@@step_idx@@"
+
+ if vlogtbtop is not None:
+ for item in vlogtbtop.split("."):
+ assert item in smt.modinfo[vlogtb_topmod].cells
+ vlogtb_state = "(|%s_h %s| %s)" % (vlogtb_topmod, item, vlogtb_state)
+ vlogtb_topmod = smt.modinfo[vlogtb_topmod].cells[item]
+
with open(filename, "w") as f:
print("module testbench;", file=f)
print(" reg [4095:0] vcdfile;", file=f)
@@ -669,10 +686,10 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
primary_inputs = list()
clock_inputs = set()
- for name in smt.modinfo[topmod].inputs:
+ for name in smt.modinfo[vlogtb_topmod].inputs:
if name in ["clk", "clock", "CLK", "CLOCK"]:
clock_inputs.add(name)
- width = smt.modinfo[topmod].wsize[name]
+ width = smt.modinfo[vlogtb_topmod].wsize[name]
primary_inputs.append((name, width))
for name, width in primary_inputs:
@@ -681,7 +698,7 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
else:
print(" reg [%d:0] PI_%s;" % (width-1, name), file=f)
- print(" %s UUT (" % topmod, file=f)
+ print(" %s UUT (" % vlogtb_topmod, file=f)
print(",\n".join(" .{name}(PI_{name})".format(name=name) for name, _ in primary_inputs), file=f)
print(" );", file=f)
@@ -698,8 +715,8 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
print(" initial begin", file=f)
- regs = sorted(smt.hiernets(topmod, regs_only=True))
- regvals = smt.get_net_bin_list(topmod, regs, "s%d" % steps_start)
+ regs = sorted(smt.hiernets(vlogtb_topmod, regs_only=True))
+ regvals = smt.get_net_bin_list(vlogtb_topmod, regs, vlogtb_state.replace("@@step_idx@@", str(steps_start)))
print(" #1;", file=f)
for reg, val in zip(regs, regvals):
@@ -709,23 +726,23 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
hidden_net = True
print(" %sUUT.%s = %d'b%s;" % ("// " if hidden_net else "", ".".join(reg), len(val), val), file=f)
- anyconsts = sorted(smt.hieranyconsts(topmod))
+ anyconsts = sorted(smt.hieranyconsts(vlogtb_topmod))
for info in anyconsts:
if info[3] is not None:
- modstate = smt.net_expr(topmod, "s%d" % steps_start, info[0])
+ modstate = smt.net_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(steps_start)), info[0])
value = smt.bv2bin(smt.get("(|%s| %s)" % (info[1], modstate)))
print(" UUT.%s = %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
- mems = sorted(smt.hiermems(topmod))
+ mems = sorted(smt.hiermems(vlogtb_topmod))
for mempath in mems:
- abits, width, rports, wports = smt.mem_info(topmod, mempath)
+ abits, width, rports, wports = smt.mem_info(vlogtb_topmod, mempath)
addr_expr_list = list()
data_expr_list = list()
for i in range(steps_start, steps_stop):
for j in range(rports):
- addr_expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "R%dA" % j))
- data_expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "R%dD" % j))
+ addr_expr_list.append(smt.mem_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), mempath, "R%dA" % j))
+ data_expr_list.append(smt.mem_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), mempath, "R%dD" % j))
addr_list = smt.get_list(addr_expr_list)
data_list = smt.get_list(data_expr_list)
@@ -740,13 +757,13 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
for addr, data in addr_data.items():
print(" UUT.%s[%d'b%s] = %d'b%s;" % (".".join(mempath), len(addr), addr, len(data), data), file=f)
- anyseqs = sorted(smt.hieranyseqs(topmod))
+ anyseqs = sorted(smt.hieranyseqs(vlogtb_topmod))
for i in range(steps_start, steps_stop):
pi_names = [[name] for name, _ in primary_inputs if name not in clock_inputs]
- pi_values = smt.get_net_bin_list(topmod, pi_names, "s%d" % i)
+ pi_values = smt.get_net_bin_list(vlogtb_topmod, pi_names, vlogtb_state.replace("@@step_idx@@", str(i)))
- print(" #1;", file=f)
+ print("", file=f)
print(" // state %d" % i, file=f)
if i > 0:
print(" @(posedge clock);", file=f)
@@ -755,11 +772,11 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
for info in anyseqs:
if info[3] is not None:
- modstate = smt.net_expr(topmod, "s%d" % steps_start, info[0])
+ modstate = smt.net_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), info[0])
value = smt.bv2bin(smt.get("(|%s| %s)" % (info[1], modstate)))
- print(" UUT.%s = %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+ print(" UUT.%s <= %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
- print(" genclock = 0;", file=f)
+ print(" genclock <= 0;", file=f)
print(" end", file=f)
print("endmodule", file=f)
diff --git a/kernel/driver.cc b/kernel/driver.cc
index 7d714d079..1fe61b499 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -119,6 +119,29 @@ const char *prompt()
#else /* EMSCRIPTEN */
+#ifdef YOSYS_ENABLE_READLINE
+int yosys_history_offset = 0;
+std::string yosys_history_file;
+#endif
+
+void yosys_atexit()
+{
+#ifdef YOSYS_ENABLE_READLINE
+ if (!yosys_history_file.empty()) {
+ if (yosys_history_offset > 0) {
+ history_truncate_file(yosys_history_file.c_str(), 100);
+ append_history(where_history() - yosys_history_offset, yosys_history_file.c_str());
+ } else
+ write_history(yosys_history_file.c_str());
+ }
+
+ clear_history();
+ HIST_ENTRY **hist_list = history_list();
+ if (hist_list != NULL)
+ free(hist_list);
+#endif
+}
+
int main(int argc, char **argv)
{
std::string frontend_command = "auto";
@@ -137,12 +160,10 @@ int main(int argc, char **argv)
bool mode_q = false;
#ifdef YOSYS_ENABLE_READLINE
- int history_offset = 0;
- std::string history_file;
if (getenv("HOME") != NULL) {
- history_file = stringf("%s/.yosys_history", getenv("HOME"));
- read_history(history_file.c_str());
- history_offset = where_history();
+ yosys_history_file = stringf("%s/.yosys_history", getenv("HOME"));
+ read_history(yosys_history_file.c_str());
+ yosys_history_offset = where_history();
}
#endif
@@ -379,6 +400,7 @@ int main(int argc, char **argv)
log_hasher = new SHA1;
yosys_setup();
+ log_error_atexit = yosys_atexit;
for (auto &fn : plugin_filenames)
load_plugin(fn, {});
@@ -509,25 +531,12 @@ int main(int argc, char **argv)
}
#endif
+ yosys_atexit();
+
memhasher_off();
if (call_abort)
abort();
-#ifdef YOSYS_ENABLE_READLINE
- if (!history_file.empty()) {
- if (history_offset > 0) {
- history_truncate_file(history_file.c_str(), 100);
- append_history(where_history() - history_offset, history_file.c_str());
- } else
- write_history(history_file.c_str());
- }
-
- clear_history();
- HIST_ENTRY **hist_list = history_list();
- if (hist_list != NULL)
- free(hist_list);
-#endif
-
log_flush();
#if defined(_MSC_VER)
_exit(0);
diff --git a/kernel/log.cc b/kernel/log.cc
index c7240d540..3768922cd 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -52,6 +52,7 @@ bool log_cmd_error_throw = false;
bool log_quiet_warnings = false;
int log_verbose_level;
string log_last_error;
+void (*log_error_atexit)() = NULL;
vector<int> header_count;
pool<RTLIL::IdString> log_id_cache;
@@ -244,6 +245,9 @@ void logv_error(const char *format, va_list ap)
log("ERROR: %s", log_last_error.c_str());
log_flush();
+ if (log_error_atexit)
+ log_error_atexit();
+
#ifdef EMSCRIPTEN
log_files = backup_log_files;
throw 0;
diff --git a/kernel/log.h b/kernel/log.h
index 34c309016..6cae4431d 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -60,6 +60,7 @@ extern bool log_cmd_error_throw;
extern bool log_quiet_warnings;
extern int log_verbose_level;
extern string log_last_error;
+extern void (*log_error_atexit)();
void logv(const char *format, va_list ap);
void logv_header(RTLIL::Design *design, const char *format, va_list ap);
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 0a4ed1537..1dbb439ca 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -26,4 +26,5 @@ OBJS += passes/cmds/check.o
OBJS += passes/cmds/qwp.o
OBJS += passes/cmds/edgetypes.o
OBJS += passes/cmds/chformal.o
+OBJS += passes/cmds/chtype.o
diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc
new file mode 100644
index 000000000..90d51667c
--- /dev/null
+++ b/passes/cmds/chtype.cc
@@ -0,0 +1,83 @@
+/*
+ * 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"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ChtypePass : public Pass {
+ ChtypePass() : Pass("chtype", "change type of cells in the design") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" chtype [options] [selection]\n");
+ log("\n");
+ log("Change the types of cells in the design.\n");
+ log("\n");
+ log(" -set <type>\n");
+ log(" set the cell type to the given type\n");
+ log("\n");
+ log(" -map <old_type> <new_type>\n");
+ log(" change cells types that match <old_type> to <new_type>\n");
+ log("\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ IdString set_type;
+ dict<IdString, IdString> map_types;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (set_type == IdString() && args[argidx] == "-set" && argidx+1 < args.size()) {
+ set_type = RTLIL::escape_id(args[++argidx]);
+ continue;
+ }
+ if (args[argidx] == "-map" && argidx+2 < args.size()) {
+ IdString old_type = RTLIL::escape_id(args[++argidx]);
+ IdString new_type = RTLIL::escape_id(args[++argidx]);
+ map_types[old_type] = new_type;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (map_types.count(cell->type)) {
+ cell->type = map_types.at(cell->type);
+ continue;
+ }
+
+ if (set_type != IdString()) {
+ cell->type = set_type;
+ continue;
+ }
+ }
+ }
+ }
+} ChtypePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index fad1d9c0f..490c8dde5 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -81,6 +81,13 @@ struct DesignPass : public Pass {
log("Copy modules from the current design into the specified one.\n");
log("\n");
log("\n");
+ log(" design -import <name> [-as <new_top_name>] [selection]\n");
+ log("\n");
+ log("Import the specified design into the current design. The source design must\n");
+ log("either have a selected top module or the selection must contain exactly one\n");
+ log("module that is then used as top module for this command.\n");
+ log("\n");
+ log("\n");
log(" design -reset-vlog\n");
log("\n");
log("The Verilog front-end remembers defined macros and top-level declarations\n");
@@ -94,6 +101,7 @@ struct DesignPass : public Pass {
bool reset_vlog_mode = false;
bool push_mode = false;
bool pop_mode = false;
+ bool import_mode = false;
RTLIL::Design *copy_from_design = NULL, *copy_to_design = NULL;
std::string save_name, load_name, as_name;
std::vector<RTLIL::Module*> copy_src_modules;
@@ -156,8 +164,17 @@ struct DesignPass : public Pass {
copy_from_design = design;
continue;
}
- if (copy_from_design != NULL && args[argidx] == "-as" && argidx+1 < args.size()) {
+ if (!got_mode && args[argidx] == "-import" && argidx+1 < args.size()) {
got_mode = true;
+ import_mode = true;
+ if (saved_designs.count(args[++argidx]) == 0)
+ log_cmd_error("No saved design '%s' found!\n", args[argidx].c_str());
+ copy_from_design = saved_designs.at(args[argidx]);
+ copy_to_design = design;
+ as_name = args[argidx];
+ continue;
+ }
+ if (copy_from_design != NULL && args[argidx] == "-as" && argidx+1 < args.size()) {
as_name = args[++argidx];
continue;
}
@@ -166,10 +183,10 @@ struct DesignPass : public Pass {
if (copy_from_design != NULL)
{
- if (copy_from_design != design && argidx == args.size())
+ if (copy_from_design != design && argidx == args.size() && !import_mode)
cmd_error(args, argidx, "Missing selection.");
- RTLIL::Selection sel = design->selection_stack.back();
+ RTLIL::Selection sel;
if (argidx != args.size()) {
handle_extra_select_args(this, args, argidx, args.size(), copy_from_design);
sel = copy_from_design->selection_stack.back();
@@ -185,6 +202,17 @@ struct DesignPass : public Pass {
if (sel.selected_module(it.first))
log_cmd_error("Module %s is only partly selected.\n", RTLIL::id2cstr(it.first));
}
+
+ if (import_mode) {
+ for (auto module : copy_src_modules)
+ {
+ if (module->get_bool_attribute("\\top")) {
+ copy_src_modules.clear();
+ copy_src_modules.push_back(module);
+ break;
+ }
+ }
+ }
}
extra_args(args, argidx, design, false);
@@ -195,6 +223,68 @@ struct DesignPass : public Pass {
if (pop_mode && pushed_designs.empty())
log_cmd_error("No pushed designs.\n");
+ if (import_mode)
+ {
+ std::string prefix = RTLIL::escape_id(as_name);
+
+ pool<Module*> queue;
+ dict<IdString, IdString> done;
+
+ if (copy_to_design->modules_.count(prefix))
+ delete copy_to_design->modules_.at(prefix);
+
+ if (GetSize(copy_src_modules) != 1)
+ log_cmd_error("No top module found in source design.\n");
+
+ for (auto mod : copy_src_modules)
+ {
+ log("Importing %s as %s.\n", log_id(mod), log_id(prefix));
+
+ copy_to_design->modules_[prefix] = mod->clone();
+ copy_to_design->modules_[prefix]->name = prefix;
+ copy_to_design->modules_[prefix]->design = copy_to_design;
+ copy_to_design->modules_[prefix]->attributes.erase("\\top");
+
+ queue.insert(copy_to_design->modules_[prefix]);
+ done[mod->name] = prefix;
+ }
+
+ while (!queue.empty())
+ {
+ pool<Module*> old_queue;
+ old_queue.swap(queue);
+
+ for (auto mod : old_queue)
+ for (auto cell : mod->cells())
+ {
+ Module *fmod = copy_from_design->module(cell->type);
+
+ if (fmod == nullptr)
+ continue;
+
+ if (done.count(cell->type) == 0)
+ {
+ std::string trg_name = prefix + "." + (cell->type.c_str() + (*cell->type.c_str() == '\\'));
+
+ log("Importing %s as %s.\n", log_id(fmod), log_id(trg_name));
+
+ if (copy_to_design->modules_.count(trg_name))
+ delete copy_to_design->modules_.at(trg_name);
+
+ copy_to_design->modules_[trg_name] = fmod->clone();
+ copy_to_design->modules_[trg_name]->name = trg_name;
+ copy_to_design->modules_[trg_name]->design = copy_to_design;
+ copy_to_design->modules_[trg_name]->attributes.erase("\\top");
+
+ queue.insert(copy_to_design->modules_[trg_name]);
+ done[cell->type] = trg_name;
+ }
+
+ cell->type = done.at(cell->type);
+ }
+ }
+ }
+ else
if (copy_to_design != NULL)
{
if (!as_name.empty() && copy_src_modules.size() > 1)
@@ -206,6 +296,7 @@ struct DesignPass : public Pass {
if (copy_to_design->modules_.count(trg_name))
delete copy_to_design->modules_.at(trg_name);
+
copy_to_design->modules_[trg_name] = mod->clone();
copy_to_design->modules_[trg_name]->name = trg_name;
copy_to_design->modules_[trg_name]->design = copy_to_design;
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 07cdf4652..f9e40869d 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -371,13 +371,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (cell->type.in("$reduce_and", "$_AND_"))
detect_const_and = true;
- if (cell->type.in("$and", "$logic_and") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1)
+ if (cell->type.in("$and", "$logic_and") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1 && !cell->getParam("\\A_SIGNED").as_bool())
detect_const_and = true;
if (cell->type.in("$reduce_or", "$reduce_bool", "$_OR_"))
detect_const_or = true;
- if (cell->type.in("$or", "$logic_or") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1)
+ if (cell->type.in("$or", "$logic_or") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1 && !cell->getParam("\\A_SIGNED").as_bool())
detect_const_or = true;
if (detect_const_and || detect_const_or)
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index b63fd3c8d..93d9f012f 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -275,6 +275,8 @@ struct OptMergeWorker
ct.cell_types.erase("$pmux");
}
+ ct.cell_types.erase("$tribuf");
+ ct.cell_types.erase("$_TBUF_");
ct.cell_types.erase("$anyseq");
ct.cell_types.erase("$anyconst");
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index dd2469839..341e65ddc 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -92,6 +92,7 @@ struct gate_t
int in1, in2, in3, in4;
bool is_port;
RTLIL::SigBit bit;
+ RTLIL::State init;
};
bool map_mux4;
@@ -104,7 +105,9 @@ SigMap assign_map;
RTLIL::Module *module;
std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map;
+std::map<RTLIL::SigBit, RTLIL::State> signal_init;
pool<std::string> enabled_gates;
+bool recover_init;
bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig;
@@ -123,6 +126,10 @@ int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1,
gate.in4 = -1;
gate.is_port = false;
gate.bit = bit;
+ if (signal_init.count(bit))
+ gate.init = signal_init.at(bit);
+ else
+ gate.init = State::Sx;
signal_list.push_back(gate);
signal_map[bit] = gate.id;
}
@@ -609,11 +616,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
signal_map.clear();
signal_list.clear();
+ recover_init = false;
if (clk_str != "$")
{
- assign_map.set(module);
-
clk_polarity = true;
clk_sig = RTLIL::SigSpec();
@@ -621,6 +627,30 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
en_sig = RTLIL::SigSpec();
}
+ if (!clk_str.empty() && clk_str != "$")
+ {
+ if (clk_str.find(',') != std::string::npos) {
+ int pos = clk_str.find(',');
+ std::string en_str = clk_str.substr(pos+1);
+ clk_str = clk_str.substr(0, pos);
+ if (en_str[0] == '!') {
+ en_polarity = false;
+ en_str = en_str.substr(1);
+ }
+ if (module->wires_.count(RTLIL::escape_id(en_str)) != 0)
+ en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0));
+ }
+ if (clk_str[0] == '!') {
+ clk_polarity = false;
+ clk_str = clk_str.substr(1);
+ }
+ if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0)
+ clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0));
+ }
+
+ if (dff_mode && clk_sig.empty())
+ log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
+
std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
if (!cleanup)
tempdir_name[0] = tempdir_name[4] = '_';
@@ -693,30 +723,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
fprintf(f, "%s\n", abc_script.c_str());
fclose(f);
- if (!clk_str.empty() && clk_str != "$")
- {
- if (clk_str.find(',') != std::string::npos) {
- int pos = clk_str.find(',');
- std::string en_str = clk_str.substr(pos+1);
- clk_str = clk_str.substr(0, pos);
- if (en_str[0] == '!') {
- en_polarity = false;
- en_str = en_str.substr(1);
- }
- if (module->wires_.count(RTLIL::escape_id(en_str)) != 0)
- en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0));
- }
- if (clk_str[0] == '!') {
- clk_polarity = false;
- clk_str = clk_str.substr(1);
- }
- if (module->wires_.count(RTLIL::escape_id(clk_str)) != 0)
- clk_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(clk_str)), 0));
- }
-
- if (dff_mode && clk_sig.empty())
- log_error("Clock domain %s not found.\n", clk_str.c_str());
-
if (dff_mode || !clk_str.empty())
{
if (clk_sig.size() == 0)
@@ -849,7 +855,11 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
fprintf(f, "00-- 1\n");
fprintf(f, "--00 1\n");
} else if (si.type == G(FF)) {
- fprintf(f, ".latch n%d n%d\n", si.in1, si.id);
+ if (si.init == State::S0 || si.init == State::S1) {
+ fprintf(f, ".latch n%d n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0);
+ recover_init = true;
+ } else
+ fprintf(f, ".latch n%d n%d 2\n", si.in1, si.id);
} else if (si.type != G(NONE))
log_abort();
if (si.type != G(NONE))
@@ -1155,6 +1165,15 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
module->connect(conn);
}
+ if (recover_init)
+ for (auto wire : mapped_mod->wires()) {
+ if (wire->attributes.count("\\init")) {
+ Wire *w = module->wires_[remap_name(wire->name)];
+ log_assert(w->attributes.count("\\init") == 0);
+ w->attributes["\\init"] = wire->attributes.at("\\init");
+ }
+ }
+
for (auto &it : cell_stats)
log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
int in_wires = 0, out_wires = 0;
@@ -1369,6 +1388,11 @@ struct AbcPass : public Pass {
log_header(design, "Executing ABC pass (technology mapping using ABC).\n");
log_push();
+ assign_map.clear();
+ signal_list.clear();
+ signal_map.clear();
+ signal_init.clear();
+
#ifdef ABCEXTERNAL
std::string exe_file = ABCEXTERNAL;
#else
@@ -1610,163 +1634,188 @@ struct AbcPass : public Pass {
log_cmd_error("Got -constr but no -liberty!\n");
for (auto mod : design->selected_modules())
- if (mod->processes.size() > 0)
+ {
+ if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod));
- else if (!dff_mode || !clk_str.empty())
+ continue;
+ }
+
+ assign_map.set(mod);
+ signal_init.clear();
+
+ for (Wire *wire : mod->wires())
+ if (wire->attributes.count("\\init")) {
+ SigSpec initsig = assign_map(wire);
+ Const initval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
+ switch (initval[i]) {
+ case State::S0:
+ signal_init[initsig[i]] = State::S0;
+ break;
+ case State::S1:
+ signal_init[initsig[i]] = State::S0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!dff_mode || !clk_str.empty()) {
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode);
- else
- {
- assign_map.set(mod);
- CellTypes ct(design);
+ continue;
+ }
- std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
- std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());
+ CellTypes ct(design);
- std::set<RTLIL::Cell*> expand_queue, next_expand_queue;
- std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
- std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;
+ std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
+ std::set<RTLIL::Cell*> unassigned_cells(all_cells.begin(), all_cells.end());
- typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
- std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells;
- std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;
+ std::set<RTLIL::Cell*> expand_queue, next_expand_queue;
+ std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
+ std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;
- std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down;
- std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down;
+ typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
+ std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells;
+ std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;
- for (auto cell : all_cells)
- {
- clkdomain_t key;
-
- for (auto &conn : cell->connections())
- for (auto bit : conn.second) {
- bit = assign_map(bit);
- if (bit.wire != nullptr) {
- cell_to_bit[cell].insert(bit);
- bit_to_cell[bit].insert(cell);
- if (ct.cell_input(cell->type, conn.first)) {
- cell_to_bit_up[cell].insert(bit);
- bit_to_cell_down[bit].insert(cell);
- }
- if (ct.cell_output(cell->type, conn.first)) {
- cell_to_bit_down[cell].insert(bit);
- bit_to_cell_up[bit].insert(cell);
- }
- }
- }
+ std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_bit, cell_to_bit_up, cell_to_bit_down;
+ std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> bit_to_cell, bit_to_cell_up, bit_to_cell_down;
- if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
- {
- key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec());
- }
- else
- if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")
- {
- bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_";
- bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_";
- key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E")));
+ for (auto cell : all_cells)
+ {
+ clkdomain_t key;
+
+ for (auto &conn : cell->connections())
+ for (auto bit : conn.second) {
+ bit = assign_map(bit);
+ if (bit.wire != nullptr) {
+ cell_to_bit[cell].insert(bit);
+ bit_to_cell[bit].insert(cell);
+ if (ct.cell_input(cell->type, conn.first)) {
+ cell_to_bit_up[cell].insert(bit);
+ bit_to_cell_down[bit].insert(cell);
+ }
+ if (ct.cell_output(cell->type, conn.first)) {
+ cell_to_bit_down[cell].insert(bit);
+ bit_to_cell_up[bit].insert(cell);
+ }
}
- else
- continue;
-
- unassigned_cells.erase(cell);
- expand_queue.insert(cell);
- expand_queue_up.insert(cell);
- expand_queue_down.insert(cell);
-
- assigned_cells[key].push_back(cell);
- assigned_cells_reverse[cell] = key;
}
- while (!expand_queue_up.empty() || !expand_queue_down.empty())
+ if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
{
- if (!expand_queue_up.empty())
- {
- RTLIL::Cell *cell = *expand_queue_up.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
- expand_queue_up.erase(cell);
-
- for (auto bit : cell_to_bit_up[cell])
- for (auto c : bit_to_cell_up[bit])
- if (unassigned_cells.count(c)) {
- unassigned_cells.erase(c);
- next_expand_queue_up.insert(c);
- assigned_cells[key].push_back(c);
- assigned_cells_reverse[c] = key;
- expand_queue.insert(c);
- }
- }
+ key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec());
+ }
+ else
+ if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")
+ {
+ bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_";
+ bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_";
+ key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E")));
+ }
+ else
+ continue;
- if (!expand_queue_down.empty())
- {
- RTLIL::Cell *cell = *expand_queue_down.begin();
- clkdomain_t key = assigned_cells_reverse.at(cell);
- expand_queue_down.erase(cell);
-
- for (auto bit : cell_to_bit_down[cell])
- for (auto c : bit_to_cell_down[bit])
- if (unassigned_cells.count(c)) {
- unassigned_cells.erase(c);
- next_expand_queue_up.insert(c);
- assigned_cells[key].push_back(c);
- assigned_cells_reverse[c] = key;
- expand_queue.insert(c);
- }
- }
+ unassigned_cells.erase(cell);
+ expand_queue.insert(cell);
+ expand_queue_up.insert(cell);
+ expand_queue_down.insert(cell);
- if (expand_queue_up.empty() && expand_queue_down.empty()) {
- expand_queue_up.swap(next_expand_queue_up);
- expand_queue_down.swap(next_expand_queue_down);
- }
- }
+ assigned_cells[key].push_back(cell);
+ assigned_cells_reverse[cell] = key;
+ }
- while (!expand_queue.empty())
+ while (!expand_queue_up.empty() || !expand_queue_down.empty())
+ {
+ if (!expand_queue_up.empty())
{
- RTLIL::Cell *cell = *expand_queue.begin();
+ RTLIL::Cell *cell = *expand_queue_up.begin();
clkdomain_t key = assigned_cells_reverse.at(cell);
- expand_queue.erase(cell);
-
- for (auto bit : cell_to_bit.at(cell)) {
- for (auto c : bit_to_cell[bit])
- if (unassigned_cells.count(c)) {
- unassigned_cells.erase(c);
- next_expand_queue.insert(c);
- assigned_cells[key].push_back(c);
- assigned_cells_reverse[c] = key;
- }
- bit_to_cell[bit].clear();
- }
+ expand_queue_up.erase(cell);
+
+ for (auto bit : cell_to_bit_up[cell])
+ for (auto c : bit_to_cell_up[bit])
+ if (unassigned_cells.count(c)) {
+ unassigned_cells.erase(c);
+ next_expand_queue_up.insert(c);
+ assigned_cells[key].push_back(c);
+ assigned_cells_reverse[c] = key;
+ expand_queue.insert(c);
+ }
+ }
- if (expand_queue.empty())
- expand_queue.swap(next_expand_queue);
+ if (!expand_queue_down.empty())
+ {
+ RTLIL::Cell *cell = *expand_queue_down.begin();
+ clkdomain_t key = assigned_cells_reverse.at(cell);
+ expand_queue_down.erase(cell);
+
+ for (auto bit : cell_to_bit_down[cell])
+ for (auto c : bit_to_cell_down[bit])
+ if (unassigned_cells.count(c)) {
+ unassigned_cells.erase(c);
+ next_expand_queue_up.insert(c);
+ assigned_cells[key].push_back(c);
+ assigned_cells_reverse[c] = key;
+ expand_queue.insert(c);
+ }
}
- clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
- for (auto cell : unassigned_cells) {
- assigned_cells[key].push_back(cell);
- assigned_cells_reverse[cell] = key;
+ if (expand_queue_up.empty() && expand_queue_down.empty()) {
+ expand_queue_up.swap(next_expand_queue_up);
+ expand_queue_down.swap(next_expand_queue_down);
}
+ }
- log_header(design, "Summary of detected clock domains:\n");
- for (auto &it : assigned_cells)
- log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
- std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
- std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));
-
- for (auto &it : assigned_cells) {
- clk_polarity = std::get<0>(it.first);
- clk_sig = assign_map(std::get<1>(it.first));
- en_polarity = std::get<2>(it.first);
- en_sig = assign_map(std::get<3>(it.first));
- abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
- keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode);
- assign_map.set(mod);
+ while (!expand_queue.empty())
+ {
+ RTLIL::Cell *cell = *expand_queue.begin();
+ clkdomain_t key = assigned_cells_reverse.at(cell);
+ expand_queue.erase(cell);
+
+ for (auto bit : cell_to_bit.at(cell)) {
+ for (auto c : bit_to_cell[bit])
+ if (unassigned_cells.count(c)) {
+ unassigned_cells.erase(c);
+ next_expand_queue.insert(c);
+ assigned_cells[key].push_back(c);
+ assigned_cells_reverse[c] = key;
+ }
+ bit_to_cell[bit].clear();
}
+
+ if (expand_queue.empty())
+ expand_queue.swap(next_expand_queue);
}
+ clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
+ for (auto cell : unassigned_cells) {
+ assigned_cells[key].push_back(cell);
+ assigned_cells_reverse[cell] = key;
+ }
+
+ log_header(design, "Summary of detected clock domains:\n");
+ for (auto &it : assigned_cells)
+ log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
+ std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
+ std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));
+
+ for (auto &it : assigned_cells) {
+ clk_polarity = std::get<0>(it.first);
+ clk_sig = assign_map(std::get<1>(it.first));
+ en_polarity = std::get<2>(it.first);
+ en_sig = assign_map(std::get<3>(it.first));
+ abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
+ keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode);
+ assign_map.set(mod);
+ }
+ }
+
assign_map.clear();
signal_list.clear();
signal_map.clear();
+ signal_init.clear();
log_pop();
}
diff --git a/techlibs/greenpak4/greenpak4_counters.cc b/techlibs/greenpak4/greenpak4_counters.cc
index a7fd125d9..50a237b1b 100644
--- a/techlibs/greenpak4/greenpak4_counters.cc
+++ b/techlibs/greenpak4/greenpak4_counters.cc
@@ -280,7 +280,8 @@ void greenpak4_counters_worker(
ModIndex& index,
Cell *cell,
unsigned int& total_counters,
- pool<Cell*>& cells_to_remove)
+ pool<Cell*>& cells_to_remove,
+ pool<pair<Cell*, string>>& cells_to_rename)
{
SigMap& sigmap = index.sigmap;
@@ -376,6 +377,9 @@ void greenpak4_counters_worker(
if(extract.width > 8)
celltype = "\\GP_COUNT14";
+ //Get new cell name
+ string countname = string("$auto$GP_COUNTx$") + log_id(extract.rwire->name.str());
+
//Log it
total_counters ++;
string reset_type = "non-resettable";
@@ -384,9 +388,10 @@ void greenpak4_counters_worker(
//TODO: support other kind of reset
reset_type = "async resettable";
}
- log(" Found %d-bit %s down counter (counting from %d) for register %s declared at %s\n",
+ log(" Found %d-bit %s down counter %s (counting from %d) for register %s declared at %s\n",
extract.width,
reset_type.c_str(),
+ countname.c_str(),
extract.count_value,
log_id(extract.rwire->name),
count_reg_src.c_str());
@@ -445,6 +450,9 @@ void greenpak4_counters_worker(
cells_to_remove.insert(extract.count_mux);
cells_to_remove.insert(extract.count_reg);
cells_to_remove.insert(extract.underflow_inv);
+
+ //Finally, rename the cell
+ cells_to_rename.insert(pair<Cell*, string>(cell, countname));
}
struct Greenpak4CountersPass : public Pass {
@@ -478,13 +486,23 @@ struct Greenpak4CountersPass : public Pass {
for (auto module : design->selected_modules())
{
pool<Cell*> cells_to_remove;
+ pool<pair<Cell*, string>> cells_to_rename;
ModIndex index(module);
for (auto cell : module->selected_cells())
- greenpak4_counters_worker(index, cell, total_counters, cells_to_remove);
+ greenpak4_counters_worker(index, cell, total_counters, cells_to_remove, cells_to_rename);
for(auto cell : cells_to_remove)
+ {
+ //log("Removing cell %s\n", log_id(cell->name));
module->remove(cell);
+ }
+
+ for(auto cpair : cells_to_rename)
+ {
+ //log("Renaming cell %s to %s\n", log_id(cpair.first->name), cpair.second.c_str());
+ module->rename(cpair.first, cpair.second);
+ }
}
if(total_counters)