aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2019-04-22 11:58:59 -0700
committerEddie Hung <eddie@fpgeh.com>2019-04-22 11:58:59 -0700
commit4cfef7897f4bac285853bf0f08ae366523ae76b4 (patch)
tree238a71ec6696966652211fb79bd52c3c8c97eee7
parent4486a98fd5928a4e3cdf9cd27c27b7dd821513bb (diff)
parenteaf3c247729365cec776e147f380ce59f7dccd4d (diff)
downloadyosys-4cfef7897f4bac285853bf0f08ae366523ae76b4.tar.gz
yosys-4cfef7897f4bac285853bf0f08ae366523ae76b4.tar.bz2
yosys-4cfef7897f4bac285853bf0f08ae366523ae76b4.zip
Merge branch 'xaig' into xc7mux
-rw-r--r--backends/aiger/aiger.cc2
-rw-r--r--backends/aiger/xaiger.cc325
-rw-r--r--backends/json/json.cc115
-rw-r--r--backends/verilog/verilog_backend.cc8
-rw-r--r--frontends/aiger/aigerparse.cc10
-rw-r--r--frontends/ast/simplify.cc21
-rw-r--r--kernel/driver.cc8
-rw-r--r--kernel/log.cc7
-rw-r--r--kernel/log.h43
-rw-r--r--kernel/register.cc1
-rw-r--r--passes/cmds/trace.cc34
-rw-r--r--passes/opt/opt_clean.cc11
-rw-r--r--passes/opt/opt_expr.cc79
-rw-r--r--passes/opt/opt_merge.cc8
-rw-r--r--passes/opt/opt_muxtree.cc6
-rw-r--r--passes/opt/pmux2shiftx.cc23
-rw-r--r--passes/techmap/abc9.cc8
-rw-r--r--passes/techmap/techmap.cc37
-rw-r--r--techlibs/ice40/Makefile.inc6
-rw-r--r--techlibs/ice40/abc_hx.box113
-rw-r--r--techlibs/ice40/abc_hx.lut6
-rw-r--r--techlibs/ice40/abc_lp.box113
-rw-r--r--techlibs/ice40/abc_lp.lut6
-rw-r--r--techlibs/ice40/abc_u.box113
-rw-r--r--techlibs/ice40/abc_u.lut6
-rw-r--r--techlibs/ice40/cells_map.v18
-rw-r--r--techlibs/ice40/cells_sim.v77
-rw-r--r--techlibs/ice40/synth_ice40.cc22
-rw-r--r--techlibs/intel/synth_intel.cc4
-rwxr-xr-xtests/simple_abc9/run-test.sh2
-rw-r--r--tests/various/pmux2shiftx.ys4
31 files changed, 953 insertions, 283 deletions
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index dfe506c66..516e538a5 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -685,7 +685,7 @@ struct AigerBackend : public Backend {
log("invariant constraints.\n");
log("\n");
log(" -ascii\n");
- log(" write ASCII version of AGIER format\n");
+ log(" write ASCII version of AIGER format\n");
log("\n");
log(" -zinit\n");
log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 66ab3878e..d6438a297 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -20,6 +20,8 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "kernel/utils.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -46,9 +48,8 @@ struct XAigerWriter
pool<SigBit> input_bits, output_bits;
dict<SigBit, SigBit> not_map, ff_map, alias_map;
dict<SigBit, pair<SigBit, SigBit>> and_map;
- pool<SigBit> initstate_bits;
+ //pool<SigBit> initstate_bits;
vector<std::pair<SigBit,int>> ci_bits, co_bits;
- dict<IdString, unsigned> type_map;
vector<pair<int, int>> aig_gates;
vector<int> aig_latchin, aig_latchinit, aig_outputs;
@@ -58,11 +59,11 @@ struct XAigerWriter
dict<SigBit, int> ordered_outputs;
dict<SigBit, int> ordered_latches;
- dict<SigBit, int> init_inputs;
- int initstate_ff = 0;
-
vector<Cell*> box_list;
+ //dict<SigBit, int> init_inputs;
+ //int initstate_ff = 0;
+
int mkgate(int a0, int a1)
{
aig_m++, aig_a++;
@@ -76,10 +77,10 @@ struct XAigerWriter
{
aig_map[bit] = -1;
- if (initstate_bits.count(bit)) {
- log_assert(initstate_ff > 0);
- aig_map[bit] = initstate_ff;
- } else
+ //if (initstate_bits.count(bit)) {
+ // log_assert(initstate_ff > 0);
+ // aig_map[bit] = initstate_ff;
+ //} else
if (not_map.count(bit)) {
int a = bit2aig(not_map.at(bit)) ^ 1;
aig_map[bit] = a;
@@ -102,7 +103,7 @@ struct XAigerWriter
return aig_map.at(bit);
}
- XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
+ XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module)
{
pool<SigBit> undriven_bits;
pool<SigBit> unused_bits;
@@ -159,19 +160,56 @@ struct XAigerWriter
}
}
- for (auto bit : input_bits) {
- if (!bit.wire->port_output)
- undriven_bits.erase(bit);
- // Erase POs that are also PIs
- output_bits.erase(bit);
- }
+ for (auto bit : input_bits)
+ undriven_bits.erase(bit);
for (auto bit : output_bits)
if (!bit.wire->port_input)
unused_bits.erase(bit);
+ dict<SigBit, pool<IdString>> bit_drivers, bit_users;
+ TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
+ bool abc_box_seen = false;
+
for (auto cell : module->cells())
{
+ RTLIL::Module* inst_module = module->design->module(cell->type);
+ bool known_type = yosys_celltypes.cell_known(cell->type);
+
+ if (!holes_mode) {
+ toposort.node(cell->name);
+ for (const auto &conn : cell->connections())
+ {
+ if (!cell->type.in("$_NOT_", "$_AND_")) {
+ if (known_type) {
+ if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA"))
+ continue;
+ if (cell->type == "$memrd" && conn.first == "\\DATA")
+ continue;
+ }
+
+ if (inst_module) {
+ RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
+ log_assert(inst_module_port);
+
+ if (inst_module_port->attributes.count("\\abc_flop_q"))
+ continue;
+ }
+ }
+
+ if (cell->input(conn.first)) {
+ // Ignore inout for the sake of topographical ordering
+ if (cell->output(conn.first)) continue;
+ for (auto bit : sigmap(conn.second))
+ bit_users[bit].insert(cell->name);
+ }
+
+ if (cell->output(conn.first))
+ for (auto bit : sigmap(conn.second))
+ bit_drivers[bit].insert(cell->name);
+ }
+ }
+
if (cell->type == "$_NOT_")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
@@ -204,57 +242,98 @@ struct XAigerWriter
continue;
}
- if (cell->type == "$initstate")
- {
- SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
- undriven_bits.erase(Y);
- initstate_bits.insert(Y);
- continue;
+ //if (cell->type == "$initstate")
+ //{
+ // SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+ // undriven_bits.erase(Y);
+ // initstate_bits.insert(Y);
+ // continue;
+ //}
+
+ if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
+ abc_box_seen = true;
+ }
+ else {
+ for (const auto &c : cell->connections()) {
+ if (c.second.is_fully_const()) continue;
+ for (auto b : c.second.bits()) {
+ Wire *w = b.wire;
+ if (!w) continue;
+ auto is_input = cell->input(c.first);
+ auto is_output = cell->output(c.first);
+ log_assert(is_input || is_output);
+ if (is_input) {
+ if (!w->port_input) {
+ SigBit I = sigmap(b);
+ if (I != b)
+ alias_map[b] = I;
+ output_bits.insert(b);
+ unused_bits.erase(b);
+ }
+ }
+ if (is_output) {
+ SigBit O = sigmap(b);
+ input_bits.insert(O);
+ undriven_bits.erase(O);
+ }
+ }
+ }
+ }
+
+ //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
+ }
+
+ if (abc_box_seen) {
+ for (auto &it : bit_users)
+ if (bit_drivers.count(it.first))
+ for (auto driver_cell : bit_drivers.at(it.first))
+ for (auto user_cell : it.second)
+ toposort.edge(driver_cell, user_cell);
+
+#ifndef NDEBUG
+ toposort.analyze_loops = true;
+#endif
+ toposort.sort();
+#ifndef NDEBUG
+ for (auto &it : toposort.loops) {
+ log(" loop");
+ for (auto cell : it)
+ log(" %s", log_id(cell));
+ log("\n");
}
+#endif
+ log_assert(!toposort.found_loops);
+
+ for (auto cell_name : toposort.sorted) {
+ RTLIL::Cell *cell = module->cell(cell_name);
+ RTLIL::Module* box_module = module->design->module(cell->type);
+ if (!box_module || !box_module->attributes.count("\\abc_box_id"))
+ continue;
- RTLIL::Module* box_module = module->design->module(cell->type);
- bool abc_box = box_module && box_module->attributes.count("\\abc_box_id");
-
- for (const auto &c : cell->connections()) {
- /*if (c.second.is_fully_const()) continue;*/
- for (auto b : c.second.bits()) {
- auto is_input = cell->input(c.first);
- auto is_output = cell->output(c.first);
- log_assert(is_input || is_output);
- if (is_input) {
- /*if (!w->port_input)*/ {
+ // Box ordering is alphabetical
+ cell->connections_.sort(RTLIL::sort_by_id_str());
+ for (const auto &c : cell->connections()) {
+ for (auto b : c.second.bits()) {
+ auto is_input = cell->input(c.first);
+ auto is_output = cell->output(c.first);
+ log_assert(is_input || is_output);
+ if (is_input) {
SigBit I = sigmap(b);
if (I != b)
alias_map[b] = I;
- /*if (!output_bits.count(b))*/
- if (abc_box)
- co_bits.emplace_back(b, 0);
- else if (b.wire) {
- output_bits.insert(b);
- if (!b.wire->port_input)
- unused_bits.erase(b);
- }
+ co_bits.emplace_back(b, 0);
}
- }
- if (is_output) {
- SigBit O = sigmap(b);
- /*if (!input_bits.count(O))*/
- if (abc_box)
+ if (is_output) {
+ SigBit O = sigmap(b);
ci_bits.emplace_back(O, 0);
- else {
- input_bits.insert(O);
- if (!O.wire->port_output)
- undriven_bits.erase(O);
}
}
}
- if (!type_map.count(cell->type))
- type_map[cell->type] = type_map.size()+1;
- }
- if (abc_box)
box_list.emplace_back(cell);
- //log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
+ }
+
+ // TODO: Free memory from toposort, bit_drivers, bit_users
}
for (auto bit : input_bits) {
@@ -274,27 +353,23 @@ struct XAigerWriter
and_map[new_bit] = and_map.at(bit);
else if (alias_map.count(bit))
alias_map[new_bit] = alias_map.at(bit);
+ else
+ alias_map[new_bit] = bit;
output_bits.insert(new_bit);
}
}
// Do some CI/CO post-processing:
- // Erase all POs and COs that are undriven
- for (auto bit : undriven_bits) {
- //co_bits.erase(bit);
+ // Erase all POs that are undriven
+ for (auto bit : undriven_bits)
output_bits.erase(bit);
- }
- // Erase all CIs that are also COs
- //for (auto bit : co_bits)
- // ci_bits.erase(bit);
// CIs cannot be undriven
for (const auto &c : ci_bits)
undriven_bits.erase(c.first);
-
for (auto bit : unused_bits)
undriven_bits.erase(bit);
- if (!undriven_bits.empty()) {
+ if (!undriven_bits.empty() && !holes_mode) {
undriven_bits.sort();
for (auto bit : undriven_bits) {
log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
@@ -313,30 +388,30 @@ struct XAigerWriter
aig_map[State::S0] = 0;
aig_map[State::S1] = 1;
- for (auto &c : ci_bits) {
+ for (auto bit : input_bits) {
aig_m++, aig_i++;
- c.second = 2*aig_m;
- aig_map[c.first] = c.second;
+ aig_map[bit] = 2*aig_m;
}
- for (auto bit : input_bits) {
+ for (auto &c : ci_bits) {
aig_m++, aig_i++;
- aig_map[bit] = 2*aig_m;
+ c.second = 2*aig_m;
+ aig_map[c.first] = c.second;
}
if (imode && input_bits.empty()) {
aig_m++, aig_i++;
}
- if (zinit_mode)
- {
- for (auto it : ff_map) {
- if (init_map.count(it.first))
- continue;
- aig_m++, aig_i++;
- init_inputs[it.first] = 2*aig_m;
- }
- }
+ //if (zinit_mode)
+ //{
+ // for (auto it : ff_map) {
+ // if (init_map.count(it.first))
+ // continue;
+ // aig_m++, aig_i++;
+ // init_inputs[it.first] = 2*aig_m;
+ // }
+ //}
for (auto it : ff_map) {
aig_m++, aig_l++;
@@ -348,29 +423,29 @@ struct XAigerWriter
aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0);
}
- if (!initstate_bits.empty() || !init_inputs.empty()) {
- aig_m++, aig_l++;
- initstate_ff = 2*aig_m+1;
- aig_latchinit.push_back(0);
- }
-
- if (zinit_mode)
- {
- for (auto it : ff_map)
- {
- int l = ordered_latches[it.first];
-
- if (aig_latchinit.at(l) == 1)
- aig_map[it.first] ^= 1;
-
- if (aig_latchinit.at(l) == 2)
- {
- int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
- int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
- aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
- }
- }
- }
+ //if (!initstate_bits.empty() || !init_inputs.empty()) {
+ // aig_m++, aig_l++;
+ // initstate_ff = 2*aig_m+1;
+ // aig_latchinit.push_back(0);
+ //}
+
+ //if (zinit_mode)
+ //{
+ // for (auto it : ff_map)
+ // {
+ // int l = ordered_latches[it.first];
+
+ // if (aig_latchinit.at(l) == 1)
+ // aig_map[it.first] ^= 1;
+
+ // if (aig_latchinit.at(l) == 2)
+ // {
+ // int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
+ // int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
+ // aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
+ // }
+ // }
+ //}
for (auto it : ff_map) {
int a = bit2aig(it.second);
@@ -381,8 +456,8 @@ struct XAigerWriter
aig_latchin.push_back(a);
}
- if (!initstate_bits.empty() || !init_inputs.empty())
- aig_latchin.push_back(1);
+ //if (!initstate_bits.empty() || !init_inputs.empty())
+ // aig_latchin.push_back(1);
for (auto &c : co_bits) {
RTLIL::SigBit bit = c.first;
@@ -517,14 +592,14 @@ struct XAigerWriter
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
}
- if (init_inputs.count(sig[i])) {
- int a = init_inputs.at(sig[i]);
- log_assert((a & 1) == 0);
- if (GetSize(wire) != 1)
- symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
- else
- symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
- }
+ //if (init_inputs.count(sig[i])) {
+ // int a = init_inputs.at(sig[i]);
+ // log_assert((a & 1) == 0);
+ // if (GetSize(wire) != 1)
+ // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
+ // else
+ // symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
+ //}
if (ordered_latches.count(sig[i])) {
int l = ordered_latches.at(sig[i]);
@@ -584,17 +659,17 @@ struct XAigerWriter
if (holes_module && !holes_module->cell(stringf("\\u%d", box_id)))
holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type);
RTLIL::Wire *holes_wire;
- int num_inputs = 0;
+ // NB: cell->connections_ already sorted from before
for (const auto &c : cell->connections()) {
+ log_assert(c.second.size() == 1);
if (cell->input(c.first)) {
box_inputs += c.second.size();
if (holes_cell) {
- holes_wire = holes_module->wire(stringf("\\i%d", num_inputs));
+ holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
if (!holes_wire) {
- holes_wire = holes_module->addWire(stringf("\\i%d", num_inputs));
+ holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
holes_wire->port_input = true;
}
- ++num_inputs;
holes_cell->setPort(c.first, holes_wire);
}
}
@@ -631,12 +706,12 @@ struct XAigerWriter
RTLIL::Selection& sel = holes_module->design->selection_stack.back();
sel.select(holes_module);
- Pass::call(holes_module->design, "flatten; aigmap");
+ Pass::call(holes_module->design, "flatten -wb; aigmap; clean -purge");
holes_module->design->selection_stack.pop_back();
std::stringstream a_buffer;
- XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/);
+ XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */);
writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/);
f << "a";
@@ -686,12 +761,12 @@ struct XAigerWriter
continue;
}
- if (init_inputs.count(sig[i])) {
- int a = init_inputs.at(sig[i]);
- log_assert((a & 1) == 0);
- init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
- continue;
- }
+ //if (init_inputs.count(sig[i])) {
+ // int a = init_inputs.at(sig[i]);
+ // log_assert((a & 1) == 0);
+ // init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
+ // continue;
+ //}
if (ordered_latches.count(sig[i])) {
int l = ordered_latches.at(sig[i]);
@@ -716,7 +791,7 @@ struct XAigerWriter
RTLIL::SigBit b = c.first;
RTLIL::Wire *wire = b.wire;
int i = b.offset;
- int a = c.second;
+ int a = bit2aig(b);
log_assert((a & 1) == 0);
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
}
@@ -769,7 +844,7 @@ struct XAigerBackend : public Backend {
log("all unsupported cells will be converted into psuedo-inputs and pseudo-outputs.\n");
log("\n");
log(" -ascii\n");
- log(" write ASCII version of AGIER format\n");
+ log(" write ASCII version of AIGER format\n");
log("\n");
log(" -zinit\n");
log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
diff --git a/backends/json/json.cc b/backends/json/json.cc
index f5c687981..b4f82a3fe 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -130,72 +130,75 @@ struct JsonWriter
f << stringf(" }");
first = false;
}
- f << stringf("\n },\n");
+ f << stringf("\n }");
- f << stringf(" \"cells\": {");
- first = true;
- for (auto c : module->cells()) {
- if (use_selection && !module->selected(c))
- continue;
- f << stringf("%s\n", first ? "" : ",");
- f << stringf(" %s: {\n", get_name(c->name).c_str());
- f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
- f << stringf(" \"type\": %s,\n", get_name(c->type).c_str());
- if (aig_mode) {
- Aig aig(c);
- if (!aig.name.empty()) {
- f << stringf(" \"model\": \"%s\",\n", aig.name.c_str());
- aig_models.insert(aig);
+ if (!module->get_blackbox_attribute()) {
+ f << stringf(",\n \"cells\": {");
+ first = true;
+ for (auto c : module->cells()) {
+ if (use_selection && !module->selected(c))
+ continue;
+ f << stringf("%s\n", first ? "" : ",");
+ f << stringf(" %s: {\n", get_name(c->name).c_str());
+ f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
+ f << stringf(" \"type\": %s,\n", get_name(c->type).c_str());
+ if (aig_mode) {
+ Aig aig(c);
+ if (!aig.name.empty()) {
+ f << stringf(" \"model\": \"%s\",\n", aig.name.c_str());
+ aig_models.insert(aig);
+ }
}
- }
- f << stringf(" \"parameters\": {");
- write_parameters(c->parameters);
- f << stringf("\n },\n");
- f << stringf(" \"attributes\": {");
- write_parameters(c->attributes);
- f << stringf("\n },\n");
- if (c->known()) {
- f << stringf(" \"port_directions\": {");
+ f << stringf(" \"parameters\": {");
+ write_parameters(c->parameters);
+ f << stringf("\n },\n");
+ f << stringf(" \"attributes\": {");
+ write_parameters(c->attributes);
+ f << stringf("\n },\n");
+ if (c->known()) {
+ f << stringf(" \"port_directions\": {");
+ bool first2 = true;
+ for (auto &conn : c->connections()) {
+ string direction = "output";
+ if (c->input(conn.first))
+ direction = c->output(conn.first) ? "inout" : "input";
+ f << stringf("%s\n", first2 ? "" : ",");
+ f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
+ first2 = false;
+ }
+ f << stringf("\n },\n");
+ }
+ f << stringf(" \"connections\": {");
bool first2 = true;
for (auto &conn : c->connections()) {
- string direction = "output";
- if (c->input(conn.first))
- direction = c->output(conn.first) ? "inout" : "input";
f << stringf("%s\n", first2 ? "" : ",");
- f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
+ f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
first2 = false;
}
- f << stringf("\n },\n");
+ f << stringf("\n }\n");
+ f << stringf(" }");
+ first = false;
}
- f << stringf(" \"connections\": {");
- bool first2 = true;
- for (auto &conn : c->connections()) {
- f << stringf("%s\n", first2 ? "" : ",");
- f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
- first2 = false;
- }
- f << stringf("\n }\n");
- f << stringf(" }");
- first = false;
- }
- f << stringf("\n },\n");
+ f << stringf("\n },\n");
- f << stringf(" \"netnames\": {");
- first = true;
- for (auto w : module->wires()) {
- if (use_selection && !module->selected(w))
- continue;
- f << stringf("%s\n", first ? "" : ",");
- f << stringf(" %s: {\n", get_name(w->name).c_str());
- f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
- f << stringf(" \"bits\": %s,\n", get_bits(w).c_str());
- f << stringf(" \"attributes\": {");
- write_parameters(w->attributes);
- f << stringf("\n }\n");
- f << stringf(" }");
- first = false;
+ f << stringf(" \"netnames\": {");
+ first = true;
+ for (auto w : module->wires()) {
+ if (use_selection && !module->selected(w))
+ continue;
+ f << stringf("%s\n", first ? "" : ",");
+ f << stringf(" %s: {\n", get_name(w->name).c_str());
+ f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
+ f << stringf(" \"bits\": %s,\n", get_bits(w).c_str());
+ f << stringf(" \"attributes\": {");
+ write_parameters(w->attributes);
+ f << stringf("\n }\n");
+ f << stringf(" }");
+ first = false;
+ }
+ f << stringf("\n }");
}
- f << stringf("\n }\n");
+ f << stringf("\n");
f << stringf(" }");
}
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 855409d0b..9967482d6 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -187,6 +187,10 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
{
if (width < 0)
width = data.bits.size() - offset;
+ if (width == 0) {
+ f << "\"\"";
+ return;
+ }
if (nostr)
goto dump_hex;
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
@@ -340,6 +344,10 @@ void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decima
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
{
+ if (GetSize(sig) == 0) {
+ f << "\"\"";
+ return;
+ }
if (sig.is_chunk()) {
dump_sigchunk(f, sig.as_chunk());
} else {
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index f2d21f1db..3fa6f5c2d 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -35,9 +35,6 @@
YOSYS_NAMESPACE_BEGIN
-//#define log_debug log
-#define log_debug(...) ;
-
AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports)
: design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports)
{
@@ -368,6 +365,13 @@ void AigerReader::parse_xaiger()
f >> s;
log_debug("n: '%s'\n", s.c_str());
}
+ else if (c == 'a' || c == 'i' || c == 'o' || c == 'h') {
+ uint32_t dataSize = parse_xaiger_literal(f);
+ f.ignore(dataSize);
+ }
+ else {
+ break;
+ }
}
else if (c == 'i' || c == 'l' || c == 'o') {
f.ignore(1);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 76da5a97c..3e453bd7f 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1085,7 +1085,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// eval 1st expression
AstNode *varbuf = init_ast->children[1]->clone();
- while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
+ {
+ int expr_width_hint = -1;
+ bool expr_sign_hint = true;
+ varbuf->detectSignWidth(expr_width_hint, expr_sign_hint);
+ while (varbuf->simplify(true, false, false, stage, 32, true, false)) { }
+ }
if (varbuf->type != AST_CONSTANT)
log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n");
@@ -1107,7 +1112,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
// eval 2nd expression
AstNode *buf = while_ast->clone();
- while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
+ {
+ int expr_width_hint = -1;
+ bool expr_sign_hint = true;
+ buf->detectSignWidth(expr_width_hint, expr_sign_hint);
+ while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { }
+ }
if (buf->type != AST_CONSTANT)
log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n");
@@ -1148,7 +1158,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// eval 3rd expression
buf = next_ast->children[1]->clone();
- while (buf->simplify(true, false, false, stage, 32, true, false)) { }
+ {
+ int expr_width_hint = -1;
+ bool expr_sign_hint = true;
+ buf->detectSignWidth(expr_width_hint, expr_sign_hint);
+ while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { }
+ }
if (buf->type != AST_CONSTANT)
log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n");
diff --git a/kernel/driver.cc b/kernel/driver.cc
index c539ba569..1bc7a5935 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -295,6 +295,9 @@ int main(int argc, char **argv)
printf(" -E <depsfile>\n");
printf(" write a Makefile dependencies file with in- and output file names\n");
printf("\n");
+ printf(" -g\n");
+ printf(" globally enable debug log messages\n");
+ printf("\n");
printf(" -V\n");
printf(" print version information and exit\n");
printf("\n");
@@ -315,7 +318,7 @@ int main(int argc, char **argv)
}
int opt;
- while ((opt = getopt(argc, argv, "MXAQTVSm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1)
+ while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:")) != -1)
{
switch (opt)
{
@@ -340,6 +343,9 @@ int main(int argc, char **argv)
case 'S':
passes_commands.push_back("synth");
break;
+ case 'g':
+ log_force_debug++;
+ break;
case 'm':
plugin_filenames.push_back(optarg);
break;
diff --git a/kernel/log.cc b/kernel/log.cc
index 400a549dd..9a9104e26 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -56,6 +56,10 @@ int log_verbose_level;
string log_last_error;
void (*log_error_atexit)() = NULL;
+int log_make_debug = 0;
+int log_force_debug = 0;
+int log_debug_suppressed = 0;
+
vector<int> header_count;
pool<RTLIL::IdString> log_id_cache;
vector<shared_str> string_buf;
@@ -92,6 +96,9 @@ void logv(const char *format, va_list ap)
format++;
}
+ if (log_make_debug && !ys_debug(1))
+ return;
+
std::string str = vstringf(format, ap);
if (str.empty())
diff --git a/kernel/log.h b/kernel/log.h
index 759939025..e6afae716 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -64,6 +64,10 @@ extern int log_verbose_level;
extern string log_last_error;
extern void (*log_error_atexit)();
+extern int log_make_debug;
+extern int log_force_debug;
+extern int log_debug_suppressed;
+
void logv(const char *format, va_list ap);
void logv_header(RTLIL::Design *design, const char *format, va_list ap);
void logv_warning(const char *format, va_list ap);
@@ -82,6 +86,45 @@ YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf,
void log_file_error(const string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4), noreturn);
YS_NORETURN void log_cmd_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);
+#ifndef NDEBUG
+static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_debug_suppressed += n; return false; }
+# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0)
+#else
+static inline bool ys_debug(int n = 0) { return false; }
+# define log_debug(_fmt, ...) do { } while (0)
+#endif
+
+static inline void log_suppressed() {
+ if (log_debug_suppressed && !log_make_debug) {
+ log("<suppressed ~%d debug messages>\n", log_debug_suppressed);
+ log_debug_suppressed = 0;
+ }
+}
+
+struct LogMakeDebugHdl {
+ bool status = false;
+ LogMakeDebugHdl(bool start_on = false) {
+ if (start_on)
+ on();
+ }
+ ~LogMakeDebugHdl() {
+ off();
+ }
+ void on() {
+ if (status) return;
+ status=true;
+ log_make_debug++;
+ }
+ void off_silent() {
+ if (!status) return;
+ status=false;
+ log_make_debug--;
+ }
+ void off() {
+ off_silent();
+ }
+};
+
void log_spacer();
void log_push();
void log_pop();
diff --git a/kernel/register.cc b/kernel/register.cc
index 64956401f..71eb6b187 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -87,6 +87,7 @@ Pass::pre_post_exec_state_t Pass::pre_execute()
void Pass::post_execute(Pass::pre_post_exec_state_t state)
{
IdString::checkpoint();
+ log_suppressed();
int64_t time_ns = PerformanceTimer::query() - state.begin_ns;
runtime_ns += time_ns;
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index f5305cde9..cf3e46ace 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -94,4 +94,38 @@ struct TracePass : public Pass {
}
} TracePass;
+struct DebugPass : public Pass {
+ DebugPass() : Pass("debug", "run command with debug log messages enabled") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" debug cmd\n");
+ log("\n");
+ 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
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // .. parse options ..
+ break;
+ }
+
+ log_force_debug++;
+
+ try {
+ std::vector<std::string> new_args(args.begin() + argidx, args.end());
+ Pass::call(design, new_args);
+ } catch (...) {
+ log_force_debug--;
+ throw;
+ }
+
+ log_force_debug--;
+ }
+} DebugPass;
+
PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index c3b13acaf..c38e9df5e 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -137,7 +137,7 @@ void rmunused_module_cells(Module *module, bool verbose)
for (auto cell : unused) {
if (verbose)
- log(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
+ log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
module->design->scratchpad_set_bool("opt.did_something", true);
module->remove(cell);
count_rm_cells++;
@@ -326,7 +326,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
for (auto wire : maybe_del_wires)
if (!used_signals.check_any(RTLIL::SigSpec(wire))) {
if (check_public_name(wire->name) && verbose) {
- log(" removing unused non-port wire %s.\n", wire->name.c_str());
+ log_debug(" removing unused non-port wire %s.\n", wire->name.c_str());
}
del_wires.insert(wire);
del_wires_count++;
@@ -336,7 +336,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
count_rm_wires += del_wires.size();
if (verbose && del_wires_count > 0)
- log(" removed %d unused temporary wires.\n", del_wires_count);
+ log_debug(" removed %d unused temporary wires.\n", del_wires_count);
}
bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
@@ -399,7 +399,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose)
}
if (verbose)
- log(" removing redundant init attribute on %s.\n", log_id(wire));
+ log_debug(" removing redundant init attribute on %s.\n", log_id(wire));
wire->attributes.erase("\\init");
did_something = true;
@@ -426,7 +426,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
}
for (auto cell : delcells) {
if (verbose)
- log(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
+ log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(),
log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A")));
module->remove(cell);
}
@@ -551,6 +551,7 @@ struct CleanPass : public Pass {
rmunused_module(module, purge_mode, false, false);
}
+ log_suppressed();
if (count_rm_cells > 0 || count_rm_wires > 0)
log("Removed %d unused cells and %d unused wires.\n", count_rm_cells, count_rm_wires);
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index a05db2a4f..af6d352af 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -67,7 +67,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module)
if (sig.size() == 0)
continue;
- log("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
+ log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c));
module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width)));
did_something = true;
}
@@ -78,7 +78,7 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell,
RTLIL::SigSpec Y = cell->getPort(out_port);
out_val.extend_u0(Y.size(), false);
- log("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
+ log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n",
cell->type.c_str(), cell->name.c_str(), info.c_str(),
module->name.c_str(), log_signal(Y), log_signal(out_val));
// log_cell(cell);
@@ -134,7 +134,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
if (GetSize(grouped_bits[i]) == GetSize(bits_y))
return false;
- log("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
+ log_debug("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n",
log_id(cell->type), log_id(cell), log_id(module));
for (int i = 0; i < GRP_N; i++)
@@ -156,7 +156,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
}
if (cell->type.in("$and", "$or") && i == GRP_CONST_A) {
- log(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
+ log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a));
module->connect(new_y, new_b);
module->connect(new_conn);
continue;
@@ -180,10 +180,10 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ
module->connect(new_conn);
- log(" New cell `%s': A=%s", log_id(c), log_signal(new_a));
+ log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a));
if (b_name == "\\B")
- log(", B=%s", log_signal(new_b));
- log("\n");
+ log_debug(", B=%s", log_signal(new_b));
+ log_debug("\n");
}
cover_list("opt.opt_expr.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str());
@@ -197,7 +197,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap
{
SigSpec sig = assign_map(cell->getPort(port));
if (invert_map.count(sig)) {
- log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
+ log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module),
log_signal(sig), log_signal(invert_map.at(sig)));
cell->setPort(port, (invert_map.at(sig)));
@@ -226,7 +226,7 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin
if (cell->type.in(type1, type2)) {
SigSpec sig = assign_map(cell->getPort(port));
if (invert_map.count(sig)) {
- log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
+ log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n",
log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module),
log_signal(sig), log_signal(invert_map.at(sig)));
cell->setPort(port, (invert_map.at(sig)));
@@ -455,9 +455,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
{
if (cell->type == "$reduce_xnor") {
cover("opt.opt_expr.reduce_xnor_not");
- log("Replacing %s cell `%s' in module `%s' with $not cell.\n",
+ log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n",
log_id(cell->type), log_id(cell->name), log_id(module));
cell->type = "$not";
+ did_something = true;
} else {
cover("opt.opt_expr.unary_buffer");
replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort("\\A"));
@@ -488,7 +489,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (GetSize(new_sig_a) < GetSize(sig_a)) {
cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str());
- log("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
+ log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a));
cell->setPort("\\A", new_sig_a);
cell->parameters.at("\\A_WIDTH") = GetSize(new_sig_a);
@@ -511,7 +512,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (GetSize(new_sig_b) < GetSize(sig_b)) {
cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str());
- log("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
+ log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b));
cell->setPort("\\B", new_sig_b);
cell->parameters.at("\\B_WIDTH") = GetSize(new_sig_b);
@@ -537,7 +538,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
cover("opt.opt_expr.fine.$reduce_and");
- log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
+ log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
cell->setPort("\\A", sig_a = new_a);
cell->parameters.at("\\A_WIDTH") = 1;
@@ -563,7 +564,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) {
cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str());
- log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
+ log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a));
cell->setPort("\\A", sig_a = new_a);
cell->parameters.at("\\A_WIDTH") = 1;
@@ -589,7 +590,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) {
cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str());
- log("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
+ log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b));
cell->setPort("\\B", sig_b = new_b);
cell->parameters.at("\\B_WIDTH") = 1;
@@ -640,7 +641,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if ((cell->type == "$_MUX_" || cell->type == "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) {
cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str());
- log("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
+ log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module));
RTLIL::SigSpec tmp = cell->getPort("\\A");
cell->setPort("\\A", cell->getPort("\\B"));
cell->setPort("\\B", tmp);
@@ -750,7 +751,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
ACTION_DO("\\Y", cell->getPort("\\A"));
if (input == State::S0 && !a.is_fully_undef()) {
cover("opt.opt_expr.action_" S__LINE__);
- log("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
+ log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str());
cell->setPort("\\A", SigSpec(State::Sx, GetSize(a)));
did_something = true;
@@ -822,7 +823,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
ACTION_DO("\\Y", cell->getPort("\\A"));
} else {
cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str());
- log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
+ log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->type = "$not";
cell->parameters.erase("\\B_WIDTH");
cell->parameters.erase("\\B_SIGNED");
@@ -837,7 +838,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
(assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero()))
{
cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str());
- log("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
+ log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell),
log_id(module), "$eq" ? "$logic_not" : "$reduce_bool");
cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool";
if (assign_map(cell->getPort("\\A")).is_fully_zero()) {
@@ -876,7 +877,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str());
- log("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
+ log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n",
log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y));
module->connect(cell->getPort("\\Y"), sig_y);
@@ -939,7 +940,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (identity_wrt_b)
cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str());
- log("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
+ log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n",
cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B');
if (!identity_wrt_a) {
@@ -969,7 +970,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") &&
cell->getPort("\\A") == RTLIL::SigSpec(1, 1) && cell->getPort("\\B") == RTLIL::SigSpec(0, 1)) {
cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str());
- log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
+ log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", cell->getPort("\\S"));
cell->unsetPort("\\B");
cell->unsetPort("\\S");
@@ -988,7 +989,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) {
cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str());
- log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
+ log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", cell->getPort("\\S"));
cell->unsetPort("\\S");
if (cell->type == "$mux") {
@@ -1008,7 +1009,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) {
cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str());
- log("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
+ log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\B", cell->getPort("\\S"));
cell->unsetPort("\\S");
if (cell->type == "$mux") {
@@ -1061,7 +1062,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
if (cell->getPort("\\S").size() != new_s.size()) {
cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str());
- log("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
+ log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n",
GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", new_a);
cell->setPort("\\B", new_b);
@@ -1179,7 +1180,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
{
cover("opt.opt_expr.mul_shift.zero");
- log("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
+ log_debug("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n",
cell->name.c_str(), module->name.c_str());
module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size())));
@@ -1197,7 +1198,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
else
cover("opt.opt_expr.mul_shift.unswapped");
- log("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
+ log_debug("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
a_val, cell->name.c_str(), module->name.c_str(), i);
if (!swapped_ab) {
@@ -1237,7 +1238,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
{
cover("opt.opt_expr.divmod_zero");
- log("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
+ log_debug("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n",
cell->name.c_str(), module->name.c_str());
module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size())));
@@ -1254,7 +1255,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
{
cover("opt.opt_expr.div_shift");
- log("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
+ log_debug("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
b_val, cell->name.c_str(), module->name.c_str(), i);
std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
@@ -1272,7 +1273,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
{
cover("opt.opt_expr.mod_mask");
- log("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
+ log_debug("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
b_val, cell->name.c_str(), module->name.c_str());
std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
@@ -1342,7 +1343,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
SigSpec y_sig = cell->getPort("\\Y");
Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig));
- log("Replacing cell `%s' in module `%s' with constant driver %s.\n",
+ log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n",
log_id(cell), log_id(module), log_signal(y_value));
module->connect(y_sig, y_value);
@@ -1354,7 +1355,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (redundant_bits)
{
- log("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
+ log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n",
redundant_bits, log_id(cell->type), log_id(cell), log_id(module));
cell->setPort("\\A", sig_a);
@@ -1493,7 +1494,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (replace || remove)
{
- log("Replacing %s cell `%s' (implementing %s) with %s.\n",
+ log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n",
log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str());
if (replace)
module->connect(cell->getPort("\\Y"), replace_sig);
@@ -1599,8 +1600,14 @@ struct OptExprPass : public Pass {
for (auto module : design->selected_modules())
{
- if (undriven)
+ log("Optimizing module %s.\n", log_id(module));
+
+ if (undriven) {
+ did_something = false;
replace_undriven(design, module);
+ if (did_something)
+ design->scratchpad_set_bool("opt.did_something", true);
+ }
do {
do {
@@ -1610,7 +1617,11 @@ struct OptExprPass : public Pass {
design->scratchpad_set_bool("opt.did_something", true);
} while (did_something);
replace_const_cells(design, module, true, mux_undef, mux_bool, do_fine, keepdc, clkinv);
+ if (did_something)
+ design->scratchpad_set_bool("opt.did_something", true);
} while (did_something);
+
+ log_suppressed();
}
log_pop();
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index eedf88904..7567d4657 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -315,17 +315,17 @@ struct OptMergeWorker
{
if (sharemap.count(cell) > 0) {
did_something = true;
- log(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
+ log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str());
for (auto &it : cell->connections()) {
if (cell->output(it.first)) {
RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first);
- log(" Redirecting output %s: %s = %s\n", it.first.c_str(),
+ log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
log_signal(it.second), log_signal(other_sig));
module->connect(RTLIL::SigSig(it.second, other_sig));
assign_map.add(it.second, other_sig);
}
}
- log(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
+ log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
#ifdef USE_CELL_HASH_CACHE
cell_hash_cache.erase(cell);
#endif
@@ -336,6 +336,8 @@ struct OptMergeWorker
}
}
}
+
+ log_suppressed();
}
};
diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc
index 375697dc8..dbebf21e0 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -181,14 +181,14 @@ struct OptMuxtreeWorker
for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++)
if (root_muxes.at(mux_idx)) {
- log(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : "");
+ log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : "");
root_mux_rerun.erase(mux_idx);
eval_root_mux(mux_idx);
}
while (!root_mux_rerun.empty()) {
int mux_idx = *root_mux_rerun.begin();
- log(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell));
+ log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell));
log_assert(root_enable_muxes.at(mux_idx));
root_mux_rerun.erase(mux_idx);
eval_root_mux(mux_idx);
@@ -326,7 +326,7 @@ struct OptMuxtreeWorker
if (abort_count == 0) {
root_mux_rerun.insert(m);
root_enable_muxes.at(m) = true;
- log(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell));
+ log_debug(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell));
} else
eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1);
} else
diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc
index 5f897b131..29870f510 100644
--- a/passes/opt/pmux2shiftx.cc
+++ b/passes/opt/pmux2shiftx.cc
@@ -369,6 +369,7 @@ struct Pmux2ShiftxPass : public Pass {
dict<SigSpec, pool<int>> seldb;
+ SigSpec A = cell->getPort("\\A");
SigSpec B = cell->getPort("\\B");
SigSpec S = sigmap(cell->getPort("\\S"));
for (int i = 0; i < GetSize(S); i++)
@@ -419,6 +420,8 @@ struct Pmux2ShiftxPass : public Pass {
choices[val] = i;
}
+ bool full_pmux = GetSize(choices) == GetSize(S);
+
// TBD: also find choices that are using signals that are subsets of the bits in "sig"
if (!verbose)
@@ -634,7 +637,21 @@ struct Pmux2ShiftxPass : public Pass {
log(" range density: %d%%\n", range_density);
log(" absolute density: %d%%\n", absolute_density);
- bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (max_choice+1 == GetSize(choices));
+ if (full_pmux) {
+ int full_density = 100*GetSize(choices) / (1 << GetSize(sig));
+ log(" full density: %d%%\n", full_density);
+ if (full_density < min_density) {
+ full_pmux = false;
+ } else {
+ min_choice = 0;
+ max_choice = (1 << GetSize(sig))-1;
+ log(" update to full case.\n");
+ log(" new min choice: %d\n", min_choice);
+ log(" new max choice: %d\n", max_choice);
+ }
+ }
+
+ bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (full_pmux || max_choice+1 == GetSize(choices));
log(" full case: %s\n", full_case ? "true" : "false");
// check density percentages
@@ -677,6 +694,10 @@ struct Pmux2ShiftxPass : public Pass {
// create data signal
SigSpec data(State::Sx, (max_choice+1)*extwidth);
+ if (full_pmux) {
+ for (int i = 0; i <= max_choice; i++)
+ data.replace(i*extwidth, A);
+ }
for (auto &it : perm_choices) {
int position = it.first.as_int()*extwidth;
int data_index = it.second;
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index b14eef485..3cee5a586 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -25,7 +25,8 @@
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
//#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
-#define ABC_COMMAND_LUT "&st; &fraig; &scorr; &dc2; &retime; &dch -f; &if; &mfs"
+//#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps"
+#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m"
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
@@ -343,7 +344,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
else
abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
- abc_script += stringf("&read %s/input.xaig; &ps ", tempdir_name.c_str());
+ abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
if (!script_file.empty()) {
if (script_file[0] == '+') {
@@ -1401,6 +1402,9 @@ struct Abc9Pass : public Pass {
for (auto mod : design->selected_modules())
{
+ if (mod->attributes.count("\\abc_box_id"))
+ continue;
+
if (mod->processes.size() > 0) {
log("Skipping module %s as it contains processes.\n", log_id(mod));
continue;
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 1a4318460..ab0bd3b54 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -72,6 +72,8 @@ struct TechmapWorker
pool<IdString> flatten_done_list;
pool<Cell*> flatten_keep_list;
+ pool<string> log_msg_cache;
+
struct TechmapWireData {
RTLIL::Wire *wire;
RTLIL::SigSpec value;
@@ -390,6 +392,7 @@ struct TechmapWorker
bool log_continue = false;
bool did_something = false;
+ LogMakeDebugHdl mkdebug;
SigMap sigmap(module);
@@ -547,6 +550,7 @@ struct TechmapWorker
if (extmapper_name == "wrap") {
std::string cmd_string = tpl->attributes.at("\\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;
}
@@ -560,11 +564,21 @@ struct TechmapWorker
goto use_wrapper_tpl;
}
- log("%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));
+ 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
{
- log("%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());
+ 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)
@@ -662,6 +676,7 @@ struct TechmapWorker
tpl = techmap_cache[key];
} else {
if (parameters.size() != 0) {
+ mkdebug.on();
derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end()));
tpl = map->module(derived_name);
log_continue = true;
@@ -831,6 +846,7 @@ struct TechmapWorker
if (log_continue) {
log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
+ mkdebug.off();
}
while (techmap_module(map, tpl, map, handled_cells, celltypeMap, true)) { }
}
@@ -842,6 +858,7 @@ struct TechmapWorker
if (log_continue) {
log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
+ mkdebug.off();
}
if (extern_mode && !in_recursion)
@@ -861,13 +878,18 @@ struct TechmapWorker
module_queue.insert(m);
}
- log("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
+ log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name));
cell->type = m_name;
cell->parameters.clear();
}
else
{
- log("%s %s.%s using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(tpl));
+ auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), 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) 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;
}
@@ -885,6 +907,7 @@ struct TechmapWorker
if (log_continue) {
log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
+ mkdebug.off();
}
return did_something;
@@ -1085,7 +1108,7 @@ struct TechmapPass : public Pass {
if (map_files.empty()) {
std::istringstream f(stdcells_code);
Frontend::frontend_call(map, &f, "<techmap.v>", verilog_frontend);
- } else
+ } else {
for (auto &fn : map_files)
if (fn.substr(0, 1) == "%") {
if (!saved_designs.count(fn.substr(1))) {
@@ -1104,6 +1127,9 @@ struct TechmapPass : public Pass {
log_cmd_error("Can't open map file `%s'\n", fn.c_str());
Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "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_) {
@@ -1211,6 +1237,7 @@ struct FlattenPass : public Pass {
}
}
+ log_suppressed();
log("No more expansions possible.\n");
if (top_mod != NULL)
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index 723b59d6f..d258d5a5d 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -28,6 +28,12 @@ $(eval $(call add_share_file,share/ice40,techlibs/ice40/cells_sim.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/latches_map.v))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams.txt))
$(eval $(call add_share_file,share/ice40,techlibs/ice40/brams_map.v))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_hx.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_lp.lut))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.box))
+$(eval $(call add_share_file,share/ice40,techlibs/ice40/abc_u.lut))
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init1.vh))
$(eval $(call add_gen_share_file,share/ice40,techlibs/ice40/brams_init2.vh))
diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box
new file mode 100644
index 000000000..994f3091d
--- /dev/null
+++ b/techlibs/ice40/abc_hx.box
@@ -0,0 +1,113 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
+
+# NB: Inputs/Outputs must be ordered alphabetically
+
+# Inputs: C D
+# Outputs: Q
+SB_DFF 1 1 2 1
+- -
+
+# Inputs: C D E
+# Outputs: Q
+SB_DFFE 2 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFSR 3 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFR 4 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFSS 5 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFS 6 0 3 1
+- - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFESR 7 0 4 1
+- - - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFER 8 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFESS 9 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFES 10 0 4 1
+- - - -
+
+# Inputs: C D
+# Outputs: Q
+SB_DFFN 11 0 2 1
+- -
+
+# Inputs: C D E
+# Outputs: Q
+SB_DFFNE 12 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFNSR 13 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFNR 14 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFNSS 15 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFNS 16 0 3 1
+- - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFNESR 17 0 4 1
+- - - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFNER 18 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFNESS 19 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFNES 20 0 4 1
+- - - -
+
+# Inputs: CI I0 I1
+# Outputs: CO
+SB_CARRY 21 1 3 1
+126 259 231
+
+# Inputs: I0 I1 I2 I3
+# Outputs: O
+SB_LUT4 22 0 4 1
+449 400 379 316
diff --git a/techlibs/ice40/abc_hx.lut b/techlibs/ice40/abc_hx.lut
new file mode 100644
index 000000000..3b3bb11e2
--- /dev/null
+++ b/techlibs/ice40/abc_hx.lut
@@ -0,0 +1,6 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_hx8k.txt
+# I3 I2 I1 I0
+1 1 316
+2 1 316 379
+3 1 316 379 400
+4 1 316 379 400 449
diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box
new file mode 100644
index 000000000..002b7bba4
--- /dev/null
+++ b/techlibs/ice40/abc_lp.box
@@ -0,0 +1,113 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
+
+# NB: Inputs/Outputs must be ordered alphabetically
+
+# Inputs: C D
+# Outputs: Q
+SB_DFF 1 1 2 1
+- -
+
+# Inputs: C D E
+# Outputs: Q
+SB_DFFE 2 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFSR 3 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFR 4 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFSS 5 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFS 6 0 3 1
+- - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFESR 7 0 4 1
+- - - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFER 8 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFESS 9 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFES 10 0 4 1
+- - - -
+
+# Inputs: C D
+# Outputs: Q
+SB_DFFN 11 0 2 1
+- -
+
+# Inputs: C D E
+# Outputs: Q
+SB_DFFNE 12 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFNSR 13 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFNR 14 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFNSS 15 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFNS 16 0 3 1
+- - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFNESR 17 0 4 1
+- - - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFNER 18 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFNESS 19 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFNES 20 0 4 1
+- - - -
+
+# Inputs: CI I0 I1
+# Outputs: CO
+SB_CARRY 21 1 3 1
+186 675 609
+
+# Inputs: I0 I1 I2 I3
+# Outputs: O
+SB_LUT4 22 0 4 1
+465 558 589 661
diff --git a/techlibs/ice40/abc_lp.lut b/techlibs/ice40/abc_lp.lut
new file mode 100644
index 000000000..e72f760a2
--- /dev/null
+++ b/techlibs/ice40/abc_lp.lut
@@ -0,0 +1,6 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_lp8k.txt
+# I3 I2 I1 I0
+1 1 465
+2 1 465 558
+3 1 465 558 589
+4 1 465 558 589 661
diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box
new file mode 100644
index 000000000..cb336181c
--- /dev/null
+++ b/techlibs/ice40/abc_u.box
@@ -0,0 +1,113 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
+
+# NB: Inputs/Outputs must be ordered alphabetically
+
+# Inputs: C D
+# Outputs: Q
+SB_DFF 1 1 2 1
+- -
+
+# Inputs: C D E
+# Outputs: Q
+SB_DFFE 2 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFSR 3 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFR 4 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFSS 5 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFS 6 0 3 1
+- - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFESR 7 0 4 1
+- - - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFER 8 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFESS 9 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFES 10 0 4 1
+- - - -
+
+# Inputs: C D
+# Outputs: Q
+SB_DFFN 11 0 2 1
+- -
+
+# Inputs: C D E
+# Outputs: Q
+SB_DFFNE 12 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFNSR 13 0 3 1
+- - -
+
+# Inputs: C D R
+# Outputs: Q
+SB_DFFNR 14 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFNSS 15 0 3 1
+- - -
+
+# Inputs: C D S
+# Outputs: Q
+SB_DFFNS 16 0 3 1
+- - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFNESR 17 0 4 1
+- - - -
+
+# Inputs: C D E R
+# Outputs: Q
+SB_DFFNER 18 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFNESS 19 0 4 1
+- - - -
+
+# Inputs: C D E S
+# Outputs: Q
+SB_DFFNES 20 0 4 1
+- - - -
+
+# Inputs: CI I0 I1
+# Outputs: CO
+SB_CARRY 21 1 3 1
+278 675 609
+
+# Inputs: I0 I1 I2 I3
+# Outputs: O
+SB_LUT4 22 0 4 1
+1285 1231 1205 874
diff --git a/techlibs/ice40/abc_u.lut b/techlibs/ice40/abc_u.lut
new file mode 100644
index 000000000..1e4fcadb6
--- /dev/null
+++ b/techlibs/ice40/abc_u.lut
@@ -0,0 +1,6 @@
+# From https://github.com/cliffordwolf/icestorm/blob/be0bca0/icefuzz/timings_up5k.txt
+# I3 I2 I1 I0
+1 1 874
+2 1 874 1205
+3 1 874 1205 1231
+4 1 874 1205 1231 1285
diff --git a/techlibs/ice40/cells_map.v b/techlibs/ice40/cells_map.v
index d0ddfd02e..287c48b11 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -37,20 +37,24 @@ module \$lut (A, Y);
generate
if (WIDTH == 1) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0));
+ localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(1'b0), .I1(1'b0), .I2(1'b0), .I3(A[0]));
end else
if (WIDTH == 2) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(1'b0), .I3(1'b0));
+ localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[1]}}, {4{LUT[2]}}, {4{LUT[0]}}};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(1'b0), .I1(1'b0), .I2(A[1]), .I3(A[0]));
end else
if (WIDTH == 3) begin
- SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(1'b0));
+ localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[3]}}, {2{LUT[5]}}, {2{LUT[1]}}, {2{LUT[6]}}, {2{LUT[2]}}, {2{LUT[4]}}, {2{LUT[0]}}};
+ SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
+ .I0(1'b0), .I1(A[2]), .I2(A[1]), .I3(A[0]));
end else
if (WIDTH == 4) begin
+ localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]};
SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
- .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
+ .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 00843b97c..40e54f9f0 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -127,6 +127,7 @@ endmodule
// SiliconBlue Logic Cells
+(* abc_box_id = 22 *)
module SB_LUT4 (output O, input I0, I1, I2, I3);
parameter [15:0] LUT_INIT = 0;
wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
@@ -135,24 +136,32 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
assign O = I0 ? s1[1] : s1[0];
endmodule
+(* abc_box_id = 21, lib_whitebox *)
module SB_CARRY (output CO, input I0, I1, CI);
assign CO = (I0 && I1) || ((I0 || I1) && CI);
endmodule
// Positive Edge SiliconBlue FF Cells
-module SB_DFF (output `SB_DFF_REG, input C, D);
+(* abc_box_id = 1, abc_flop, lib_whitebox *)
+module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
+`ifndef ABC_MODEL
always @(posedge C)
Q <= D;
+`else
+ always @* Q = D;
+`endif
endmodule
-module SB_DFFE (output `SB_DFF_REG, input C, E, D);
+//(* abc_box_id = 2, abc_flop *)
+module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
always @(posedge C)
if (E)
Q <= D;
endmodule
-module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
+//(* abc_box_id = 3, abc_flop *)
+module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
always @(posedge C)
if (R)
Q <= 0;
@@ -160,7 +169,8 @@ module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
Q <= D;
endmodule
-module SB_DFFR (output `SB_DFF_REG, input C, R, D);
+//(* abc_box_id = 4, abc_flop *)
+module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -168,7 +178,8 @@ module SB_DFFR (output `SB_DFF_REG, input C, R, D);
Q <= D;
endmodule
-module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
+//(* abc_box_id = 5, abc_flop *)
+module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
always @(posedge C)
if (S)
Q <= 1;
@@ -176,7 +187,8 @@ module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
Q <= D;
endmodule
-module SB_DFFS (output `SB_DFF_REG, input C, S, D);
+//(* abc_box_id = 6, abc_flop *)
+module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -184,7 +196,8 @@ module SB_DFFS (output `SB_DFF_REG, input C, S, D);
Q <= D;
endmodule
-module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
+//(* abc_box_id = 7, abc_flop *)
+module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
always @(posedge C)
if (E) begin
if (R)
@@ -194,7 +207,8 @@ module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
end
endmodule
-module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
+//(* abc_box_id = 8, abc_flop *)
+module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -202,7 +216,8 @@ module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
Q <= D;
endmodule
-module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
+//(* abc_box_id = 9, abc_flop *)
+module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
always @(posedge C)
if (E) begin
if (S)
@@ -212,7 +227,8 @@ module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
end
endmodule
-module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
+//(* abc_box_id = 10, abc_flop *)
+module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -222,18 +238,21 @@ endmodule
// Negative Edge SiliconBlue FF Cells
-module SB_DFFN (output `SB_DFF_REG, input C, D);
+//(* abc_box_id = 11, abc_flop *)
+module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
always @(negedge C)
Q <= D;
endmodule
-module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
+//(* abc_box_id = 12, abc_flop *)
+module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
always @(negedge C)
if (E)
Q <= D;
endmodule
-module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
+//(* abc_box_id = 13, abc_flop *)
+module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
always @(negedge C)
if (R)
Q <= 0;
@@ -241,7 +260,8 @@ module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
Q <= D;
endmodule
-module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
+//(* abc_box_id = 14, abc_flop *)
+module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -249,7 +269,8 @@ module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
Q <= D;
endmodule
-module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
+//(* abc_box_id = 15, abc_flop *)
+module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
always @(negedge C)
if (S)
Q <= 1;
@@ -257,7 +278,8 @@ module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
Q <= D;
endmodule
-module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
+//(* abc_box_id = 16, abc_flop *)
+module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -265,7 +287,8 @@ module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
Q <= D;
endmodule
-module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
+//(* abc_box_id = 17, abc_flop *)
+module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
always @(negedge C)
if (E) begin
if (R)
@@ -275,7 +298,8 @@ module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
end
endmodule
-module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
+//(* abc_box_id = 18, abc_flop *)
+module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -283,7 +307,8 @@ module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
Q <= D;
endmodule
-module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
+//(* abc_box_id = 19, abc_flop *)
+module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
always @(negedge C)
if (E) begin
if (S)
@@ -293,7 +318,8 @@ module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
end
endmodule
-module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
+//(* abc_box_id = 20, abc_flop *)
+module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -304,7 +330,7 @@ endmodule
// SiliconBlue RAM Cells
module SB_RAM40_4K (
- output [15:0] RDATA,
+ (* abc_flop_q *) output [15:0] RDATA,
input RCLK, RCLKE, RE,
input [10:0] RADDR,
input WCLK, WCLKE, WE,
@@ -472,7 +498,7 @@ module SB_RAM40_4K (
endmodule
module SB_RAM40_4KNR (
- output [15:0] RDATA,
+ (* abc_flop_q *) output [15:0] RDATA,
input RCLKN, RCLKE, RE,
input [10:0] RADDR,
input WCLK, WCLKE, WE,
@@ -537,7 +563,7 @@ module SB_RAM40_4KNR (
endmodule
module SB_RAM40_4KNW (
- output [15:0] RDATA,
+ (* abc_flop_q *) output [15:0] RDATA,
input RCLK, RCLKE, RE,
input [10:0] RADDR,
input WCLKN, WCLKE, WE,
@@ -602,7 +628,7 @@ module SB_RAM40_4KNW (
endmodule
module SB_RAM40_4KNRNW (
- output [15:0] RDATA,
+ (* abc_flop_q *) output [15:0] RDATA,
input RCLKN, RCLKE, RE,
input [10:0] RADDR,
input WCLKN, WCLKE, WE,
@@ -890,12 +916,13 @@ module SB_WARMBOOT (
);
endmodule
+(* nomem2reg *)
module SB_SPRAM256KA (
input [13:0] ADDRESS,
input [15:0] DATAIN,
input [3:0] MASKWREN,
input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF,
- output reg [15:0] DATAOUT
+ (* abc_flop_q *) output reg [15:0] DATAOUT
);
`ifndef BLACKBOX
`ifndef EQUIV
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 6c77e5482..718f9d9e0 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -37,6 +37,10 @@ struct SynthIce40Pass : public ScriptPass
log("\n");
log("This command runs synthesis for iCE40 FPGAs.\n");
log("\n");
+ log(" -device < hx | lp | u >\n");
+ log(" optimise the synthesis netlist for the specified device.\n");
+ log(" HX is the default target if no device argument specified.\n");
+ log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
@@ -102,7 +106,7 @@ struct SynthIce40Pass : public ScriptPass
}
- string top_opt, blif_file, edif_file, json_file, abc;
+ string top_opt, blif_file, edif_file, json_file, abc, device_opt;
bool nocarry, nodffe, nobram, dsp, flatten, retime, relut, noabc, abc2, vpr;
int min_ce_use;
@@ -124,6 +128,7 @@ struct SynthIce40Pass : public ScriptPass
abc2 = false;
vpr = false;
abc = "abc";
+ device_opt = "hx";
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -210,12 +215,18 @@ struct SynthIce40Pass : public ScriptPass
abc = "abc9";
continue;
}
+ if (args[argidx] == "-device" && argidx+1 < args.size()) {
+ device_opt = args[++argidx];
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
+ if (device_opt != "hx" && device_opt != "lp" && device_opt !="u")
+ log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str());
log_header(design, "Executing SYNTH_ICE40 pass.\n");
log_push();
@@ -229,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass
{
if (check_label("begin"))
{
- run("read_verilog -lib +/ice40/cells_sim.v");
+ run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
run("proc");
}
@@ -282,7 +293,7 @@ struct SynthIce40Pass : public ScriptPass
run("techmap");
else
run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
- if (retime || help_mode)
+ if ((retime || help_mode) && abc != "abc9")
run(abc + " -dff", "(only if -retime)");
run("ice40_opt");
}
@@ -316,7 +327,10 @@ struct SynthIce40Pass : public ScriptPass
run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
}
if (!noabc) {
- run(abc + " -dress -lut 4", "(skip if -noabc)");
+ if (abc == "abc9")
+ run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
+ else
+ run(abc + " -lut 4", "(skip if -noabc)");
}
run("clean");
if (relut || help_mode) {
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index 0f1d7a7b5..d2291b8d4 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -38,7 +38,7 @@ struct SynthIntelPass : public ScriptPass {
log("\n");
log(" -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
log(" generate the synthesis netlist for the specified family.\n");
- log(" MAX10 is the default target if not family argument specified.\n");
+ log(" MAX10 is the default target if no family argument specified.\n");
log(" For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
log(" Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
log("\n");
@@ -146,7 +146,7 @@ struct SynthIntelPass : public ScriptPass {
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
if (family_opt != "max10" && family_opt !="a10gx" && family_opt != "cyclonev" && family_opt !="cycloneiv" && family_opt !="cycloneive" && family_opt != "cyclone10")
- log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
+ log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
log_header(design, "Executing SYNTH_INTEL pass.\n");
log_push();
diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh
index af003d52e..97f284378 100755
--- a/tests/simple_abc9/run-test.sh
+++ b/tests/simple_abc9/run-test.sh
@@ -19,4 +19,4 @@ fi
cp ../simple/*.v .
DOLLAR='?'
-exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_'"
+exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
diff --git a/tests/various/pmux2shiftx.ys b/tests/various/pmux2shiftx.ys
index 6bb9626eb..deb134083 100644
--- a/tests/various/pmux2shiftx.ys
+++ b/tests/various/pmux2shiftx.ys
@@ -9,8 +9,8 @@ opt
stat
# show -width
select -assert-count 1 t:$sub
-select -assert-count 2 t:$mux
-select -assert-count 2 t:$shift
+select -assert-count 1 t:$mux
+select -assert-count 1 t:$shift
select -assert-count 3 t:$shiftx
design -stash gate