aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.travis/build-and-test.sh2
-rw-r--r--CHANGELOG2
-rw-r--r--backends/aiger/xaiger.cc17
-rw-r--r--backends/firrtl/firrtl.cc2
-rw-r--r--frontends/aiger/aigerparse.cc33
-rw-r--r--frontends/aiger/aigerparse.h2
-rw-r--r--frontends/ast/ast.cc2
-rw-r--r--frontends/verific/verific.cc63
-rw-r--r--frontends/verific/verific.h4
-rw-r--r--kernel/celltypes.h19
-rw-r--r--passes/opt/opt_lut.cc6
-rw-r--r--passes/pmgen/Makefile.inc10
-rw-r--r--passes/pmgen/ice40_wrapcarry.cc90
-rw-r--r--passes/pmgen/ice40_wrapcarry.pmg11
-rw-r--r--passes/proc/proc_prune.cc16
-rw-r--r--passes/techmap/abc.cc69
-rw-r--r--passes/techmap/abc9.cc37
-rw-r--r--techlibs/common/simlib.v44
-rw-r--r--techlibs/ice40/Makefile.inc1
-rw-r--r--techlibs/ice40/arith_map.v30
-rw-r--r--techlibs/ice40/cells_map.v23
-rw-r--r--techlibs/ice40/ice40_unlut.cc106
-rw-r--r--techlibs/ice40/synth_ice40.cc13
-rw-r--r--techlibs/ice40/tests/test_arith.ys9
-rw-r--r--tests/opt/opt_expr.ys (renamed from tests/various/opt_expr.ys)0
-rw-r--r--tests/opt/opt_ff.v21
-rw-r--r--tests/opt/opt_ff.ys3
-rw-r--r--tests/opt/opt_lut.ys4
-rw-r--r--tests/opt/opt_rmdff.v (renamed from tests/various/opt_rmdff.v)0
-rw-r--r--tests/opt/opt_rmdff.ys (renamed from tests/various/opt_rmdff.ys)0
-rw-r--r--tests/opt/opt_rmdff_sat.v (renamed from tests/opt/opt_ff_sat.v)0
-rw-r--r--tests/opt/opt_rmdff_sat.ys (renamed from tests/opt/opt_ff_sat.ys)2
-rw-r--r--tests/various/wreduce.ys33
33 files changed, 408 insertions, 266 deletions
diff --git a/.travis/build-and-test.sh b/.travis/build-and-test.sh
index b8c35041d..801407d1e 100755
--- a/.travis/build-and-test.sh
+++ b/.travis/build-and-test.sh
@@ -28,7 +28,7 @@ echo
echo 'Building...' && echo -en 'travis_fold:start:script.build\\r'
echo
-make
+make CC=$CC CXX=$CC LD=$CC
echo
echo -en 'travis_fold:end:script.build\\r'
diff --git a/CHANGELOG b/CHANGELOG
index 638c36121..21fb8a3f5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -19,6 +19,8 @@ Yosys 0.9 .. Yosys 0.9-dev
- Added automatic gzip compression (based on filename extension) for backends
- Improve attribute and parameter encoding in JSON to avoid ambiguities between
bit vectors and strings containing [01xz]*
+ - Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
+ - Removed "ice40_unlut"
Yosys 0.8 .. Yosys 0.8-dev
--------------------------
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 615854459..f49ecbeda 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -621,8 +621,7 @@ struct XAigerWriter
log_debug("boxNum = %d\n", GetSize(box_list));
write_h_buffer(box_list.size());
- RTLIL::Module *holes_module = nullptr;
- holes_module = module->design->addModule("$__holes__");
+ RTLIL::Module *holes_module = module->design->addModule("$__holes__");
log_assert(holes_module);
int port_id = 1;
@@ -719,27 +718,33 @@ struct XAigerWriter
Pass::call(holes_module->design, "flatten -wb");
// TODO: Should techmap/aigmap/check all lib_whitebox-es just once,
- // instead of per write_xaiger call
+ // instead of per write_xaiger call
Pass::call(holes_module->design, "techmap");
Pass::call(holes_module->design, "aigmap");
for (auto cell : holes_module->cells())
if (!cell->type.in("$_NOT_", "$_AND_"))
log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n");
- Pass::call(holes_module->design, "clean -purge");
+ holes_module->design->selection_stack.pop_back();
+
+ // Move into a new (temporary) design so that "clean" will only
+ // operate (and run checks on) this one module
+ RTLIL::Design *holes_design = new RTLIL::Design;
+ holes_module->design->modules_.erase(holes_module->name);
+ holes_design->add(holes_module);
+ Pass::call(holes_design, "clean -purge");
std::stringstream a_buffer;
XAigerWriter writer(holes_module, true /* holes_mode */);
writer.write_aiger(a_buffer, false /*ascii_mode*/);
- holes_module->design->selection_stack.pop_back();
+ delete holes_design;
f << "a";
std::string buffer_str = a_buffer.str();
int32_t buffer_size_be = to_big_endian(buffer_str.size());
f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
f.write(buffer_str.data(), buffer_str.size());
- holes_module->design->remove(holes_module);
log_pop();
}
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index 73b1e7d53..87db0edf7 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -943,7 +943,7 @@ struct FirrtlWorker
register_reverse_wire_map(y_id, cell->getPort("\\Y"));
continue;
}
- log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
+ log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
}
for (auto conn : module->connections())
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 4ecd01993..bd0596cc0 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -30,6 +30,7 @@
#include <libkern/OSByteOrder.h>
#define __builtin_bswap32 OSSwapInt32
#endif
+#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include "kernel/yosys.h"
@@ -337,7 +338,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
return wire;
}
-void AigerReader::parse_xaiger()
+void AigerReader::parse_xaiger(const dict<int,IdString> &box_lookup)
{
std::string header;
f >> header;
@@ -373,21 +374,6 @@ void AigerReader::parse_xaiger()
if (n0)
module->connect(n0, State::S0);
- dict<int,IdString> box_lookup;
- for (auto m : design->modules()) {
- auto it = m->attributes.find("\\abc_box_id");
- if (it == m->attributes.end())
- continue;
- if (m->name.begins_with("$paramod"))
- continue;
- auto id = it->second.as_int();
- auto r = box_lookup.insert(std::make_pair(id, m->name));
- if (!r.second)
- log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
- log_id(m), id, log_id(r.first->second));
- log_assert(r.second);
- }
-
// Parse footer (symbol table, comments, etc.)
std::string s;
bool comment_seen = false;
@@ -986,15 +972,16 @@ void AigerReader::post_process()
}
module->fixup_ports();
- design->add(module);
- design->selection_stack.emplace_back(false);
- RTLIL::Selection& sel = design->selection_stack.back();
- sel.select(module);
+ // Insert into a new (temporary) design so that "clean" will only
+ // operate (and run checks on) this one module
+ RTLIL::Design *mapped_design = new RTLIL::Design;
+ mapped_design->add(module);
+ Pass::call(mapped_design, "clean");
+ mapped_design->modules_.erase(module->name);
+ delete mapped_design;
- Pass::call(design, "clean");
-
- design->selection_stack.pop_back();
+ design->add(module);
for (auto cell : module->cells().to_vector()) {
if (cell->type != "$lut") continue;
diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h
index de3c3efbc..583c9d0f9 100644
--- a/frontends/aiger/aigerparse.h
+++ b/frontends/aiger/aigerparse.h
@@ -47,7 +47,7 @@ struct AigerReader
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports);
void parse_aiger();
- void parse_xaiger();
+ void parse_xaiger(const dict<int,IdString> &box_lookup);
void parse_aiger_ascii();
void parse_aiger_binary();
void post_process();
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 07ef0a86e..0d6626b19 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -1172,7 +1172,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
if (design->has((*it)->str)) {
RTLIL::Module *existing_mod = design->module((*it)->str);
- if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
+ if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s:%d.\n",
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 594da45eb..17c4a1e5b 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>
@@ -111,9 +112,10 @@ string get_full_netlist_name(Netlist *nl)
// ==================================================================
-VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover) :
+VerificImporter::VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit) :
mode_gates(mode_gates), mode_keep(mode_keep), mode_nosva(mode_nosva),
- mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover)
+ mode_names(mode_names), mode_verific(mode_verific), mode_autocover(mode_autocover),
+ mode_fullinit(mode_fullinit)
{
}
@@ -1454,6 +1456,50 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
merge_past_ffs(past_ffs);
}
+
+ if (!mode_fullinit)
+ {
+ pool<SigBit> non_ff_bits;
+ CellTypes ff_types;
+
+ ff_types.setup_internals_ff();
+ ff_types.setup_stdcells_mem();
+
+ for (auto cell : module->cells())
+ {
+ if (ff_types.cell_known(cell->type))
+ continue;
+
+ for (auto conn : cell->connections())
+ {
+ if (!cell->output(conn.first))
+ continue;
+
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr)
+ non_ff_bits.insert(bit);
+ }
+ }
+
+ for (auto wire : module->wires())
+ {
+ if (!wire->attributes.count("\\init"))
+ continue;
+
+ Const &initval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(initval); i++)
+ {
+ if (initval[i] != State::S0 && initval[i] != State::S1)
+ continue;
+
+ if (non_ff_bits.count(SigBit(wire, i)))
+ initval[i] = State::Sx;
+ }
+
+ if (initval.is_fully_undef())
+ wire->attributes.erase("\\init");
+ }
+ }
}
// ==================================================================
@@ -1829,7 +1875,7 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
while (!nl_todo.empty()) {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
- VerificImporter importer(false, false, false, false, false, false);
+ VerificImporter importer(false, false, false, false, false, false, false);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
@@ -1952,6 +1998,9 @@ struct VerificPass : public Pass {
log(" -autocover\n");
log(" Generate automatic cover statements for all asserts\n");
log("\n");
+ log(" -fullinit\n");
+ log(" Keep all register initializations, even those for non-FF registers.\n");
+ log("\n");
log(" -chparam name value \n");
log(" Elaborate the specified top modules (all modules when -all given) using\n");
log(" this parameter value. Modules on which this parameter does not exist will\n");
@@ -2213,7 +2262,7 @@ struct VerificPass : public Pass {
std::set<Netlist*> nl_todo, nl_done;
bool mode_all = false, mode_gates = false, mode_keep = false;
bool mode_nosva = false, mode_names = false, mode_verific = false;
- bool mode_autocover = false;
+ bool mode_autocover = false, mode_fullinit = false;
bool flatten = false, extnets = false;
string dumpfile;
Map parameters(STRING_HASH);
@@ -2255,6 +2304,10 @@ struct VerificPass : public Pass {
mode_autocover = true;
continue;
}
+ if (args[argidx] == "-fullinit") {
+ mode_fullinit = true;
+ continue;
+ }
if (args[argidx] == "-chparam" && argidx+2 < GetSize(args)) {
const std::string &key = args[++argidx];
const std::string &value = args[++argidx];
@@ -2378,7 +2431,7 @@ struct VerificPass : public Pass {
Netlist *nl = *nl_todo.begin();
if (nl_done.count(nl) == 0) {
VerificImporter importer(mode_gates, mode_keep, mode_nosva,
- mode_names, mode_verific, mode_autocover);
+ mode_names, mode_verific, mode_autocover, mode_fullinit);
importer.import_netlist(design, nl, nl_todo);
}
nl_todo.erase(nl);
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index 88a6cc0ba..5cbd78f7b 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -72,9 +72,9 @@ struct VerificImporter
pool<Verific::Net*, hash_ptr_ops> any_all_nets;
bool mode_gates, mode_keep, mode_nosva, mode_names, mode_verific;
- bool mode_autocover;
+ bool mode_autocover, mode_fullinit;
- VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover);
+ VerificImporter(bool mode_gates, bool mode_keep, bool mode_nosva, bool mode_names, bool mode_verific, bool mode_autocover, bool mode_fullinit);
RTLIL::SigBit net_map_at(Verific::Net *net);
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 7f1d35560..1256fbcba 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -139,13 +139,10 @@ struct CellTypes
setup_type("$fa", {A, B, C}, {X, Y}, true);
}
- void setup_internals_mem()
+ void setup_internals_ff()
{
IdString SET = "\\SET", CLR = "\\CLR", CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
- IdString Q = "\\Q", D = "\\D", ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN";
- IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
- IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
- IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
+ IdString Q = "\\Q", D = "\\D";
setup_type("$sr", {SET, CLR}, {Q});
setup_type("$ff", {D}, {Q});
@@ -156,6 +153,18 @@ struct CellTypes
setup_type("$dlatch", {EN, D}, {Q});
setup_type("$dlatchsr", {EN, SET, CLR, D}, {Q});
+ }
+
+ void setup_internals_mem()
+ {
+ setup_internals_ff();
+
+ IdString CLK = "\\CLK", ARST = "\\ARST", EN = "\\EN";
+ IdString ADDR = "\\ADDR", DATA = "\\DATA", RD_EN = "\\RD_EN";
+ IdString RD_CLK = "\\RD_CLK", RD_ADDR = "\\RD_ADDR", WR_CLK = "\\WR_CLK", WR_EN = "\\WR_EN";
+ IdString WR_ADDR = "\\WR_ADDR", WR_DATA = "\\WR_DATA", RD_DATA = "\\RD_DATA";
+ IdString CTRL_IN = "\\CTRL_IN", CTRL_OUT = "\\CTRL_OUT";
+
setup_type("$memrd", {CLK, EN, ADDR}, {DATA});
setup_type("$memwr", {CLK, EN, ADDR, DATA}, pool<RTLIL::IdString>());
setup_type("$meminit", {ADDR, DATA}, pool<RTLIL::IdString>());
diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc
index 587ef878a..4c199ba72 100644
--- a/passes/opt/opt_lut.cc
+++ b/passes/opt/opt_lut.cc
@@ -101,6 +101,12 @@ struct OptLutWorker
{
if (cell->type == "$lut")
{
+ if (cell->has_keep_attr())
+ continue;
+ SigBit lut_output = cell->getPort("\\Y");
+ if (lut_output.wire->get_bool_attribute("\\keep"))
+ continue;
+
int lut_width = cell->getParam("\\WIDTH").as_int();
SigSpec lut_input = cell->getPort("\\A");
int lut_arity = 0;
diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc
index 7911132db..c03606152 100644
--- a/passes/pmgen/Makefile.inc
+++ b/passes/pmgen/Makefile.inc
@@ -1,4 +1,5 @@
OBJS += passes/pmgen/ice40_dsp.o
+OBJS += passes/pmgen/ice40_wrapcarry.o
OBJS += passes/pmgen/peepopt.o
# --------------------------------------
@@ -12,6 +13,15 @@ passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg
# --------------------------------------
+passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h
+EXTRA_OBJS += passes/pmgen/ice40_wrapcarry_pm.h
+.SECONDARY: passes/pmgen/ice40_wrapcarry_pm.h
+
+passes/pmgen/ice40_wrapcarry_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_wrapcarry.pmg
+ $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_wrapcarry $(filter-out $<,$^)
+
+# --------------------------------------
+
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
EXTRA_OBJS += passes/pmgen/peepopt_pm.h
.SECONDARY: passes/pmgen/peepopt_pm.h
diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc
new file mode 100644
index 000000000..69ef3cd82
--- /dev/null
+++ b/passes/pmgen/ice40_wrapcarry.cc
@@ -0,0 +1,90 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+#include "passes/pmgen/ice40_wrapcarry_pm.h"
+
+void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
+{
+ auto &st = pm.st_ice40_wrapcarry;
+
+#if 0
+ log("\n");
+ log("carry: %s\n", log_id(st.carry, "--"));
+ log("lut: %s\n", log_id(st.lut, "--"));
+#endif
+
+ log(" replacing SB_LUT + SB_CARRY with $__ICE40_CARRY_WRAPPER cell.\n");
+
+ Cell *cell = pm.module->addCell(NEW_ID, "$__ICE40_CARRY_WRAPPER");
+ pm.module->swap_names(cell, st.carry);
+
+ cell->setPort("\\A", st.carry->getPort("\\I0"));
+ cell->setPort("\\B", st.carry->getPort("\\I1"));
+ cell->setPort("\\CI", st.carry->getPort("\\CI"));
+ cell->setPort("\\CO", st.carry->getPort("\\CO"));
+
+ cell->setPort("\\I0", st.lut->getPort("\\I0"));
+ cell->setPort("\\I3", st.lut->getPort("\\I3"));
+ cell->setPort("\\O", st.lut->getPort("\\O"));
+ cell->setParam("\\LUT", st.lut->getParam("\\LUT_INIT"));
+
+ pm.autoremove(st.carry);
+ pm.autoremove(st.lut);
+}
+
+struct Ice40WrapCarryPass : public Pass {
+ Ice40WrapCarryPass() : Pass("ice40_wrapcarry", "iCE40: wrap carries") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" ice40_wrapcarry [selection]\n");
+ log("\n");
+ log("Wrap manually instantiated SB_CARRY cells, along with their associated SB_LUTs,\n");
+ log("into an internal $__ICE40_CARRY_WRAPPER cell for preservation across technology\n");
+ log("mapping.");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing ICE40_WRAPCARRY pass (wrap carries).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-singleton") {
+ // singleton_mode = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
+ }
+} Ice40WrapCarryPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/pmgen/ice40_wrapcarry.pmg b/passes/pmgen/ice40_wrapcarry.pmg
new file mode 100644
index 000000000..9e64c7467
--- /dev/null
+++ b/passes/pmgen/ice40_wrapcarry.pmg
@@ -0,0 +1,11 @@
+pattern ice40_wrapcarry
+
+match carry
+ select carry->type.in(\SB_CARRY)
+endmatch
+
+match lut
+ select lut->type.in(\SB_LUT4)
+ index <SigSpec> port(lut, \I1) === port(carry, \I0)
+ index <SigSpec> port(lut, \I2) === port(carry, \I1)
+endmatch
diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc
index b47ee79c2..d4aee9df0 100644
--- a/passes/proc/proc_prune.cc
+++ b/passes/proc/proc_prune.cc
@@ -65,8 +65,7 @@ struct PruneWorker
pool<RTLIL::SigBit> sw_assigned = do_switch((*it), assigned, affected);
assigned.insert(sw_assigned.begin(), sw_assigned.end());
}
- pool<RTLIL::SigSig> remove;
- for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ++it) {
+ for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ) {
RTLIL::SigSpec lhs = sigmap(it->first);
bool redundant = true;
for (auto &bit : lhs) {
@@ -75,9 +74,10 @@ struct PruneWorker
break;
}
}
+ bool remove = false;
if (redundant) {
removed_count++;
- remove.insert(*it);
+ remove = true;
} else {
if (root) {
bool promotable = true;
@@ -99,7 +99,7 @@ struct PruneWorker
}
promoted_count++;
module->connect(conn);
- remove.insert(*it);
+ remove = true;
}
}
for (auto &bit : lhs)
@@ -109,11 +109,9 @@ struct PruneWorker
if (bit.wire)
affected.insert(bit);
}
- }
- for (auto it = cs->actions.begin(); it != cs->actions.end(); ) {
- if (remove[*it]) {
- it = cs->actions.erase(it);
- } else it++;
+ if (remove)
+ cs->actions.erase((it++).base() - 1);
+ else it++;
}
return assigned;
}
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 9db8aafa7..9f963a8bf 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -941,33 +941,33 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_BUF_"));
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOT_"));
- if (enabled_gates.empty() || enabled_gates.count("AND"))
+ if (enabled_gates.count("AND"))
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_AND_"));
- if (enabled_gates.empty() || enabled_gates.count("NAND"))
+ if (enabled_gates.count("NAND"))
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NAND_"));
- if (enabled_gates.empty() || enabled_gates.count("OR"))
+ if (enabled_gates.count("OR"))
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_OR_"));
- if (enabled_gates.empty() || enabled_gates.count("NOR"))
+ if (enabled_gates.count("NOR"))
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOR_"));
- if (enabled_gates.empty() || enabled_gates.count("XOR"))
+ if (enabled_gates.count("XOR"))
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_"));
- if (enabled_gates.empty() || enabled_gates.count("XNOR"))
+ if (enabled_gates.count("XNOR"))
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_"));
- if (enabled_gates.empty() || enabled_gates.count("ANDNOT"))
+ if (enabled_gates.count("ANDNOT"))
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_"));
- if (enabled_gates.empty() || enabled_gates.count("ORNOT"))
+ if (enabled_gates.count("ORNOT"))
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_"));
- if (enabled_gates.empty() || enabled_gates.count("AOI3"))
+ if (enabled_gates.count("AOI3"))
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI3_"));
- if (enabled_gates.empty() || enabled_gates.count("OAI3"))
+ if (enabled_gates.count("OAI3"))
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI3_"));
- if (enabled_gates.empty() || enabled_gates.count("AOI4"))
+ if (enabled_gates.count("AOI4"))
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI4_"));
- if (enabled_gates.empty() || enabled_gates.count("OAI4"))
+ if (enabled_gates.count("OAI4"))
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI4_"));
- if (enabled_gates.empty() || enabled_gates.count("MUX"))
+ if (enabled_gates.count("MUX"))
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_"));
- if (enabled_gates.empty() || enabled_gates.count("NMUX"))
+ if (enabled_gates.count("NMUX"))
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_"));
if (map_mux4)
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_"));
@@ -1411,7 +1411,9 @@ struct AbcPass : public Pass {
// log("\n");
log(" -g type1,type2,...\n");
log(" Map to the specified list of gate types. Supported gates types are:\n");
- log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n");
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log(" AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX,\n");
+ log(" NMUX, AOI3, OAI3, AOI4, OAI4.\n");
log(" (The NOT gate is always added to this list automatically.)\n");
log("\n");
log(" The following aliases can be used to reference common sets of gate types:\n");
@@ -1423,9 +1425,13 @@ struct AbcPass : public Pass {
log(" gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
log(" aig: AND NAND OR NOR ANDNOT ORNOT\n");
log("\n");
+ log(" The alias 'all' represent the full set of all gate types.\n");
+ log("\n");
log(" Prefix a gate type with a '-' to remove it from the list. For example\n");
log(" the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\n");
log("\n");
+ log(" The default is 'all,-NMUX,-AOI3,-OAI3,-AOI4,-OAI4'.\n");
+ log("\n");
log(" -dff\n");
log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
log(" clock domains are automatically partitioned in clock domains and each\n");
@@ -1701,6 +1707,22 @@ struct AbcPass : public Pass {
gate_list.push_back("ORNOT");
goto ok_alias;
}
+ if (g == "all") {
+ gate_list.push_back("AND");
+ gate_list.push_back("NAND");
+ gate_list.push_back("OR");
+ gate_list.push_back("NOR");
+ gate_list.push_back("XOR");
+ gate_list.push_back("XNOR");
+ gate_list.push_back("ANDNOT");
+ gate_list.push_back("ORNOT");
+ gate_list.push_back("AOI3");
+ gate_list.push_back("OAI3");
+ gate_list.push_back("AOI4");
+ gate_list.push_back("OAI4");
+ gate_list.push_back("MUX");
+ gate_list.push_back("NMUX");
+ }
cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));
ok_gate:
gate_list.push_back(g);
@@ -1752,6 +1774,23 @@ struct AbcPass : public Pass {
if (!constr_file.empty() && liberty_file.empty())
log_cmd_error("Got -constr but no -liberty!\n");
+ if (enabled_gates.empty()) {
+ enabled_gates.insert("AND");
+ enabled_gates.insert("NAND");
+ enabled_gates.insert("OR");
+ enabled_gates.insert("NOR");
+ enabled_gates.insert("XOR");
+ enabled_gates.insert("XNOR");
+ enabled_gates.insert("ANDNOT");
+ enabled_gates.insert("ORNOT");
+ // enabled_gates.insert("AOI3");
+ // enabled_gates.insert("OAI3");
+ // enabled_gates.insert("AOI4");
+ // enabled_gates.insert("OAI4");
+ enabled_gates.insert("MUX");
+ // enabled_gates.insert("NMUX");
+ }
+
for (auto mod : design->selected_modules())
{
if (mod->processes.size() > 0) {
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 31c1d6f80..7418ed4a3 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -82,7 +82,7 @@ void handle_loops(RTLIL::Design *design)
{
Pass::call(design, "scc -set_attr abc_scc_id {}");
- dict<IdString, vector<IdString>> abc_scc_break;
+ dict<IdString, vector<IdString>> abc_scc_break;
// For every unique SCC found, (arbitrarily) find the first
// cell in the component, and select (and mark) all its output
@@ -290,7 +290,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
bool show_tempdir, std::string box_file, std::string lut_file,
- std::string wire_delay)
+ std::string wire_delay, const dict<int,IdString> &box_lookup)
{
module = current_module;
map_autoidx = autoidx++;
@@ -429,10 +429,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
RTLIL::Selection& sel = design->selection_stack.back();
sel.select(module);
- Pass::call(design, "aigmap");
-
handle_loops(design);
+ Pass::call(design, "aigmap");
+
//log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
// count_gates, GetSize(signal_list), count_input, count_output);
@@ -476,7 +476,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
module->fixup_ports();
-
log_header(design, "Executing ABC9.\n");
if (!lut_costs.empty()) {
@@ -520,8 +519,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
log_assert(!design->module("$__abc9__"));
+
AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
- reader.parse_xaiger();
+ reader.parse_xaiger(box_lookup);
ifs.close();
#if 0
@@ -646,6 +646,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
}
else {
existing_cell = module->cell(c->name);
+ log_assert(existing_cell);
cell = module->addCell(remap_name(c->name), c->type);
module->swap_names(cell, existing_cell);
}
@@ -1081,6 +1082,21 @@ struct Abc9Pass : public Pass {
}
extra_args(args, argidx, design);
+ dict<int,IdString> box_lookup;
+ for (auto m : design->modules()) {
+ auto it = m->attributes.find("\\abc_box_id");
+ if (it == m->attributes.end())
+ continue;
+ if (m->name.begins_with("$paramod"))
+ continue;
+ auto id = it->second.as_int();
+ auto r = box_lookup.insert(std::make_pair(id, m->name));
+ if (!r.second)
+ log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n",
+ log_id(m), id, log_id(r.first->second));
+ log_assert(r.second);
+ }
+
for (auto mod : design->selected_modules())
{
if (mod->attributes.count("\\abc_box_id"))
@@ -1096,7 +1112,7 @@ struct Abc9Pass : public Pass {
if (!dff_mode || !clk_str.empty()) {
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay);
+ box_file, lut_file, wire_delay, box_lookup);
continue;
}
@@ -1242,15 +1258,16 @@ struct Abc9Pass : public Pass {
en_sig = assign_map(std::get<3>(it.first));
abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
- box_file, lut_file, wire_delay);
+ box_file, lut_file, wire_delay, box_lookup);
assign_map.set(mod);
}
}
- Pass::call(design, "clean");
-
assign_map.clear();
+ // The "clean" pass also contains a design->check() call
+ Pass::call(design, "clean");
+
log_pop();
}
} Abc9Pass;
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index a424d3089..7845a3fed 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -532,14 +532,26 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $lcu (P, G, CI, CO)
+//-
+//- Lookahead carry unit
+//- A building block dedicated to fast computation of carry-bits used in binary
+//- arithmetic operations. By replacing the ripple carry structure used in full-adder
+//- blocks, the more significant bits of the sum can be expected to be computed more
+//- quickly.
+//- Typically created during `techmap` of $alu cells (see the "_90_alu" rule in
+//- +/techmap.v).
module \$lcu (P, G, CI, CO);
parameter WIDTH = 1;
-input [WIDTH-1:0] P, G;
-input CI;
+input [WIDTH-1:0] P; // Propagate
+input [WIDTH-1:0] G; // Generate
+input CI; // Carry-in
-output reg [WIDTH-1:0] CO;
+output reg [WIDTH-1:0] CO; // Carry-out
integer i;
always @* begin
@@ -555,6 +567,17 @@ endmodule
// --------------------------------------------------------
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $alu (A, B, CI, BI, X, Y, CO)
+//-
+//- Arithmetic logic unit.
+//- A building block supporting both binary addition/subtraction operations, and
+//- indirectly, comparison operations.
+//- Typically created by the `alumacc` pass, which transforms:
+//- $add, $sub, $lt, $le, $ge, $gt, $eq, $eqx, $ne, $nex
+//- cells into this $alu cell.
+//-
module \$alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
@@ -563,12 +586,16 @@ parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
-input [A_WIDTH-1:0] A;
-input [B_WIDTH-1:0] B;
-output [Y_WIDTH-1:0] X, Y;
+input [A_WIDTH-1:0] A; // Input operand
+input [B_WIDTH-1:0] B; // Input operand
+output [Y_WIDTH-1:0] X; // A xor B (sign-extended, optional B inversion,
+ // used in combination with
+ // reduction-AND for $eq/$ne ops)
+output [Y_WIDTH-1:0] Y; // Sum
-input CI, BI;
-output [Y_WIDTH-1:0] CO;
+input CI; // Carry-in (set for $sub)
+input BI; // Invert-B (set for $sub)
+output [Y_WIDTH-1:0] CO; // Carry-out
wire [Y_WIDTH-1:0] AA, BB;
@@ -584,6 +611,7 @@ endgenerate
wire y_co_undef = ^{A, A, B, B, CI, CI, BI, BI};
assign X = AA ^ BB;
+// Full adder
assign Y = (AA + BB + CI) ^ {Y_WIDTH{y_co_undef}};
function get_carry;
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index d258d5a5d..76a89b107 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -4,7 +4,6 @@ OBJS += techlibs/ice40/ice40_braminit.o
OBJS += techlibs/ice40/ice40_ffssr.o
OBJS += techlibs/ice40/ice40_ffinit.o
OBJS += techlibs/ice40/ice40_opt.o
-OBJS += techlibs/ice40/ice40_unlut.o
GENFILES += techlibs/ice40/brams_init1.vh
GENFILES += techlibs/ice40/brams_init2.vh
diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v
index fe83a8e38..26b24db9e 100644
--- a/techlibs/ice40/arith_map.v
+++ b/techlibs/ice40/arith_map.v
@@ -44,35 +44,21 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
-`ifdef _ABC
- \$__ICE40_FULL_ADDER carry (
+ \$__ICE40_CARRY_WRAPPER #(
+ // A[0]: 1010 1010 1010 1010
+ // A[1]: 1100 1100 1100 1100
+ // A[2]: 1111 0000 1111 0000
+ // A[3]: 1111 1111 0000 0000
+ .LUT(16'b 0110_1001_1001_0110)
+ ) fadd (
.A(AA[i]),
.B(BB[i]),
.CI(C[i]),
- .CO(CO[i]),
- .O(Y[i])
- );
-`else
- SB_CARRY carry (
- .I0(AA[i]),
- .I1(BB[i]),
- .CI(C[i]),
- .CO(CO[i])
- );
- SB_LUT4 #(
- // I0: 1010 1010 1010 1010
- // I1: 1100 1100 1100 1100
- // I2: 1111 0000 1111 0000
- // I3: 1111 1111 0000 0000
- .LUT_INIT(16'b 0110_1001_1001_0110)
- ) adder (
.I0(1'b0),
- .I1(AA[i]),
- .I2(BB[i]),
.I3(C[i]),
+ .CO(CO[i]),
.O(Y[i])
);
-`endif
end endgenerate
assign X = AA ^ BB;
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index b4b831165..0c10c9ac4 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -62,26 +62,21 @@ module \$lut (A, Y);
endmodule
`endif
-`ifdef _ABC
-module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
+`ifndef NO_ADDER
+module \$__ICE40_CARRY_WRAPPER (output CO, O, input A, B, CI, I0, I3);
+ parameter LUT = 0;
SB_CARRY carry (
.I0(A),
.I1(B),
.CI(CI),
.CO(CO)
);
- SB_LUT4 #(
- // I0: 1010 1010 1010 1010
- // I1: 1100 1100 1100 1100
- // I2: 1111 0000 1111 0000
- // I3: 1111 1111 0000 0000
- .LUT_INIT(16'b 0110_1001_1001_0110)
- ) adder (
- .I0(1'b0),
- .I1(A),
- .I2(B),
- .I3(CI),
- .O(O)
+ \$lut #(
+ .WIDTH(4),
+ .LUT(LUT)
+ ) lut (
+ .A({I3,B,A,I0}),
+ .Y(O)
);
endmodule
`endif
diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc
deleted file mode 100644
index f3f70ac1f..000000000
--- a/techlibs/ice40/ice40_unlut.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-#include <stdlib.h>
-#include <stdio.h>
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-static SigBit get_bit_or_zero(const SigSpec &sig)
-{
- if (GetSize(sig) == 0)
- return State::S0;
- return sig[0];
-}
-
-static void run_ice40_unlut(Module *module)
-{
- SigMap sigmap(module);
-
- for (auto cell : module->selected_cells())
- {
- if (cell->type == "\\SB_LUT4")
- {
- SigSpec inbits;
-
- inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
- inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
- inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
- inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
- sigmap.apply(inbits);
-
- log("Mapping SB_LUT4 cell %s.%s to $lut.\n", log_id(module), log_id(cell));
-
- cell->type ="$lut";
- cell->setParam("\\WIDTH", 4);
- cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
- cell->unsetParam("\\LUT_INIT");
-
- cell->setPort("\\A", SigSpec({
- get_bit_or_zero(cell->getPort("\\I0")),
- get_bit_or_zero(cell->getPort("\\I1")),
- get_bit_or_zero(cell->getPort("\\I2")),
- get_bit_or_zero(cell->getPort("\\I3"))
- }));
- cell->setPort("\\Y", cell->getPort("\\O")[0]);
- cell->unsetPort("\\I0");
- cell->unsetPort("\\I1");
- cell->unsetPort("\\I2");
- cell->unsetPort("\\I3");
- cell->unsetPort("\\O");
-
- cell->check();
- }
- }
-}
-
-struct Ice40UnlutPass : public Pass {
- Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SB_LUT4 cells to $lut cells") { }
- void help() YS_OVERRIDE
- {
- // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
- log("\n");
- log(" ice40_unlut [options] [selection]\n");
- log("\n");
- log("This command transforms all SB_LUT4 cells to generic $lut cells.\n");
- log("\n");
- }
- void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
- {
- log_header(design, "Executing ICE40_UNLUT pass (convert SB_LUT4 to $lut).\n");
- log_push();
-
- size_t argidx;
- for (argidx = 1; argidx < args.size(); argidx++) {
- // if (args[argidx] == "-???") {
- // continue;
- // }
- break;
- }
- extra_args(args, argidx, design);
-
- for (auto module : design->selected_modules())
- run_ice40_unlut(module);
- }
-} Ice40UnlutPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index dc04eed67..c6de81bd9 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -238,7 +238,7 @@ struct SynthIce40Pass : public ScriptPass
{
if (check_label("begin"))
{
- run("read_verilog -icells -lib -D_ABC +/ice40/cells_sim.v");
+ run("read_verilog -icells -lib +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
run("proc");
}
@@ -293,8 +293,10 @@ struct SynthIce40Pass : public ScriptPass
{
if (nocarry)
run("techmap");
- else
- run("techmap -map +/techmap.v -map +/ice40/arith_map.v" + std::string(abc == "abc9" ? " -D _ABC" : ""));
+ else {
+ run("ice40_wrapcarry");
+ run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
+ }
if (retime || help_mode)
run(abc + " -dff", "(only if -retime)");
run("ice40_opt");
@@ -309,7 +311,7 @@ struct SynthIce40Pass : public ScriptPass
run("opt_merge");
run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
}
- run("techmap -D NO_LUT -map +/ice40/cells_map.v");
+ run("techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
run("ice40_ffinit");
@@ -338,13 +340,12 @@ struct SynthIce40Pass : public ScriptPass
else
wire_delay = 250;
run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
- run("techmap -D NO_LUT -D _ABC -map +/ice40/cells_map.v");
}
else
run(abc + " -dress -lut 4", "(skip if -noabc)");
}
+ run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("clean");
- run("ice40_unlut");
run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
}
diff --git a/techlibs/ice40/tests/test_arith.ys b/techlibs/ice40/tests/test_arith.ys
index 160c767fb..ddb80b700 100644
--- a/techlibs/ice40/tests/test_arith.ys
+++ b/techlibs/ice40/tests/test_arith.ys
@@ -1,6 +1,5 @@
read_verilog test_arith.v
synth_ice40
-techmap -map ../cells_sim.v
rename test gate
read_verilog test_arith.v
@@ -8,3 +7,11 @@ rename test gold
miter -equiv -flatten -make_outputs gold gate miter
sat -verify -prove trigger 0 -show-ports miter
+
+synth_ice40 -top gate
+
+read_verilog test_arith.v
+rename test gold
+
+miter -equiv -flatten -make_outputs gold gate miter
+sat -verify -prove trigger 0 -show-ports miter
diff --git a/tests/various/opt_expr.ys b/tests/opt/opt_expr.ys
index 0c61ac881..0c61ac881 100644
--- a/tests/various/opt_expr.ys
+++ b/tests/opt/opt_expr.ys
diff --git a/tests/opt/opt_ff.v b/tests/opt/opt_ff.v
deleted file mode 100644
index a01b64b61..000000000
--- a/tests/opt/opt_ff.v
+++ /dev/null
@@ -1,21 +0,0 @@
-module top(
- input clk,
- input rst,
- input [2:0] a,
- output [1:0] b
-);
- reg [2:0] b_reg;
- initial begin
- b_reg <= 3'b0;
- end
-
- assign b = b_reg[1:0];
- always @(posedge clk or posedge rst) begin
- if(rst) begin
- b_reg <= 3'b0;
- end else begin
- b_reg <= a;
- end
- end
-endmodule
-
diff --git a/tests/opt/opt_ff.ys b/tests/opt/opt_ff.ys
deleted file mode 100644
index 704c7acf3..000000000
--- a/tests/opt/opt_ff.ys
+++ /dev/null
@@ -1,3 +0,0 @@
-read_verilog opt_ff.v
-synth_ice40
-ice40_unlut
diff --git a/tests/opt/opt_lut.ys b/tests/opt/opt_lut.ys
index 59b12c351..a9fccbb62 100644
--- a/tests/opt/opt_lut.ys
+++ b/tests/opt/opt_lut.ys
@@ -1,4 +1,2 @@
read_verilog opt_lut.v
-synth_ice40
-ice40_unlut
-equiv_opt -map +/ice40/cells_sim.v -assert opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3
+equiv_opt -map +/ice40/cells_sim.v -assert synth_ice40
diff --git a/tests/various/opt_rmdff.v b/tests/opt/opt_rmdff.v
index b1c06703c..b1c06703c 100644
--- a/tests/various/opt_rmdff.v
+++ b/tests/opt/opt_rmdff.v
diff --git a/tests/various/opt_rmdff.ys b/tests/opt/opt_rmdff.ys
index 081f81782..081f81782 100644
--- a/tests/various/opt_rmdff.ys
+++ b/tests/opt/opt_rmdff.ys
diff --git a/tests/opt/opt_ff_sat.v b/tests/opt/opt_rmdff_sat.v
index 5a0a6fe37..5a0a6fe37 100644
--- a/tests/opt/opt_ff_sat.v
+++ b/tests/opt/opt_rmdff_sat.v
diff --git a/tests/opt/opt_ff_sat.ys b/tests/opt/opt_rmdff_sat.ys
index 4e7cc6ca4..1c3dd9c05 100644
--- a/tests/opt/opt_ff_sat.ys
+++ b/tests/opt/opt_rmdff_sat.ys
@@ -1,4 +1,4 @@
-read_verilog opt_ff_sat.v
+read_verilog opt_rmdff_sat.v
prep -flatten
opt_rmdff -sat
synth
diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys
index 4257292f5..2e0812c48 100644
--- a/tests/various/wreduce.ys
+++ b/tests/various/wreduce.ys
@@ -36,7 +36,6 @@ design -save gold
opt_expr
wreduce
-dump
select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i
design -stash gate
@@ -46,3 +45,35 @@ design -import gate -as gate
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
+
+##########
+
+# Testcase from: https://github.com/YosysHQ/yosys/commit/25680f6a078bb32f157bd580705656496717bafb
+design -reset
+read_verilog <<EOT
+module top(
+ input clk,
+ input rst,
+ input [2:0] a,
+ output [1:0] b
+);
+ reg [2:0] b_reg;
+ initial begin
+ b_reg <= 3'b0;
+ end
+
+ assign b = b_reg[1:0];
+ always @(posedge clk or posedge rst) begin
+ if(rst) begin
+ b_reg <= 3'b0;
+ end else begin
+ b_reg <= a;
+ end
+ end
+endmodule
+EOT
+
+proc
+wreduce
+
+select -assert-count 1 t:$adff r:ARST_VALUE=2'b00 %i