aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--backends/smt2/smtio.py6
-rw-r--r--frontends/aiger/aigerparse.cc4
-rw-r--r--frontends/liberty/liberty.cc2
-rw-r--r--kernel/log.cc17
-rw-r--r--passes/memory/memory_bram.cc4
-rw-r--r--passes/opt/opt_lut.cc94
-rw-r--r--passes/techmap/abc.cc4
-rw-r--r--passes/techmap/extract_fa.cc12
-rw-r--r--techlibs/ice40/abc_hx.box12
-rw-r--r--techlibs/ice40/abc_lp.box12
-rw-r--r--techlibs/ice40/abc_u.box14
-rw-r--r--techlibs/ice40/arith_map.v10
-rw-r--r--techlibs/ice40/cells_map.v24
-rw-r--r--techlibs/ice40/cells_sim.v27
-rw-r--r--techlibs/ice40/ice40_opt.cc45
-rw-r--r--techlibs/ice40/synth_ice40.cc5
17 files changed, 193 insertions, 101 deletions
diff --git a/README.md b/README.md
index 42f972c8e..9e221be38 100644
--- a/README.md
+++ b/README.md
@@ -78,7 +78,7 @@ Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies
On FreeBSD use the following command to install all prerequisites:
# pkg install bison flex readline gawk libffi\
- git graphviz pkgconfig python3 python36 tcl-wrapper boost-libs
+ git graphviz pkgconf python3 python36 tcl-wrapper boost-libs
On FreeBSD system use gmake instead of make. To run tests use:
% MAKE=gmake CC=cc gmake test
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index ae7968a1b..bac68ac70 100644
--- a/backends/smt2/smtio.py
+++ b/backends/smt2/smtio.py
@@ -43,7 +43,11 @@ if os.name == "posix":
if current_rlimit_stack[1] != resource.RLIM_INFINITY:
smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1])
if current_rlimit_stack[0] < smtio_stacksize:
- resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1]))
+ try:
+ resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1]))
+ except ValueError:
+ # couldn't get more stack, just run with what we have
+ pass
# currently running solvers (so we can kill them)
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 1ac0f7ba4..03c541b7c 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -1062,8 +1062,8 @@ struct AigerFrontend : public Frontend {
if (module_name.empty()) {
#ifdef _WIN32
char fname[_MAX_FNAME];
- _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */)
- module_name = fname;
+ _splitpath(filename.c_str(), NULL /* drive */, NULL /* dir */, fname, NULL /* ext */);
+ module_name = fname;
#else
char* bn = strdup(filename.c_str());
module_name = RTLIL::escape_id(bn);
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index 6e3cffaca..14de95e07 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -551,7 +551,7 @@ struct LibertyFrontend : public Frontend {
if (design->has(cell_name)) {
Module *existing_mod = design->module(cell_name);
if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
- log_error("Re-definition of of cell/module %s!\n", log_id(cell_name));
+ log_error("Re-definition of cell/module %s!\n", log_id(cell_name));
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", log_id(cell_name));
continue;
diff --git a/kernel/log.cc b/kernel/log.cc
index a7820950c..e0a60ca12 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -61,7 +61,7 @@ int log_force_debug = 0;
int log_debug_suppressed = 0;
vector<int> header_count;
-pool<RTLIL::IdString> log_id_cache;
+vector<char*> log_id_cache;
vector<shared_str> string_buf;
int string_buf_index = -1;
@@ -69,6 +69,13 @@ static struct timeval initial_tv = { 0, 0 };
static bool next_print_log = false;
static int log_newline_count = 0;
+static void log_id_cache_clear()
+{
+ for (auto p : log_id_cache)
+ free(p);
+ log_id_cache.clear();
+}
+
#if defined(_WIN32) && !defined(__MINGW32__)
// this will get time information and return it in timeval, simulating gettimeofday()
int gettimeofday(struct timeval *tv, struct timezone *tz)
@@ -414,7 +421,7 @@ void log_push()
void log_pop()
{
header_count.pop_back();
- log_id_cache.clear();
+ log_id_cache_clear();
string_buf.clear();
string_buf_index = -1;
log_flush();
@@ -521,7 +528,7 @@ void log_reset_stack()
{
while (header_count.size() > 1)
header_count.pop_back();
- log_id_cache.clear();
+ log_id_cache_clear();
string_buf.clear();
string_buf_index = -1;
log_flush();
@@ -580,8 +587,8 @@ const char *log_const(const RTLIL::Const &value, bool autoint)
const char *log_id(RTLIL::IdString str)
{
- log_id_cache.insert(str);
- const char *p = str.c_str();
+ log_id_cache.push_back(strdup(str.c_str()));
+ const char *p = log_id_cache.back();
if (p[0] != '\\')
return p;
if (p[1] == '$' || p[1] == '\\' || p[1] == 0)
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index ddc56d9b5..aa8f94149 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -68,6 +68,10 @@ struct rules_t
if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", log_id(name), variant, groups, GetSize(transp));
if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", log_id(name), variant, groups, GetSize(clocks));
if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", log_id(name), variant, groups, GetSize(clkpol));
+
+ int group = 0;
+ for (auto e : enable)
+ if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", log_id(name), variant, group, e, dbits);
}
vector<portinfo_t> make_portinfos() const
diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc
index 26855fd70..182f63d99 100644
--- a/passes/opt/opt_lut.cc
+++ b/passes/opt/opt_lut.cc
@@ -105,7 +105,7 @@ struct OptLutWorker
SigSpec lut_input = cell->getPort("\\A");
int lut_arity = 0;
- log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
+ log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
luts.insert(cell);
// First, find all dedicated logic we're connected to. This results in an overapproximation
@@ -147,15 +147,15 @@ struct OptLutWorker
{
if (lut_width <= dlogic_conn.first)
{
- log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
- log(" LUT input A[%d] not present.\n", dlogic_conn.first);
+ log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
+ log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first);
legal = false;
break;
}
if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second)))
{
- log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
- log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second)));
+ log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
+ log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second)));
legal = false;
break;
}
@@ -163,7 +163,7 @@ struct OptLutWorker
if (legal)
{
- log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
+ log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
lut_legal_dlogics.insert(lut_dlogic);
for (auto &dlogic_conn : dlogic_map)
lut_dlogic_inputs.insert(dlogic_conn.first);
@@ -179,7 +179,7 @@ struct OptLutWorker
lut_arity++;
}
- log(" Cell implements a %d-LUT.\n", lut_arity);
+ log_debug(" Cell implements a %d-LUT.\n", lut_arity);
luts_arity[cell] = lut_arity;
luts_dlogics[cell] = lut_legal_dlogics;
luts_dlogic_inputs[cell] = lut_dlogic_inputs;
@@ -239,28 +239,26 @@ struct OptLutWorker
if (const0_match || const1_match || input_match != -1)
{
- log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut));
+ log_debug("Found redundant cell %s.%s.\n", log_id(module), log_id(lut));
SigBit value;
if (const0_match)
{
- log(" Cell evaluates constant 0.\n");
+ log_debug(" Cell evaluates constant 0.\n");
value = State::S0;
}
if (const1_match)
{
- log(" Cell evaluates constant 1.\n");
+ log_debug(" Cell evaluates constant 1.\n");
value = State::S1;
}
if (input_match != -1) {
- log(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match]));
+ log_debug(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match]));
value = lut_inputs[input_match];
}
if (lut_dlogic_inputs.size())
- {
- log(" Not eliminating cell (connected to dedicated logic).\n");
- }
+ log_debug(" Not eliminating cell (connected to dedicated logic).\n");
else
{
SigSpec lut_output = lut->getPort("\\Y");
@@ -323,11 +321,11 @@ struct OptLutWorker
int lutB_arity = luts_arity[lutB];
pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
- log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
+ log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
if (index.query_is_output(lutA->getPort("\\Y")))
{
- log(" Not combining LUTs (cascade connection feeds module output).\n");
+ log_debug(" Not combining LUTs (cascade connection feeds module output).\n");
continue;
}
@@ -353,67 +351,51 @@ struct OptLutWorker
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
if (lutA_dlogic_inputs.size())
- log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
+ log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
else
- log(" Cell A is a %d-LUT. ", lutA_arity);
+ log_debug(" Cell A is a %d-LUT. ", lutA_arity);
if (lutB_dlogic_inputs.size())
- log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
+ log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
else
- log("Cell B is a %d-LUT.\n", lutB_arity);
- log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
+ log_debug("Cell B is a %d-LUT.\n", lutB_arity);
+ log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
int combine_mask = 0;
if (lutM_arity > lutA_width)
- {
- log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n");
- }
+ log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n");
else if (lutB_dlogic_inputs.size() > 0)
- {
- log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
- }
+ log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
else if (lutB->get_bool_attribute("\\lut_keep"))
- {
- log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
- }
+ log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
else
- {
combine_mask |= COMBINE_A;
- }
if (lutM_arity > lutB_width)
- {
- log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n");
- }
+ log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n");
else if (lutA_dlogic_inputs.size() > 0)
- {
- log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
- }
+ log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
else if (lutA->get_bool_attribute("\\lut_keep"))
- {
- log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
- }
+ log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
else
- {
combine_mask |= COMBINE_B;
- }
int combine = combine_mask;
if (combine == COMBINE_EITHER)
{
- log(" Can combine into either cell.\n");
+ log_debug(" Can combine into either cell.\n");
if (lutA_arity == 1)
{
- log(" Cell A is a buffer or inverter, combining into cell B.\n");
+ log_debug(" Cell A is a buffer or inverter, combining into cell B.\n");
combine = COMBINE_B;
}
else if (lutB_arity == 1)
{
- log(" Cell B is a buffer or inverter, combining into cell A.\n");
+ log_debug(" Cell B is a buffer or inverter, combining into cell A.\n");
combine = COMBINE_A;
}
else
{
- log(" Arbitrarily combining into cell A.\n");
+ log_debug(" Arbitrarily combining into cell A.\n");
combine = COMBINE_A;
}
}
@@ -423,7 +405,7 @@ struct OptLutWorker
pool<int> lutM_dlogic_inputs;
if (combine == COMBINE_A)
{
- log(" Combining LUTs into cell A.\n");
+ log_debug(" Combining LUTs into cell A.\n");
lutM = lutA;
lutM_inputs = lutA_inputs;
lutM_dlogic_inputs = lutA_dlogic_inputs;
@@ -432,7 +414,7 @@ struct OptLutWorker
}
else if (combine == COMBINE_B)
{
- log(" Combining LUTs into cell B.\n");
+ log_debug(" Combining LUTs into cell B.\n");
lutM = lutB;
lutM_inputs = lutB_inputs;
lutM_dlogic_inputs = lutB_dlogic_inputs;
@@ -441,7 +423,7 @@ struct OptLutWorker
}
else
{
- log(" Cannot combine LUTs.\n");
+ log_debug(" Cannot combine LUTs.\n");
continue;
}
@@ -466,17 +448,17 @@ struct OptLutWorker
if (input_unused && lutR_unique.size())
{
SigBit new_input = lutR_unique.pop();
- log(" Connecting input %d as %s.\n", i, log_signal(new_input));
+ log_debug(" Connecting input %d as %s.\n", i, log_signal(new_input));
lutM_new_inputs.push_back(new_input);
}
else if (sigmap(lutM_input[i]) == lutA_output)
{
- log(" Disconnecting cascade input %d.\n", i);
+ log_debug(" Disconnecting cascade input %d.\n", i);
lutM_new_inputs.push_back(SigBit());
}
else
{
- log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i]));
+ log_debug(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i]));
lutM_new_inputs.push_back(lutM_input[i]);
}
}
@@ -494,9 +476,9 @@ struct OptLutWorker
lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
}
- log(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
- log(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
- log(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
+ log_debug(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
+ log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
+ log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
lutM->setParam("\\LUT", lutM_new_table);
lutM->setPort("\\A", lutM_new_inputs);
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 15e79f9d1..65c7d1bb8 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -1172,8 +1172,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
continue;
}
}
-
- cell_stats[RTLIL::unescape_id(c->type)]++;
+ else
+ cell_stats[RTLIL::unescape_id(c->type)]++;
if (c->type == "\\_const0_" || c->type == "\\_const1_") {
RTLIL::SigSig conn;
diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc
index 9e6dc0d24..591bc43dd 100644
--- a/passes/techmap/extract_fa.cc
+++ b/passes/techmap/extract_fa.cc
@@ -174,8 +174,10 @@ struct ExtractFaWorker
SigSpec sig = root;
- if (!ce.eval(sig))
- log_abort();
+ if (!ce.eval(sig)) {
+ ce.pop();
+ return;
+ }
if (sig == State::S1)
func |= 1 << i;
@@ -214,8 +216,10 @@ struct ExtractFaWorker
SigSpec sig = root;
- if (!ce.eval(sig))
- log_abort();
+ if (!ce.eval(sig)) {
+ ce.pop();
+ return;
+ }
if (sig == State::S1)
func |= 1 << i;
diff --git a/techlibs/ice40/abc_hx.box b/techlibs/ice40/abc_hx.box
index f8e12b527..c0ea742e2 100644
--- a/techlibs/ice40/abc_hx.box
+++ b/techlibs/ice40/abc_hx.box
@@ -3,15 +3,11 @@
# NB: Inputs/Outputs must be ordered alphabetically
# (with exceptions for carry in/out)
-# Inputs: I0 I1 CI
-# Outputs: CO
+# Inputs: A B CI
+# Outputs: O CO
# (NB: carry chain input/output must be last
# input/output and have been moved there
# overriding the alphabetical ordering)
-SB_CARRY 1 1 3 1
+$__ICE40_FULL_ADDER 1 1 3 2
+400 379 316
259 231 126
-
-# Inputs: I0 I1 I2 I3
-# Outputs: O
-SB_LUT4 2 1 4 1
-449 400 379 316
diff --git a/techlibs/ice40/abc_lp.box b/techlibs/ice40/abc_lp.box
index fbe4c56e6..d73b6d649 100644
--- a/techlibs/ice40/abc_lp.box
+++ b/techlibs/ice40/abc_lp.box
@@ -3,15 +3,11 @@
# NB: Inputs/Outputs must be ordered alphabetically
# (with exceptions for carry in/out)
-# Inputs: CI I0 I1
-# Outputs: CO
+# Inputs: A B CI
+# Outputs: O CO
# (NB: carry chain input/output must be last
# input/output and have been moved there
# overriding the alphabetical ordering)
-SB_CARRY 1 1 3 1
+$__ICE40_FULL_ADDER 1 1 3 2
+589 558 465
675 609 186
-
-# Inputs: I0 I1 I2 I3
-# Outputs: O
-SB_LUT4 2 1 4 1
-661 589 558 465
diff --git a/techlibs/ice40/abc_u.box b/techlibs/ice40/abc_u.box
index f44deabc4..42d666051 100644
--- a/techlibs/ice40/abc_u.box
+++ b/techlibs/ice40/abc_u.box
@@ -3,15 +3,11 @@
# NB: Inputs/Outputs must be ordered alphabetically
# (with exceptions for carry in/out)
-# Inputs: I0 I1 CI
-# Outputs: CO
+# Inputs: A B CI
+# Outputs: O CO
# (NB: carry chain input/output must be last
# input/output and have been moved there
# overriding the alphabetical ordering)
-SB_CARRY 1 1 3 1
-675 609 278
-
-# Inputs: I0 I1 I2 I3
-# Outputs: O
-SB_LUT4 2 1 4 1
-1285 1231 1205 874
+$__ICE40_FULL_ADDER 1 1 3 2
+1231 1205 874
+675 609 278
diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v
index 4449fdc1b..fe83a8e38 100644
--- a/techlibs/ice40/arith_map.v
+++ b/techlibs/ice40/arith_map.v
@@ -44,6 +44,15 @@ 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 (
+ .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]),
@@ -63,6 +72,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
.I3(C[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 759549e30..b4b831165 100644
--- a/techlibs/ice40/cells_map.v
+++ b/techlibs/ice40/cells_map.v
@@ -61,3 +61,27 @@ module \$lut (A, Y);
endgenerate
endmodule
`endif
+
+`ifdef _ABC
+module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
+ 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)
+ );
+endmodule
+`endif
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index b746ba4e5..609facc93 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -127,7 +127,7 @@ endmodule
// SiliconBlue Logic Cells
-(* abc_box_id = 2, lib_whitebox *)
+(* lib_whitebox *)
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];
@@ -136,11 +136,34 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
assign O = I0 ? s1[1] : s1[0];
endmodule
-(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *)
+(* lib_whitebox *)
module SB_CARRY (output CO, input I0, I1, CI);
assign CO = (I0 && I1) || ((I0 || I1) && CI);
endmodule
+(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *)
+module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
+ 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)
+ );
+endmodule
+
// Positive Edge SiliconBlue FF Cells
module SB_DFF (output `SB_DFF_REG, input C, D);
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index f528607d6..e492454fb 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -83,6 +83,51 @@ static void run_ice40_opts(Module *module)
}
continue;
}
+
+ if (cell->type == "$__ICE40_FULL_ADDER")
+ {
+ SigSpec non_const_inputs, replacement_output;
+ int count_zeros = 0, count_ones = 0;
+
+ SigBit inbit[3] = {
+ cell->getPort("\\A"),
+ cell->getPort("\\B"),
+ cell->getPort("\\CI")
+ };
+ for (int i = 0; i < 3; i++)
+ if (inbit[i].wire == nullptr) {
+ if (inbit[i] == State::S1)
+ count_ones++;
+ else
+ count_zeros++;
+ } else
+ non_const_inputs.append(inbit[i]);
+
+ if (count_zeros >= 2)
+ replacement_output = State::S0;
+ else if (count_ones >= 2)
+ replacement_output = State::S1;
+ else if (GetSize(non_const_inputs) == 1)
+ replacement_output = non_const_inputs;
+
+ if (GetSize(replacement_output)) {
+ optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
+ module->connect(cell->getPort("\\CO")[0], replacement_output);
+ module->design->scratchpad_set_bool("opt.did_something", true);
+ log("Optimized $__ICE40_FULL_ADDER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
+ log_id(module), log_id(cell), log_signal(replacement_output));
+ cell->type = "$lut";
+ cell->setPort("\\A", { RTLIL::S0, inbit[0], inbit[1], inbit[2] });
+ cell->setPort("\\Y", cell->getPort("\\O"));
+ cell->unsetPort("\\B");
+ cell->unsetPort("\\CI");
+ cell->unsetPort("\\CO");
+ cell->unsetPort("\\O");
+ cell->setParam("\\LUT", RTLIL::Const::from_string("0110100110010110"));
+ cell->setParam("\\WIDTH", 4);
+ }
+ continue;
+ }
}
for (auto cell : sb_lut_cells)
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index 0474e76e9..b3d30791a 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 -lib -D_ABC +/ice40/cells_sim.v");
+ run("read_verilog -icells -lib -D_ABC +/ice40/cells_sim.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
run("proc");
}
@@ -294,7 +294,7 @@ struct SynthIce40Pass : public ScriptPass
if (nocarry)
run("techmap");
else
- run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
+ run("techmap -map +/techmap.v -map +/ice40/arith_map.v" + std::string(abc == "abc9" ? " -D _ABC" : ""));
if (retime || help_mode)
run(abc + " -dff", "(only if -retime)");
run("ice40_opt");
@@ -338,6 +338,7 @@ 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)");