aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.editorconfig7
-rw-r--r--.travis.yml4
-rwxr-xr-x.travis/setup.sh1
-rw-r--r--Makefile5
-rw-r--r--backends/btor/btor.cc22
-rw-r--r--backends/smt2/smtbmc.py105
-rw-r--r--backends/verilog/verilog_backend.cc2
-rw-r--r--frontends/ast/simplify.cc2
-rw-r--r--frontends/verific/verific.cc53
-rw-r--r--frontends/verilog/verilog_parser.y48
-rw-r--r--kernel/celltypes.h19
-rw-r--r--kernel/consteval.h9
-rw-r--r--passes/cmds/rename.cc50
-rw-r--r--passes/equiv/Makefile.inc2
-rw-r--r--passes/equiv/equiv_make.cc27
-rw-r--r--passes/equiv/equiv_opt.cc157
-rw-r--r--passes/memory/memory_bram.cc17
-rw-r--r--passes/opt/Makefile.inc1
-rw-r--r--passes/opt/opt_expr.cc2
-rw-r--r--passes/opt/opt_lut.cc503
-rw-r--r--passes/opt/opt_muxtree.cc18
-rw-r--r--passes/techmap/abc.cc80
-rw-r--r--passes/techmap/deminout.cc7
-rw-r--r--passes/techmap/dff2dffe.cc35
-rw-r--r--passes/techmap/lut2mux.cc2
-rw-r--r--techlibs/anlogic/Makefile.inc8
-rw-r--r--techlibs/anlogic/anlogic_eqn.cc113
-rw-r--r--techlibs/anlogic/arith_map.v84
-rw-r--r--techlibs/anlogic/cells_map.v49
-rw-r--r--techlibs/anlogic/cells_sim.v103
-rw-r--r--techlibs/anlogic/eagle_bb.v716
-rw-r--r--techlibs/anlogic/synth_anlogic.cc205
-rw-r--r--techlibs/common/Makefile.inc1
-rw-r--r--techlibs/common/gate2lut.v87
-rw-r--r--techlibs/common/simcells.v4
-rw-r--r--techlibs/gowin/Makefile.inc1
-rw-r--r--techlibs/gowin/arith_map.v59
-rw-r--r--techlibs/gowin/cells_sim.v6
-rw-r--r--techlibs/gowin/synth_gowin.cc21
-rw-r--r--techlibs/ice40/Makefile.inc1
-rw-r--r--techlibs/ice40/cells_sim.v21
-rw-r--r--techlibs/ice40/ice40_ffssr.cc3
-rw-r--r--techlibs/ice40/ice40_opt.cc15
-rw-r--r--techlibs/ice40/ice40_unlut.cc106
-rw-r--r--techlibs/ice40/synth_ice40.cc48
-rw-r--r--techlibs/intel/common/brams_map.v16
-rw-r--r--tests/lut/.gitignore1
-rw-r--r--tests/lut/check_map.ys4
-rw-r--r--tests/lut/map_and.v5
-rw-r--r--tests/lut/map_mux.v5
-rw-r--r--tests/lut/map_not.v5
-rw-r--r--tests/lut/map_or.v5
-rw-r--r--tests/lut/map_xor.v5
-rw-r--r--tests/lut/run-test.sh6
-rw-r--r--tests/opt/.gitignore1
-rw-r--r--tests/opt/opt_lut.v18
-rw-r--r--tests/opt/opt_lut.ys4
-rw-r--r--tests/opt/opt_lut_port.il18
-rw-r--r--tests/opt/opt_lut_port.ys2
-rwxr-xr-xtests/opt/run-test.sh6
-rw-r--r--tests/svinterfaces/.gitignore8
61 files changed, 2766 insertions, 172 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..4d6f5ef7a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,7 @@
+root = true
+
+[*]
+indent_style = tab
+indent_size = tab
+trim_trailing_whitespace = true
+insert_final_newline = true
diff --git a/.travis.yml b/.travis.yml
index 321c3325f..8aacbb8b1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -134,9 +134,9 @@ matrix:
# Latest clang on Mac OS X
- os: osx
- osx_image: xcode8
+ osx_image: xcode9.4
env:
- - MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
+ - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
before_install:
- ./.travis/setup.sh
diff --git a/.travis/setup.sh b/.travis/setup.sh
index 068515786..d689cd2bd 100755
--- a/.travis/setup.sh
+++ b/.travis/setup.sh
@@ -64,7 +64,6 @@ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew tap Homebrew/bundle
brew bundle
brew install ccache
- brew install gcc@7
echo
echo -en 'travis_fold:end:before_install.brew\\r'
echo
diff --git a/Makefile b/Makefile
index acabb3ee2..128539f6a 100644
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,7 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),gcc-static)
LD = $(CXX)
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -static
-LDLIBS := $(filter-out -lrt,$(LDLIBS))
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
CXXFLAGS += -std=c++11 -Os
ABCMKARGS = CC="$(CC)" CXX="$(CXX)" LD="$(LD)" ABC_USE_LIBSTDCXX=1 LIBS="-lm -lpthread -static" OPTFLAGS="-O" \
@@ -358,7 +358,7 @@ endif
ifeq ($(ENABLE_VERIFIC),1)
VERIFIC_DIR ?= /usr/local/src/verific_lib_eval
-VERIFIC_COMPONENTS ?= verilog vhdl database util containers sdf hier_tree
+VERIFIC_COMPONENTS ?= verilog vhdl database util containers hier_tree
CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC
ifeq ($(OS), Darwin)
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-mac.a,$(VERIFIC_COMPONENTS)) -lz
@@ -579,6 +579,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/various && bash run-test.sh
+cd tests/sat && bash run-test.sh
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
+ +cd tests/opt && bash run-test.sh
@echo ""
@echo " Passed \"make test\"."
@echo ""
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index 58d2a8625..ab2702807 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -506,6 +506,18 @@ struct BtorWorker
}
}
+ Const initval;
+ for (int i = 0; i < GetSize(sig_q); i++)
+ if (initbits.count(sig_q[i]))
+ initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
+ else
+ initval.bits.push_back(State::Sx);
+
+ int nid_init_val = -1;
+
+ if (!initval.is_fully_undef())
+ nid_init_val = get_sig_nid(initval);
+
int sid = get_bv_sid(GetSize(sig_q));
int nid = next_nid++;
@@ -514,15 +526,7 @@ struct BtorWorker
else
btorf("%d state %d %s\n", nid, sid, log_id(symbol));
- Const initval;
- for (int i = 0; i < GetSize(sig_q); i++)
- if (initbits.count(sig_q[i]))
- initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
- else
- initval.bits.push_back(State::Sx);
-
- if (!initval.is_fully_undef()) {
- int nid_init_val = get_sig_nid(initval);
+ if (nid_init_val >= 0) {
int nid_init = next_nid++;
if (verbose)
btorf("; initval = %s\n", log_signal(initval));
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index b944ee004..721a395e3 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -32,6 +32,7 @@ cexfile = None
aimfile = None
aiwfile = None
aigheader = True
+btorwitfile = None
vlogtbfile = None
vlogtbtop = None
inconstr = list()
@@ -92,6 +93,9 @@ yosys-smtbmc [options] <yosys_smt2_output>
the AIGER witness file does not include the status and
properties lines.
+ --btorwit <btor_witness_filename>
+ read a BTOR witness.
+
--noinfo
only run the core proof, do not collect and print any
additional information (e.g. which assert failed)
@@ -152,7 +156,7 @@ yosys-smtbmc [options] <yosys_smt2_output>
try:
opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts +
- ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "presat",
+ ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "btorwit=", "presat",
"dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append=",
"smtc-init", "smtc-top=", "noinit"])
except:
@@ -189,6 +193,8 @@ for o, a in opts:
aiwfile = a + ".aiw"
elif o == "--aig-noheader":
aigheader = False
+ elif o == "--btorwit":
+ btorwitfile = a
elif o == "--dump-vcd":
vcdfile = a
elif o == "--dump-vlogtb":
@@ -575,6 +581,103 @@ if aimfile is not None:
num_steps = max(num_steps, step+1)
step += 1
+if btorwitfile is not None:
+ with open(btorwitfile, "r") as f:
+ step = None
+ suffix = None
+ altsuffix = None
+ header_okay = False
+
+ for line in f:
+ line = line.strip()
+
+ if line == "sat":
+ header_okay = True
+ continue
+
+ if not header_okay:
+ continue
+
+ if line == "" or line[0] == "b" or line[0] == "j":
+ continue
+
+ if line == ".":
+ break
+
+ if line[0] == '#' or line[0] == '@':
+ step = int(line[1:])
+ suffix = line
+ altsuffix = suffix
+ if suffix[0] == "@":
+ altsuffix = "#" + suffix[1:]
+ else:
+ altsuffix = "@" + suffix[1:]
+ continue
+
+ line = line.split()
+
+ if len(line) == 0:
+ continue
+
+ if line[-1].endswith(suffix):
+ line[-1] = line[-1][0:len(line[-1]) - len(suffix)]
+
+ if line[-1].endswith(altsuffix):
+ line[-1] = line[-1][0:len(line[-1]) - len(altsuffix)]
+
+ if line[-1][0] == "$":
+ continue
+
+ # BV assignments
+ if len(line) == 3 and line[1][0] != "[":
+ value = line[1]
+ name = line[2]
+
+ path = smt.get_path(topmod, name)
+
+ if not smt.net_exists(topmod, path):
+ continue
+
+ width = smt.net_width(topmod, path)
+
+ if width == 1:
+ assert value in ["0", "1"]
+ value = "true" if value == "1" else "false"
+ else:
+ value = "#b" + value
+
+ smtexpr = "(= [%s] %s)" % (name, value)
+ constr_assumes[step].append((btorwitfile, smtexpr))
+
+ # Array assignments
+ if len(line) == 4 and line[1][0] == "[":
+ index = line[1]
+ value = line[2]
+ name = line[3]
+
+ path = smt.get_path(topmod, name)
+
+ if not smt.mem_exists(topmod, path):
+ continue
+
+ meminfo = smt.mem_info(topmod, path)
+
+ if meminfo[1] == 1:
+ assert value in ["0", "1"]
+ value = "true" if value == "1" else "false"
+ else:
+ value = "#b" + value
+
+ assert index[0] == "["
+ assert index[-1] == "]"
+ index = "#b" + index[1:-1]
+
+ smtexpr = "(= (select [%s] %s) %s)" % (name, index, value)
+ constr_assumes[step].append((btorwitfile, smtexpr))
+
+ skip_steps = step
+ num_steps = step+1
+
def write_vcd_trace(steps_start, steps_stop, index):
filename = vcdfile.replace("%", index)
print_msg("Writing trace to VCD file: %s" % (filename))
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index dde03f920..922b4c44c 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -1352,6 +1352,8 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
if (sync->type == RTLIL::STa) {
f << stringf("%s" "always @* begin\n", indent.c_str());
+ } else if (sync->type == RTLIL::STi) {
+ f << stringf("%s" "initial begin\n", indent.c_str());
} else {
f << stringf("%s" "always @(", indent.c_str());
if (sync->type == RTLIL::STp || sync->type == RTLIL::ST1)
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index bb4c9735d..55abe165f 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1913,7 +1913,7 @@ skip_dynamic_range_lvalue_expansion:;
if (arg_value.bits.at(i) == RTLIL::State::S1)
result = i + 1;
- newNode = mkconst_int(result, false);
+ newNode = mkconst_int(result, true);
goto apply_newNode;
}
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 971f0b24a..bc035c31a 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -2094,42 +2094,6 @@ struct VerificPass : public Pass {
if (mode_all)
{
-#if 0
- log("Running veri_file::ElaborateAll().\n");
- if (!veri_file::ElaborateAll())
- log_cmd_error("Elaboration of Verilog modules failed.\n");
-
- log("Running vhdl_file::ElaborateAll().\n");
- if (!vhdl_file::ElaborateAll())
- log_cmd_error("Elaboration of VHDL modules failed.\n");
-
- Library *lib = Netlist::PresentDesign()->Owner()->Owner();
-
- if (argidx == GetSize(args))
- {
- MapIter iter;
- char *iter_name;
- Verific::Cell *iter_cell;
-
- FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) {
- if (*iter_name != '$')
- nl_todo.insert(iter_cell->GetFirstNetlist());
- }
- }
- else
- {
- for (; argidx < GetSize(args); argidx++)
- {
- Verific::Cell *cell = lib->GetCell(args[argidx].c_str());
-
- if (cell == nullptr)
- log_cmd_error("Module not found: %s\n", args[argidx].c_str());
-
- nl_todo.insert(cell->GetFirstNetlist());
- cell->GetFirstNetlist()->SetPresentDesign();
- }
- }
-#else
log("Running hier_tree::ElaborateAll().\n");
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
@@ -2146,28 +2110,12 @@ struct VerificPass : public Pass {
FOREACH_ARRAY_ITEM(netlists, i, nl)
nl_todo.insert(nl);
delete netlists;
-#endif
}
else
{
if (argidx == GetSize(args))
log_cmd_error("No top module specified.\n");
-#if 0
- for (; argidx < GetSize(args); argidx++) {
- if (veri_file::GetModule(args[argidx].c_str())) {
- log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str());
- if (!veri_file::Elaborate(args[argidx].c_str()))
- log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str());
- nl_todo.insert(Netlist::PresentDesign());
- } else {
- log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str());
- if (!vhdl_file::Elaborate(args[argidx].c_str()))
- log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str());
- nl_todo.insert(Netlist::PresentDesign());
- }
- }
-#else
Array veri_modules, vhdl_units;
for (; argidx < GetSize(args); argidx++)
{
@@ -2199,7 +2147,6 @@ struct VerificPass : public Pass {
FOREACH_ARRAY_ITEM(netlists, i, nl)
nl_todo.insert(nl);
delete netlists;
-#endif
}
if (!verific_error_msg.empty())
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 5ab1b62df..51e112ed3 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -35,6 +35,7 @@
%{
#include <list>
+#include <stack>
#include <string.h>
#include "frontends/verilog/verilog_frontend.h"
#include "kernel/log.h"
@@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND {
int port_counter;
std::map<std::string, int> port_stubs;
- std::map<std::string, AstNode*> attr_list, default_attr_list;
+ std::map<std::string, AstNode*> *attr_list, default_attr_list;
+ std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
std::map<std::string, AstNode*> *albuf;
std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3;
@@ -175,15 +177,18 @@ design:
attr:
{
- for (auto &it : attr_list)
- delete it.second;
- attr_list.clear();
+ if (attr_list != nullptr)
+ attr_list_stack.push(attr_list);
+ attr_list = new std::map<std::string, AstNode*>;
for (auto &it : default_attr_list)
- attr_list[it.first] = it.second->clone();
+ (*attr_list)[it.first] = it.second->clone();
} attr_opt {
- std::map<std::string, AstNode*> *al = new std::map<std::string, AstNode*>;
- al->swap(attr_list);
- $$ = al;
+ $$ = attr_list;
+ if (!attr_list_stack.empty()) {
+ attr_list = attr_list_stack.top();
+ attr_list_stack.pop();
+ } else
+ attr_list = nullptr;
};
attr_opt:
@@ -192,15 +197,20 @@ attr_opt:
defattr:
DEFATTR_BEGIN {
+ if (attr_list != nullptr)
+ attr_list_stack.push(attr_list);
+ attr_list = new std::map<std::string, AstNode*>;
for (auto &it : default_attr_list)
delete it.second;
default_attr_list.clear();
- for (auto &it : attr_list)
- delete it.second;
- attr_list.clear();
} opt_attr_list {
- default_attr_list = attr_list;
- attr_list.clear();
+ attr_list->swap(default_attr_list);
+ delete attr_list;
+ if (!attr_list_stack.empty()) {
+ attr_list = attr_list_stack.top();
+ attr_list_stack.pop();
+ } else
+ attr_list = nullptr;
} DEFATTR_END;
opt_attr_list:
@@ -212,15 +222,15 @@ attr_list:
attr_assign:
hierarchical_id {
- if (attr_list.count(*$1) != 0)
- delete attr_list[*$1];
- attr_list[*$1] = AstNode::mkconst_int(1, false);
+ if (attr_list->count(*$1) != 0)
+ delete (*attr_list)[*$1];
+ (*attr_list)[*$1] = AstNode::mkconst_int(1, false);
delete $1;
} |
hierarchical_id '=' expr {
- if (attr_list.count(*$1) != 0)
- delete attr_list[*$1];
- attr_list[*$1] = $3;
+ if (attr_list->count(*$1) != 0)
+ delete (*attr_list)[*$1];
+ (*attr_list)[*$1] = $3;
delete $1;
};
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 6041168bb..8b8a56111 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -257,7 +257,7 @@ struct CellTypes
return v;
}
- static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+ static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len, bool *errp = nullptr)
{
if (type == "$sshr" && !signed1)
type = "$shr";
@@ -329,10 +329,15 @@ struct CellTypes
if (type == "$_ORNOT_")
return const_or(arg1, eval_not(arg2), false, false, 1);
+ if (errp != nullptr) {
+ *errp = true;
+ return State::Sm;
+ }
+
log_abort();
}
- static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+ static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr)
{
if (cell->type == "$slice") {
RTLIL::Const ret;
@@ -415,10 +420,10 @@ struct CellTypes
bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool();
bool signed_b = cell->parameters.count("\\B_SIGNED") > 0 && cell->parameters["\\B_SIGNED"].as_bool();
int result_len = cell->parameters.count("\\Y_WIDTH") > 0 ? cell->parameters["\\Y_WIDTH"].as_int() : -1;
- return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len);
+ return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len, errp);
}
- static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3)
+ static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, bool *errp = nullptr)
{
if (cell->type.in("$mux", "$pmux", "$_MUX_")) {
RTLIL::Const ret = arg1;
@@ -436,10 +441,10 @@ struct CellTypes
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1));
log_assert(arg3.bits.size() == 0);
- return eval(cell, arg1, arg2);
+ return eval(cell, arg1, arg2, errp);
}
- static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4)
+ static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4, bool *errp = nullptr)
{
if (cell->type == "$_AOI4_")
return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
@@ -447,7 +452,7 @@ struct CellTypes
return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1));
log_assert(arg4.bits.size() == 0);
- return eval(cell, arg1, arg2, arg3);
+ return eval(cell, arg1, arg2, arg3, errp);
}
};
diff --git a/kernel/consteval.h b/kernel/consteval.h
index 0229f5045..154373a8d 100644
--- a/kernel/consteval.h
+++ b/kernel/consteval.h
@@ -321,8 +321,13 @@ struct ConstEval
if (sig_d.size() > 0 && !eval(sig_d, undef, cell))
return false;
- set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(),
- sig_c.as_const(), sig_d.as_const()));
+ bool eval_err = false;
+ RTLIL::Const eval_ret = CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(), sig_c.as_const(), sig_d.as_const(), &eval_err);
+
+ if (eval_err)
+ return false;
+
+ set(sig_y, eval_ret);
}
return true;
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index dce576fdf..4b4af0a40 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -52,6 +52,15 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std::
log_cmd_error("Object `%s' not found!\n", from_name.c_str());
}
+static std::string derive_name_from_src(const std::string &src, int counter)
+{
+ std::string src_base = src.substr(0, src.find('|'));
+ if (src_base.empty())
+ return stringf("$%d", counter);
+ else
+ return stringf("\\%s$%d", src_base.c_str(), counter);
+}
+
struct RenamePass : public Pass {
RenamePass() : Pass("rename", "rename object in the design") { }
void help() YS_OVERRIDE
@@ -63,6 +72,10 @@ struct RenamePass : public Pass {
log("Rename the specified object. Note that selection patterns are not supported\n");
log("by this command.\n");
log("\n");
+ log(" rename -src [selection]\n");
+ log("\n");
+ log("Assign names auto-generated from the src attribute to all selected wires and\n");
+ log("cells with private names.\n");
log("\n");
log(" rename -enumerate [-pattern <pattern>] [selection]\n");
log("\n");
@@ -84,6 +97,7 @@ struct RenamePass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string pattern_prefix = "_", pattern_suffix = "_";
+ bool flag_src = false;
bool flag_enumerate = false;
bool flag_hide = false;
bool flag_top = false;
@@ -93,6 +107,11 @@ struct RenamePass : public Pass {
for (argidx = 1; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
+ if (arg == "-src" && !got_mode) {
+ flag_src = true;
+ got_mode = true;
+ continue;
+ }
if (arg == "-enumerate" && !got_mode) {
flag_enumerate = true;
got_mode = true;
@@ -117,6 +136,37 @@ struct RenamePass : public Pass {
break;
}
+ if (flag_src)
+ {
+ extra_args(args, argidx, design);
+
+ for (auto &mod : design->modules_)
+ {
+ int counter = 0;
+
+ RTLIL::Module *module = mod.second;
+ if (!design->selected(module))
+ continue;
+
+ dict<RTLIL::IdString, RTLIL::Wire*> new_wires;
+ for (auto &it : module->wires_) {
+ if (it.first[0] == '$' && design->selected(module, it.second))
+ it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
+ new_wires[it.second->name] = it.second;
+ }
+ module->wires_.swap(new_wires);
+ module->fixup_ports();
+
+ dict<RTLIL::IdString, RTLIL::Cell*> new_cells;
+ for (auto &it : module->cells_) {
+ if (it.first[0] == '$' && design->selected(module, it.second))
+ it.second->name = derive_name_from_src(it.second->get_src_attribute(), counter++);
+ new_cells[it.second->name] = it.second;
+ }
+ module->cells_.swap(new_cells);
+ }
+ }
+ else
if (flag_enumerate)
{
extra_args(args, argidx, design);
diff --git a/passes/equiv/Makefile.inc b/passes/equiv/Makefile.inc
index dd7b3be02..27ea54b22 100644
--- a/passes/equiv/Makefile.inc
+++ b/passes/equiv/Makefile.inc
@@ -9,4 +9,4 @@ OBJS += passes/equiv/equiv_induct.o
OBJS += passes/equiv/equiv_struct.o
OBJS += passes/equiv/equiv_purge.o
OBJS += passes/equiv/equiv_mark.o
-
+OBJS += passes/equiv/equiv_opt.o
diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc
index 66ee28aff..dbd8682e6 100644
--- a/passes/equiv/equiv_make.cc
+++ b/passes/equiv/equiv_make.cc
@@ -290,22 +290,29 @@ struct EquivMakeWorker
init_bit2driven();
- pool<Cell*> visited_cells;
+ pool<Cell*> visited_cells;
for (auto c : cells_list)
for (auto &conn : c->connections())
if (!ct.cell_output(c->type, conn.first)) {
SigSpec old_sig = assign_map(conn.second);
SigSpec new_sig = rd_signal_map(old_sig);
-
- visited_cells.clear();
- if (old_sig != new_sig) {
- if (check_signal_in_fanout(visited_cells, old_sig, new_sig))
- continue;
- log("Changing input %s of cell %s (%s): %s -> %s\n",
- log_id(conn.first), log_id(c), log_id(c->type),
- log_signal(old_sig), log_signal(new_sig));
- c->setPort(conn.first, new_sig);
+ if(old_sig != new_sig) {
+ SigSpec tmp_sig = old_sig;
+ for (int i = 0; i < GetSize(old_sig); i++) {
+ SigBit old_bit = old_sig[i], new_bit = new_sig[i];
+
+ visited_cells.clear();
+ if (check_signal_in_fanout(visited_cells, old_bit, new_bit))
+ continue;
+
+ log("Changing input %s of cell %s (%s): %s -> %s\n",
+ log_id(conn.first), log_id(c), log_id(c->type),
+ log_signal(old_bit), log_signal(new_bit));
+
+ tmp_sig[i] = new_bit;
+ }
+ c->setPort(conn.first, tmp_sig);
}
}
diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc
new file mode 100644
index 000000000..86550a69b
--- /dev/null
+++ b/passes/equiv/equiv_opt.cc
@@ -0,0 +1,157 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 whitequark <whitequark@whitequark.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/register.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct EquivOptPass:public ScriptPass
+{
+ EquivOptPass() : ScriptPass("equiv_opt", "prove equivalence for optimized circuit") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" equiv_opt [options] [command]\n");
+ log("\n");
+ log("This command checks circuit equivalence before and after an optimization pass.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\n");
+ log(" only run the commands between the labels (see below). an empty\n");
+ log(" from label is synonymous to the start of the command list, and empty to\n");
+ log(" label is synonymous to the end of the command list.\n");
+ log("\n");
+ log(" -map <filename>\n");
+ log(" expand the modules in this file before proving equivalence. this is\n");
+ log(" useful for handling architecture-specific primitives.\n");
+ log("\n");
+ log(" -assert\n");
+ log(" produce an error if the circuits are not equivalent\n");
+ log("\n");
+ log("The following commands are executed by this verification command:\n");
+ help_script();
+ log("\n");
+ }
+
+ std::string command, techmap_opts;
+ bool assert;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ command = "";
+ techmap_opts = "";
+ assert = false;
+ }
+
+ void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-run" && argidx + 1 < args.size()) {
+ size_t pos = args[argidx + 1].find(':');
+ if (pos == std::string::npos)
+ break;
+ run_from = args[++argidx].substr(0, pos);
+ run_to = args[argidx].substr(pos + 1);
+ continue;
+ }
+ if (args[argidx] == "-map" && argidx + 1 < args.size()) {
+ techmap_opts += " -map " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-assert") {
+ assert = true;
+ continue;
+ }
+ break;
+ }
+
+ for (; argidx < args.size(); argidx++) {
+ if (command.empty()) {
+ if (args[argidx].substr(0, 1) == "-")
+ cmd_error(args, argidx, "Unknown option.");
+ } else {
+ command += " ";
+ }
+ command += args[argidx];
+ }
+
+ if (command.empty())
+ log_cmd_error("No optimization pass specified!\n");
+
+ if (!design->full_selection())
+ log_cmd_error("This command only operates on fully selected designs!\n");
+
+ log_header(design, "Executing EQUIV_OPT pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("run_pass")) {
+ run("hierarchy -auto-top");
+ run("design -save preopt");
+ if (help_mode)
+ run("[command]");
+ else
+ run(command);
+ run("design -stash postopt");
+ }
+
+ if (check_label("prepare")) {
+ run("design -copy-from preopt -as gold A:top");
+ run("design -copy-from postopt -as gate A:top");
+ }
+
+ if ((!techmap_opts.empty() || help_mode) && check_label("techmap", "(only with -map)")) {
+ string opts;
+ if (help_mode)
+ opts = " -map <filename> ...";
+ else
+ opts = techmap_opts;
+ run("techmap -D EQUIV -autoproc" + opts);
+ }
+
+ if (check_label("prove")) {
+ run("equiv_make gold gate equiv");
+ run("equiv_induct equiv");
+ if (help_mode)
+ run("equiv_status [-assert] equiv");
+ else if (assert)
+ run("equiv_status -assert equiv");
+ else
+ run("equiv_status equiv");
+ }
+
+ if (check_label("restore")) {
+ run("design -load preopt");
+ }
+ }
+} EquivOptPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index 8740042c4..cf4095d06 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -472,8 +472,12 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
std::vector<SigSpec> new_wr_en(GetSize(old_wr_en));
std::vector<SigSpec> new_wr_data(GetSize(old_wr_data));
std::vector<SigSpec> new_rd_data(GetSize(old_rd_data));
+ std::vector<std::vector<State>> new_initdata;
std::vector<int> shuffle_map;
+ if (cell_init)
+ new_initdata.resize(mem_size);
+
for (auto &it : en_order)
{
auto &bits = bits_wr_en.at(it);
@@ -489,6 +493,10 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
}
for (int j = 0; j < rd_ports; j++)
new_rd_data[j].append(old_rd_data[j][bits[i]]);
+ if (cell_init) {
+ for (int j = 0; j < mem_size; j++)
+ new_initdata[j].push_back(initdata[j][bits[i]]);
+ }
shuffle_map.push_back(bits[i]);
}
@@ -499,6 +507,10 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
}
for (int j = 0; j < rd_ports; j++)
new_rd_data[j].append(State::Sx);
+ if (cell_init) {
+ for (int j = 0; j < mem_size; j++)
+ new_initdata[j].push_back(State::Sx);
+ }
shuffle_map.push_back(-1);
}
}
@@ -522,6 +534,11 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
for (int i = 0; i < rd_ports; i++)
rd_data.replace(i*mem_width, new_rd_data[i]);
+
+ if (cell_init) {
+ for (int i = 0; i < mem_size; i++)
+ initdata[i] = Const(new_initdata[i]);
+ }
}
// assign write ports
diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc
index 0d01e9d35..0f596b1f4 100644
--- a/passes/opt/Makefile.inc
+++ b/passes/opt/Makefile.inc
@@ -6,6 +6,7 @@ OBJS += passes/opt/opt_reduce.o
OBJS += passes/opt/opt_rmdff.o
OBJS += passes/opt/opt_clean.o
OBJS += passes/opt/opt_expr.o
+OBJS += passes/opt/opt_lut.o
ifneq ($(SMALL),1)
OBJS += passes/opt/share.o
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index 0ba233c62..610edc5e9 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -1406,7 +1406,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false)
{
if (sigConst.is_fully_zero()) {
- RTLIL::SigSpec a_prime(RTLIL::State::S0, 1);
+ RTLIL::SigSpec a_prime(RTLIL::State::S0, GetSize(cell->getPort("\\Y")));
if (is_lt) {
log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n",
log_id(cell->type), log_id(cell));
diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc
new file mode 100644
index 000000000..be050c713
--- /dev/null
+++ b/passes/opt/opt_lut.cc
@@ -0,0 +1,503 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 whitequark <whitequark@whitequark.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include "kernel/modtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct OptLutWorker
+{
+ dict<IdString, dict<int, IdString>> &dlogic;
+ RTLIL::Module *module;
+ ModIndex index;
+ SigMap sigmap;
+
+ pool<RTLIL::Cell*> luts;
+ dict<RTLIL::Cell*, int> luts_arity;
+ dict<RTLIL::Cell*, pool<RTLIL::Cell*>> luts_dlogics;
+ dict<RTLIL::Cell*, pool<int>> luts_dlogic_inputs;
+
+ int combined_count = 0;
+
+ bool evaluate_lut(RTLIL::Cell *lut, dict<SigBit, bool> inputs)
+ {
+ SigSpec lut_input = sigmap(lut->getPort("\\A"));
+ int lut_width = lut->getParam("\\WIDTH").as_int();
+ Const lut_table = lut->getParam("\\LUT");
+ int lut_index = 0;
+
+ for (int i = 0; i < lut_width; i++)
+ {
+ SigBit input = sigmap(lut_input[i]);
+ if (inputs.count(input))
+ {
+ lut_index |= inputs[input] << i;
+ }
+ else
+ {
+ lut_index |= SigSpec(lut_input[i]).as_bool() << i;
+ }
+ }
+
+ return lut_table.extract(lut_index).as_bool();
+ }
+
+ void show_stats_by_arity()
+ {
+ dict<int, int> arity_counts;
+ dict<IdString, int> dlogic_counts;
+ int max_arity = 0;
+
+ for (auto lut_arity : luts_arity)
+ {
+ max_arity = max(max_arity, lut_arity.second);
+ arity_counts[lut_arity.second]++;
+ }
+
+ for (auto &lut_dlogics : luts_dlogics)
+ {
+ for (auto &lut_dlogic : lut_dlogics.second)
+ {
+ dlogic_counts[lut_dlogic->type]++;
+ }
+ }
+
+ log("Number of LUTs: %8zu\n", luts.size());
+ for (int arity = 1; arity <= max_arity; arity++)
+ {
+ if (arity_counts[arity])
+ log(" %d-LUT %16d\n", arity, arity_counts[arity]);
+ }
+ for (auto &dlogic_count : dlogic_counts)
+ {
+ log(" with %-12s %4d\n", dlogic_count.first.c_str(), dlogic_count.second);
+ }
+ }
+
+ OptLutWorker(dict<IdString, dict<int, IdString>> &dlogic, RTLIL::Module *module, int limit) :
+ dlogic(dlogic), module(module), index(module), sigmap(module)
+ {
+ log("Discovering LUTs.\n");
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "$lut")
+ {
+ int lut_width = cell->getParam("\\WIDTH").as_int();
+ 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));
+ luts.insert(cell);
+
+ // First, find all dedicated logic we're connected to. This results in an overapproximation
+ // of such connections.
+ pool<RTLIL::Cell*> lut_all_dlogics;
+ for (int i = 0; i < lut_width; i++)
+ {
+ SigBit bit = lut_input[i];
+ for (auto &port : index.query_ports(bit))
+ {
+ if (dlogic.count(port.cell->type))
+ {
+ auto &dlogic_map = dlogic[port.cell->type];
+ if (dlogic_map.count(i))
+ {
+ if (port.port == dlogic_map[i])
+ {
+ lut_all_dlogics.insert(port.cell);
+ }
+ }
+ }
+ }
+ }
+
+ // Second, make sure that the connection to dedicated logic is legal. If it is not legal,
+ // it means one of the two things:
+ // * The connection is spurious. I.e. this is dedicated logic that will be packed
+ // with some other LUT, and it just happens to be conected to this LUT as well.
+ // * The connection is illegal.
+ // In either of these cases, we don't need to concern ourselves with preserving the connection
+ // between this LUT and this dedicated logic cell.
+ pool<RTLIL::Cell*> lut_legal_dlogics;
+ pool<int> lut_dlogic_inputs;
+ for (auto lut_dlogic : lut_all_dlogics)
+ {
+ auto &dlogic_map = dlogic[lut_dlogic->type];
+ bool legal = true;
+ for (auto &dlogic_conn : dlogic_map)
+ {
+ 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);
+ 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)));
+ legal = false;
+ break;
+ }
+ }
+
+ 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));
+ lut_legal_dlogics.insert(lut_dlogic);
+ for (auto &dlogic_conn : dlogic_map)
+ lut_dlogic_inputs.insert(dlogic_conn.first);
+ }
+ }
+
+ // Third, determine LUT arity. An n-wide LUT that has k constant inputs and m inputs shared with dedicated
+ // logic implements an (n-k-m)-ary function.
+ for (int i = 0; i < lut_width; i++)
+ {
+ SigBit bit = lut_input[i];
+ if (bit.wire || lut_dlogic_inputs.count(i))
+ lut_arity++;
+ }
+
+ log(" 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;
+ }
+ }
+ show_stats_by_arity();
+
+ log("\n");
+ log("Combining LUTs.\n");
+ pool<RTLIL::Cell*> worklist = luts;
+ while (worklist.size())
+ {
+ if (limit == 0)
+ {
+ log("Limit reached.\n");
+ break;
+ }
+
+ auto lutA = worklist.pop();
+ SigSpec lutA_input = sigmap(lutA->getPort("\\A"));
+ SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]);
+ int lutA_width = lutA->getParam("\\WIDTH").as_int();
+ int lutA_arity = luts_arity[lutA];
+ pool<int> &lutA_dlogic_inputs = luts_dlogic_inputs[lutA];
+
+ auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y"));
+ if (lutA_output_ports.size() != 2)
+ continue;
+
+ for (auto &port : lutA_output_ports)
+ {
+ if (port.cell == lutA)
+ continue;
+
+ if (luts.count(port.cell))
+ {
+ auto lutB = port.cell;
+ SigSpec lutB_input = sigmap(lutB->getPort("\\A"));
+ SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]);
+ int lutB_width = lutB->getParam("\\WIDTH").as_int();
+ 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));
+
+ if (index.query_is_output(lutA->getPort("\\Y")))
+ {
+ log(" Not combining LUTs (cascade connection feeds module output).\n");
+ continue;
+ }
+
+ pool<SigBit> lutA_inputs;
+ pool<SigBit> lutB_inputs;
+ for (auto &bit : lutA_input)
+ {
+ if (bit.wire)
+ lutA_inputs.insert(sigmap(bit));
+ }
+ for (auto &bit : lutB_input)
+ {
+ if (bit.wire)
+ lutB_inputs.insert(sigmap(bit));
+ }
+
+ pool<SigBit> common_inputs;
+ for (auto &bit : lutA_inputs)
+ {
+ if (lutB_inputs.count(bit))
+ common_inputs.insert(bit);
+ }
+
+ 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());
+ else
+ log(" 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());
+ 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);
+
+ 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");
+ }
+ else if (lutB_dlogic_inputs.size() > 0)
+ {
+ log(" 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");
+ }
+ else
+ {
+ combine_mask |= COMBINE_A;
+ }
+ if (lutM_arity > lutB_width)
+ {
+ log(" 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");
+ }
+ else if (lutA->get_bool_attribute("\\lut_keep"))
+ {
+ log(" 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");
+ if (lutA_arity == 1)
+ {
+ log(" 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");
+ combine = COMBINE_A;
+ }
+ else
+ {
+ log(" Arbitrarily combining into cell A.\n");
+ combine = COMBINE_A;
+ }
+ }
+
+ RTLIL::Cell *lutM, *lutR;
+ pool<SigBit> lutM_inputs, lutR_inputs;
+ pool<int> lutM_dlogic_inputs;
+ if (combine == COMBINE_A)
+ {
+ log(" Combining LUTs into cell A.\n");
+ lutM = lutA;
+ lutM_inputs = lutA_inputs;
+ lutM_dlogic_inputs = lutA_dlogic_inputs;
+ lutR = lutB;
+ lutR_inputs = lutB_inputs;
+ }
+ else if (combine == COMBINE_B)
+ {
+ log(" Combining LUTs into cell B.\n");
+ lutM = lutB;
+ lutM_inputs = lutB_inputs;
+ lutM_dlogic_inputs = lutB_dlogic_inputs;
+ lutR = lutA;
+ lutR_inputs = lutA_inputs;
+ }
+ else
+ {
+ log(" Cannot combine LUTs.\n");
+ continue;
+ }
+
+ pool<SigBit> lutR_unique;
+ for (auto &bit : lutR_inputs)
+ {
+ if (!common_inputs.count(bit) && bit != lutA_output)
+ lutR_unique.insert(bit);
+ }
+
+ int lutM_width = lutM->getParam("\\WIDTH").as_int();
+ SigSpec lutM_input = sigmap(lutM->getPort("\\A"));
+ std::vector<SigBit> lutM_new_inputs;
+ for (int i = 0; i < lutM_width; i++)
+ {
+ bool input_unused = false;
+ if (sigmap(lutM_input[i]) == lutA_output)
+ input_unused = true;
+ if (!lutM_input[i].wire && !lutM_dlogic_inputs.count(i))
+ input_unused = true;
+
+ if (input_unused && lutR_unique.size())
+ {
+ SigBit new_input = lutR_unique.pop();
+ log(" 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);
+ lutM_new_inputs.push_back(SigBit());
+ }
+ else
+ {
+ log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i]));
+ lutM_new_inputs.push_back(lutM_input[i]);
+ }
+ }
+ log_assert(lutR_unique.size() == 0);
+
+ RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width);
+ for (int eval = 0; eval < 1 << lutM_width; eval++)
+ {
+ dict<SigBit, bool> eval_inputs;
+ for (size_t i = 0; i < lutM_new_inputs.size(); i++)
+ {
+ eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1;
+ }
+ eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs);
+ 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());
+
+ lutM->setParam("\\LUT", lutM_new_table);
+ lutM->setPort("\\A", lutM_new_inputs);
+ lutM->setPort("\\Y", lutB_output);
+
+ luts_arity[lutM] = lutM_arity;
+ luts.erase(lutR);
+ luts_arity.erase(lutR);
+ lutR->module->remove(lutR);
+
+ worklist.insert(lutM);
+ worklist.erase(lutR);
+
+ combined_count++;
+ if (limit > 0)
+ limit--;
+ }
+ }
+ }
+ show_stats_by_arity();
+ }
+};
+
+static void split(std::vector<std::string> &tokens, const std::string &text, char sep)
+{
+ size_t start = 0, end = 0;
+ while ((end = text.find(sep, start)) != std::string::npos) {
+ tokens.push_back(text.substr(start, end - start));
+ start = end + 1;
+ }
+ tokens.push_back(text.substr(start));
+}
+
+struct OptLutPass : public Pass {
+ OptLutPass() : Pass("opt_lut", "optimize LUT cells") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" opt_lut [options] [selection]\n");
+ log("\n");
+ log("This pass combines cascaded $lut cells with unused inputs.\n");
+ log("\n");
+ log(" -dlogic <type>:<cell-port>=<LUT-input>[:<cell-port>=<LUT-input>...]\n");
+ log(" preserve connections to dedicated logic cell <type> that has ports\n");
+ log(" <cell-port> connected to LUT inputs <LUT-input>. this includes\n");
+ log(" the case where both LUT and dedicated logic input are connected to\n");
+ log(" the same constant.\n");
+ log("\n");
+ log(" -limit N\n");
+ log(" only perform the first N combines, then stop. useful for debugging.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n");
+
+ dict<IdString, dict<int, IdString>> dlogic;
+ int limit = -1;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-dlogic" && argidx+1 < args.size())
+ {
+ std::vector<std::string> tokens;
+ split(tokens, args[++argidx], ':');
+ if (tokens.size() < 2)
+ log_cmd_error("The -dlogic option requires at least one connection.\n");
+ IdString type = "\\" + tokens[0];
+ for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) {
+ std::vector<std::string> conn_tokens;
+ split(conn_tokens, *it, '=');
+ if (conn_tokens.size() != 2)
+ log_cmd_error("Invalid format of -dlogic signal mapping.\n");
+ IdString logic_port = "\\" + conn_tokens[0];
+ int lut_input = atoi(conn_tokens[1].c_str());
+ dlogic[type][lut_input] = logic_port;
+ }
+ continue;
+ }
+ if (args[argidx] == "-limit" && argidx + 1 < args.size())
+ {
+ limit = atoi(args[++argidx].c_str());
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ int total_count = 0;
+ for (auto module : design->selected_modules())
+ {
+ OptLutWorker worker(dlogic, module, limit - total_count);
+ total_count += worker.combined_count;
+ }
+ if (total_count)
+ design->scratchpad_set_bool("opt.did_something", true);
+ log("\n");
+ log("Combined %d LUTs.\n", total_count);
+ }
+} OptLutPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc
index 87c7ce9b2..375697dc8 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -36,6 +36,7 @@ struct OptMuxtreeWorker
RTLIL::Module *module;
SigMap assign_map;
int removed_count;
+ int glob_abort_cnt = 100000;
struct bitinfo_t {
bool seen_non_mux;
@@ -293,6 +294,9 @@ struct OptMuxtreeWorker
void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx, bool do_replace_known, bool do_enable_ports, int abort_count)
{
+ if (glob_abort_cnt == 0)
+ return;
+
muxinfo_t &muxinfo = mux2info[mux_idx];
if (do_enable_ports)
@@ -315,7 +319,7 @@ struct OptMuxtreeWorker
knowledge.visited_muxes[m] = true;
parent_muxes.push_back(m);
}
- for (int m : parent_muxes)
+ for (int m : parent_muxes) {
if (root_enable_muxes.at(m))
continue;
else if (root_muxes.at(m)) {
@@ -327,6 +331,9 @@ struct OptMuxtreeWorker
eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1);
} else
eval_mux(knowledge, m, do_replace_known, do_enable_ports, abort_count);
+ if (glob_abort_cnt == 0)
+ return;
+ }
for (int m : parent_muxes)
knowledge.visited_muxes[m] = false;
@@ -390,6 +397,12 @@ struct OptMuxtreeWorker
void eval_mux(knowledge_t &knowledge, int mux_idx, bool do_replace_known, bool do_enable_ports, int abort_count)
{
+ if (glob_abort_cnt == 0) {
+ log(" Giving up (too many iterations)\n");
+ return;
+ }
+ glob_abort_cnt--;
+
muxinfo_t &muxinfo = mux2info[mux_idx];
// set input ports to constants if we find known active or inactive signals
@@ -433,6 +446,9 @@ struct OptMuxtreeWorker
if (knowledge.known_inactive.at(portinfo.ctrl_sig))
continue;
eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports, abort_count);
+
+ if (glob_abort_cnt == 0)
+ return;
}
}
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index d2d15a4a9..d3bdd555b 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -329,6 +329,18 @@ void extract_cell(RTLIL::Cell *cell, bool keepff)
std::string remap_name(RTLIL::IdString abc_name)
{
+ std::string abc_sname = abc_name.substr(1);
+ if (abc_sname.substr(0, 5) == "ys__n") {
+ int sid = std::stoi(abc_sname.substr(5));
+ bool inv = abc_sname.back() == 'v';
+ for (auto sig : signal_list) {
+ if (sig.id == sid) {
+ std::stringstream sstr;
+ sstr << "$abc$" << map_autoidx << "$" << log_signal(sig.bit) << (inv ? "_inv" : "");
+ return sstr.str();
+ }
+ }
+ }
std::stringstream sstr;
sstr << "$abc$" << map_autoidx << "$" << abc_name.substr(1);
return sstr.str();
@@ -353,12 +365,12 @@ void dump_loop_graph(FILE *f, int &nr, std::map<int, std::set<int>> &edges, std:
}
for (auto n : nodes)
- fprintf(f, " n%d [label=\"%s\\nid=%d, count=%d\"%s];\n", n, log_signal(signal_list[n].bit),
+ fprintf(f, " ys__n%d [label=\"%s\\nid=%d, count=%d\"%s];\n", n, log_signal(signal_list[n].bit),
n, in_counts[n], workpool.count(n) ? ", shape=box" : "");
for (auto &e : edges)
for (auto n : e.second)
- fprintf(f, " n%d -> n%d;\n", e.first, n);
+ fprintf(f, " ys__n%d -> ys__n%d;\n", e.first, n);
fprintf(f, "}\n");
}
@@ -624,7 +636,7 @@ struct abc_output_filter
void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
- const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode)
+ const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, bool abc_dress)
{
module = current_module;
map_autoidx = autoidx++;
@@ -728,7 +740,8 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
-
+ if (abc_dress)
+ abc_script += "; dress";
abc_script += stringf("; write_blif %s/output.blif", tempdir_name.c_str());
abc_script = add_echos_to_abc_cmd(abc_script);
@@ -784,7 +797,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
for (auto &si : signal_list) {
if (!si.is_port || si.type != G(NONE))
continue;
- fprintf(f, " n%d", si.id);
+ fprintf(f, " ys__n%d", si.id);
pi_map[count_input++] = log_signal(si.bit);
}
if (count_input == 0)
@@ -796,17 +809,17 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
for (auto &si : signal_list) {
if (!si.is_port || si.type == G(NONE))
continue;
- fprintf(f, " n%d", si.id);
+ fprintf(f, " ys__n%d", si.id);
po_map[count_output++] = log_signal(si.bit);
}
fprintf(f, "\n");
for (auto &si : signal_list)
- fprintf(f, "# n%-5d %s\n", si.id, log_signal(si.bit));
+ fprintf(f, "# ys__n%-5d %s\n", si.id, log_signal(si.bit));
for (auto &si : signal_list) {
if (si.bit.wire == NULL) {
- fprintf(f, ".names n%d\n", si.id);
+ fprintf(f, ".names ys__n%d\n", si.id);
if (si.bit == RTLIL::State::S1)
fprintf(f, "1\n");
}
@@ -815,68 +828,68 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
int count_gates = 0;
for (auto &si : signal_list) {
if (si.type == G(BUF)) {
- fprintf(f, ".names n%d n%d\n", si.in1, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d\n", si.in1, si.id);
fprintf(f, "1 1\n");
} else if (si.type == G(NOT)) {
- fprintf(f, ".names n%d n%d\n", si.in1, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d\n", si.in1, si.id);
fprintf(f, "0 1\n");
} else if (si.type == G(AND)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "11 1\n");
} else if (si.type == G(NAND)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "0- 1\n");
fprintf(f, "-0 1\n");
} else if (si.type == G(OR)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "-1 1\n");
fprintf(f, "1- 1\n");
} else if (si.type == G(NOR)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "00 1\n");
} else if (si.type == G(XOR)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "01 1\n");
fprintf(f, "10 1\n");
} else if (si.type == G(XNOR)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "00 1\n");
fprintf(f, "11 1\n");
} else if (si.type == G(ANDNOT)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "10 1\n");
} else if (si.type == G(ORNOT)) {
- fprintf(f, ".names n%d n%d n%d\n", si.in1, si.in2, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.id);
fprintf(f, "1- 1\n");
fprintf(f, "-0 1\n");
} else if (si.type == G(MUX)) {
- fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "1-0 1\n");
fprintf(f, "-11 1\n");
} else if (si.type == G(AOI3)) {
- fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "-00 1\n");
fprintf(f, "0-0 1\n");
} else if (si.type == G(OAI3)) {
- fprintf(f, ".names n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.id);
fprintf(f, "00- 1\n");
fprintf(f, "--0 1\n");
} else if (si.type == G(AOI4)) {
- fprintf(f, ".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
fprintf(f, "-0-0 1\n");
fprintf(f, "-00- 1\n");
fprintf(f, "0--0 1\n");
fprintf(f, "0-0- 1\n");
} else if (si.type == G(OAI4)) {
- fprintf(f, ".names n%d n%d n%d n%d n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
+ fprintf(f, ".names ys__n%d ys__n%d ys__n%d ys__n%d ys__n%d\n", si.in1, si.in2, si.in3, si.in4, si.id);
fprintf(f, "00-- 1\n");
fprintf(f, "--00 1\n");
} else if (si.type == G(FF)) {
if (si.init == State::S0 || si.init == State::S1) {
- fprintf(f, ".latch n%d n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0);
+ fprintf(f, ".latch ys__n%d ys__n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0);
recover_init = true;
} else
- fprintf(f, ".latch n%d n%d 2\n", si.in1, si.id);
+ fprintf(f, ".latch ys__n%d ys__n%d 2\n", si.in1, si.id);
} else if (si.type != G(NONE))
log_abort();
if (si.type != G(NONE))
@@ -889,7 +902,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
count_gates, GetSize(signal_list), count_input, count_output);
log_push();
-
if (count_output > 0)
{
log_header(design, "Executing ABC.\n");
@@ -1213,7 +1225,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
for (auto &si : signal_list)
if (si.is_port) {
char buffer[100];
- snprintf(buffer, 100, "\\n%d", si.id);
+ snprintf(buffer, 100, "\\ys__n%d", si.id);
RTLIL::SigSig conn;
if (si.type != G(NONE)) {
conn.first = si.bit;
@@ -1407,6 +1419,11 @@ struct AbcPass : public Pass {
log(" this attribute is a unique integer for each ABC process started. This\n");
log(" is useful for debugging the partitioning of clock domains.\n");
log("\n");
+ log(" -dress\n");
+ log(" run the 'dress' command after all other ABC commands. This aims to\n");
+ log(" preserve naming by an equivalence check between the original and post-ABC\n");
+ log(" netlists (experimental).\n");
+ log("\n");
log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n");
log("loaded into ABC before the ABC script is executed.\n");
log("\n");
@@ -1441,6 +1458,7 @@ struct AbcPass : public Pass {
std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
bool show_tempdir = false, sop_mode = false;
+ bool abc_dress = false;
vector<int> lut_costs;
markgroups = false;
@@ -1555,6 +1573,10 @@ struct AbcPass : public Pass {
map_mux16 = true;
continue;
}
+ if (arg == "-dress") {
+ abc_dress = true;
+ continue;
+ }
if (arg == "-g" && argidx+1 < args.size()) {
for (auto g : split_tokens(args[++argidx], ",")) {
vector<string> gate_list;
@@ -1704,7 +1726,7 @@ struct AbcPass : public Pass {
if (!dff_mode || !clk_str.empty()) {
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
- delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode);
+ delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode, abc_dress);
continue;
}
@@ -1849,7 +1871,7 @@ struct AbcPass : public Pass {
en_polarity = std::get<2>(it.first);
en_sig = assign_map(std::get<3>(it.first));
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
- keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode);
+ keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, abc_dress);
assign_map.set(mod);
}
}
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index 9f0c7bf67..47d0ff416 100644
--- a/passes/techmap/deminout.cc
+++ b/passes/techmap/deminout.cc
@@ -83,9 +83,9 @@ struct DeminoutPass : public Pass {
for (auto bit : sigmap(conn.second))
bits_used.insert(bit);
- if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
+ if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_", "$tribuf"))
{
- bool tribuf = (cell->type == "$_TBUF_");
+ bool tribuf = (cell->type == "$_TBUF_" || cell->type == "$tribuf");
if (!tribuf) {
for (auto &c : cell->connections()) {
@@ -113,7 +113,8 @@ struct DeminoutPass : public Pass {
{
if (bits_numports[bit] > 1 || bits_inout.count(bit))
new_input = true, new_output = true;
-
+ if (bit == State::S0 || bit == State::S1)
+ new_output = true;
if (bits_written.count(bit)) {
new_output = true;
if (bits_tribuf.count(bit))
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
index 3291f5a4a..7e1040963 100644
--- a/passes/techmap/dff2dffe.cc
+++ b/passes/techmap/dff2dffe.cc
@@ -267,6 +267,10 @@ struct Dff2dffePass : public Pass {
log(" operate in the opposite direction: replace $dffe cells with combinations\n");
log(" of $dff and $mux cells. the options below are ignore in unmap mode.\n");
log("\n");
+ log(" -unmap-mince N\n");
+ log(" Same as -unmap but only unmap $dffe where the clock enable port\n");
+ log(" signal is used by less $dffe than the specified number\n");
+ log("\n");
log(" -direct <internal_gate_type> <external_gate_type>\n");
log(" map directly to external gate type. <internal_gate_type> can\n");
log(" be any internal gate-level FF cell (except $_DFFE_??_). the\n");
@@ -289,6 +293,7 @@ struct Dff2dffePass : public Pass {
log_header(design, "Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
bool unmap_mode = false;
+ int min_ce_use = -1;
dict<IdString, IdString> direct_dict;
size_t argidx;
@@ -297,6 +302,11 @@ struct Dff2dffePass : public Pass {
unmap_mode = true;
continue;
}
+ if (args[argidx] == "-unmap-mince" && argidx + 1 < args.size()) {
+ unmap_mode = true;
+ min_ce_use = std::stoi(args[++argidx]);
+ continue;
+ }
if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
string direct_from = RTLIL::escape_id(args[++argidx]);
string direct_to = RTLIL::escape_id(args[++argidx]);
@@ -343,8 +353,21 @@ struct Dff2dffePass : public Pass {
if (!mod->has_processes_warn())
{
if (unmap_mode) {
+ SigMap sigmap(mod);
for (auto cell : mod->selected_cells()) {
if (cell->type == "$dffe") {
+ if (min_ce_use >= 0) {
+ int ce_use = 0;
+ for (auto cell_other : mod->selected_cells()) {
+ if (cell_other->type != cell->type)
+ continue;
+ if (sigmap(cell->getPort("\\EN")) == sigmap(cell_other->getPort("\\EN")))
+ ce_use++;
+ }
+ if (ce_use >= min_ce_use)
+ continue;
+ }
+
RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D")));
mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool());
if (cell->getParam("\\EN_POLARITY").as_bool())
@@ -355,6 +378,18 @@ struct Dff2dffePass : public Pass {
continue;
}
if (cell->type.substr(0, 7) == "$_DFFE_") {
+ if (min_ce_use >= 0) {
+ int ce_use = 0;
+ for (auto cell_other : mod->selected_cells()) {
+ if (cell_other->type != cell->type)
+ continue;
+ if (sigmap(cell->getPort("\\E")) == sigmap(cell_other->getPort("\\E")))
+ ce_use++;
+ }
+ if (ce_use >= min_ce_use)
+ continue;
+ }
+
bool clk_pol = cell->type.substr(7, 1) == "P";
bool en_pol = cell->type.substr(8, 1) == "P";
RTLIL::SigSpec tmp = mod->addWire(NEW_ID);
diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc
index d32bbff14..a4ed79550 100644
--- a/passes/techmap/lut2mux.cc
+++ b/passes/techmap/lut2mux.cc
@@ -32,7 +32,7 @@ int lut2mux(Cell *cell)
if (GetSize(sig_a) == 1)
{
- cell->module->addMuxGate(NEW_ID, lut[0], lut[1], sig_a, sig_y);
+ cell->module->addMuxGate(NEW_ID, lut.extract(0)[0], lut.extract(1)[0], sig_a, sig_y);
}
else
{
diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc
new file mode 100644
index 000000000..750dced31
--- /dev/null
+++ b/techlibs/anlogic/Makefile.inc
@@ -0,0 +1,8 @@
+
+OBJS += techlibs/anlogic/synth_anlogic.o
+OBJS += techlibs/anlogic/anlogic_eqn.o
+
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v))
diff --git a/techlibs/anlogic/anlogic_eqn.cc b/techlibs/anlogic/anlogic_eqn.cc
new file mode 100644
index 000000000..c025c65c4
--- /dev/null
+++ b/techlibs/anlogic/anlogic_eqn.cc
@@ -0,0 +1,113 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct AnlogicEqnPass : public Pass {
+ AnlogicEqnPass() : Pass("anlogic_eqn", "Anlogic: Calculate equations for luts") { }
+ void help() YS_OVERRIDE
+ {
+ log("\n");
+ log(" anlogic_eqn [selection]\n");
+ log("\n");
+ log("Calculate equations for luts since bitstream generator depends on it.\n");
+ log("\n");
+ }
+
+ Const init2eqn(Const init, int inputs)
+ {
+ std::string init_bits = init.as_string();
+ const char* names[] = { "A" , "B", "C", "D", "E", "F" };
+
+ std::string eqn;
+ int width = (int)pow(2,inputs);
+ for(int i=0;i<width;i++)
+ {
+ if (init_bits[width-1-i]=='1')
+ {
+ eqn += "(";
+ for(int j=0;j<inputs;j++)
+ {
+ if (i & (1<<j))
+ eqn += names[j];
+ else
+ eqn += std::string("~") + names[j];
+
+ if (j!=(inputs-1)) eqn += "*";
+ }
+ eqn += ")+";
+ }
+ }
+ if (eqn.empty()) return Const("0");
+ eqn = eqn.substr(0, eqn.length()-1);
+ return Const(eqn);
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing ANLOGIC_EQN pass (calculate equations for luts).\n");
+
+ extra_args(args, args.size(), design);
+
+ size_t cnt = 0;
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\AL_MAP_LUT1")
+ {
+ cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),1));
+ cnt++;
+ }
+ if (cell->type == "\\AL_MAP_LUT2")
+ {
+ cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),2));
+ cnt++;
+ }
+ if (cell->type == "\\AL_MAP_LUT3")
+ {
+ cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),3));
+ cnt++;
+ }
+ if (cell->type == "\\AL_MAP_LUT4")
+ {
+ cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),4));
+ cnt++;
+ }
+ if (cell->type == "\\AL_MAP_LUT5")
+ {
+ cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),5));
+ cnt++;
+ }
+ if (cell->type == "\\AL_MAP_LUT6")
+ {
+ cell->setParam("\\EQN", init2eqn(cell->getParam("\\INIT"),6));
+ cnt++;
+ }
+ }
+ }
+ log_header(design, "Updated %lu of AL_MAP_LUT* elements with equation.\n", cnt);
+ }
+} AnlogicEqnPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/anlogic/arith_map.v b/techlibs/anlogic/arith_map.v
new file mode 100644
index 000000000..11cd140ec
--- /dev/null
+++ b/techlibs/anlogic/arith_map.v
@@ -0,0 +1,84 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+(* techmap_celltype = "$alu" *)
+module _80_anlogic_alu (A, B, CI, BI, X, Y, CO);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ input [A_WIDTH-1:0] A;
+ input [B_WIDTH-1:0] B;
+ output [Y_WIDTH-1:0] X, Y;
+
+ input CI, BI;
+ output CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+
+ wire [Y_WIDTH-1:0] A_buf, B_buf;
+ \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
+ \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+ wire [Y_WIDTH-1:0] AA = A_buf;
+ wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
+ wire [Y_WIDTH+1:0] COx;
+ wire [Y_WIDTH+1:0] C = {COx, CI};
+
+ wire dummy;
+ (* keep *)
+ AL_MAP_ADDER #(
+ .ALUTYPE("ADD_CARRY"))
+ adder_cin (
+ .a(C[0]),
+ .o({COx[0], dummy})
+ );
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
+ if(i==Y_WIDTH-1) begin
+ (* keep *)
+ AL_MAP_ADDER #(
+ .ALUTYPE("ADD"))
+ adder_cout (
+ .c(C[Y_WIDTH]),
+ .o(COx[Y_WIDTH])
+ );
+ assign CO = COx[Y_WIDTH];
+ end
+ else
+ begin
+ (* keep *)
+ AL_MAP_ADDER #(
+ .ALUTYPE("ADD")
+ ) adder_i (
+ .a(AA[i]),
+ .b(BB[i]),
+ .c(C[i+1]),
+ .o({COx[i+1],Y[i]})
+ );
+ end
+ end: slice
+ endgenerate
+ /* End implementation */
+ assign X = AA ^ BB;
+endmodule \ No newline at end of file
diff --git a/techlibs/anlogic/cells_map.v b/techlibs/anlogic/cells_map.v
new file mode 100644
index 000000000..36b920ef0
--- /dev/null
+++ b/techlibs/anlogic/cells_map.v
@@ -0,0 +1,49 @@
+module \$_DFF_N_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(1'b0)); endmodule
+module \$_DFF_P_ (input D, C, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(1'b0)); endmodule
+
+module \$_DFFE_NN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
+module \$_DFFE_NP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(E), .sr(1'b0)); endmodule
+module \$_DFFE_PN_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
+module \$_DFFE_PP_ (input D, C, E, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(E), .sr(1'b0)); endmodule
+
+module \$_DFF_NN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_NP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_NP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(~C), .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C) , .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("INV"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_PP0_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("RESET"), .SRMUX("SR"), .SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
+module \$_DFF_PP1_ (input D, C, R, output Q); AL_MAP_SEQ #(.DFFMODE("FF"), .REGSET("SET"), .SRMUX("SR"), . SRMODE("SYNC")) _TECHMAP_REPLACE_ (.d(D), .q(Q), .clk(C), .ce(1'b1), .sr(R)); endmodule
+
+`ifndef NO_LUT
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ AL_MAP_LUT1 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]));
+ end else
+ if (WIDTH == 2) begin
+ AL_MAP_LUT2 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]));
+ end else
+ if (WIDTH == 3) begin
+ AL_MAP_LUT3 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]));
+ end else
+ if (WIDTH == 4) begin
+ AL_MAP_LUT4 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]), .d(A[3]));
+ end else
+ if (WIDTH == 5) begin
+ AL_MAP_LUT5 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]), .d(A[3]), .e(A[4]));
+ end else
+ if (WIDTH == 6) begin
+ AL_MAP_LUT6 #(.EQN(""),.INIT(LUT)) _TECHMAP_REPLACE_ (.o(Y), .a(A[0]), .b(A[1]), .c(A[2]), .d(A[3]), .e(A[4]), .f(A[5]));
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
+`endif
diff --git a/techlibs/anlogic/cells_sim.v b/techlibs/anlogic/cells_sim.v
new file mode 100644
index 000000000..60a367928
--- /dev/null
+++ b/techlibs/anlogic/cells_sim.v
@@ -0,0 +1,103 @@
+module AL_MAP_SEQ (
+ output q,
+ input ce,
+ input clk,
+ input sr,
+ input d
+);
+ parameter DFFMODE = "FF"; //FF,LATCH
+ parameter REGSET = "RESET"; //RESET/SET
+ parameter SRMUX = "SR"; //SR/INV
+ parameter SRMODE = "SYNC"; //SYNC/ASYNC
+endmodule
+
+module AL_MAP_LUT1 (
+ output o,
+ input a
+);
+ parameter [1:0] INIT = 2'h0;
+ parameter EQN = "(A)";
+ assign Y = INIT >> A;
+endmodule
+
+module AL_MAP_LUT2 (
+ output o,
+ input a,
+ input b
+);
+ parameter [3:0] INIT = 4'h0;
+ parameter EQN = "(A)";
+ assign o = INIT >> {b, a};
+endmodule
+
+module AL_MAP_LUT3 (
+ output o,
+ input a,
+ input b,
+ input c
+);
+ parameter [7:0] INIT = 8'h0;
+ parameter EQN = "(A)";
+ assign o = INIT >> {c, b, a};
+endmodule
+
+module AL_MAP_LUT4 (
+ output o,
+ input a,
+ input b,
+ input c,
+ input d
+);
+ parameter [15:0] INIT = 16'h0;
+ parameter EQN = "(A)";
+ assign o = INIT >> {d, c, b, a};
+endmodule
+
+module AL_MAP_LUT5 (
+ output o,
+ input a,
+ input b,
+ input c,
+ input d,
+ input e
+);
+ parameter [31:0] INIT = 32'h0;
+ parameter EQN = "(A)";
+ assign o = INIT >> {e, d, c, b, a};
+endmodule
+
+
+module AL_MAP_LUT6 (
+ output o,
+ input a,
+ input b,
+ input c,
+ input d,
+ input e,
+ input f
+);
+ parameter [63:0] INIT = 64'h0;
+ parameter EQN = "(A)";
+ assign o = INIT >> {f, e, d, c, b, a};
+endmodule
+
+module AL_MAP_ALU2B (
+ input cin,
+ input a0, b0, c0, d0,
+ input a1, b1, c1, d1,
+ output s0, s1, cout
+);
+ parameter [15:0] INIT0 = 16'h0000;
+ parameter [15:0] INIT1 = 16'h0000;
+ parameter FUNC0 = "NO";
+ parameter FUNC1 = "NO";
+endmodule
+
+module AL_MAP_ADDER (
+ input a,
+ input b,
+ input c,
+ output [1:0] o
+);
+ parameter ALUTYPE = "ADD";
+endmodule
diff --git a/techlibs/anlogic/eagle_bb.v b/techlibs/anlogic/eagle_bb.v
new file mode 100644
index 000000000..48442db2f
--- /dev/null
+++ b/techlibs/anlogic/eagle_bb.v
@@ -0,0 +1,716 @@
+// Anlogic Eagle - Blackbox cells
+// FIXME: Create sim models
+
+(* blackbox *)
+module EG_PHY_BRAM(
+ output [8:0] doa,
+ output [8:0] dob,
+ input [8:0] dia,
+ input [8:0] dib,
+ input [2:0] csa,
+ input [2:0] csb,
+ input cea,
+ input ocea,
+ input clka,
+ input wea,
+ input rsta,
+ input ceb,
+ input oceb,
+ input clkb,
+ input web,
+ input rstb,
+ input [12:0] addra,
+ input [12:0] addrb
+);
+ parameter MODE = "DP8K";
+ parameter DATA_WIDTH_A = "9";
+ parameter DATA_WIDTH_B = "9";
+ parameter READBACK = "OFF";
+ parameter REGMODE_A = "NOREG";
+ parameter REGMODE_B = "NOREG";
+ parameter WRITEMODE_A = "NORMAL";
+ parameter WRITEMODE_B = "NORMAL";
+ parameter GSR = "ENABLE";
+ parameter RESETMODE = "SYNC";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+ parameter CEAMUX = "SIG";
+ parameter CEBMUX = "SIG";
+ parameter OCEAMUX = "SIG";
+ parameter OCEBMUX = "SIG";
+ parameter RSTAMUX = "SIG";
+ parameter RSTBMUX = "SIG";
+ parameter CLKAMUX = "SIG";
+ parameter CLKBMUX = "SIG";
+ parameter WEAMUX = "SIG";
+ parameter WEBMUX = "SIG";
+ parameter CSA0 = "SIG" ;
+ parameter CSA1 = "SIG" ;
+ parameter CSA2 = "SIG" ;
+ parameter CSB0 = "SIG" ;
+ parameter CSB1 = "SIG" ;
+ parameter CSB2 = "SIG" ;
+ parameter INIT_FILE = "NONE";
+ parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+endmodule
+
+(* blackbox *)
+module EG_PHY_BRAM32K(
+ output [15:0] doa,
+ output [15:0] dob,
+ input [15:0] dia,
+ input [15:0] dib,
+ input [10:0] addra,
+ input [10:0] addrb,
+ input bytea,
+ input bytewea,
+ input byteb,
+ input byteweb,
+ input csa,
+ input wea,
+ input csb,
+ input web,
+ input clka,
+ input rsta,
+ input clkb,
+ input rstb,
+ input ocea,
+ input oceb
+);
+ parameter MODE = "DP16K";
+ parameter DATA_WIDTH_A = "16";
+ parameter DATA_WIDTH_B = "16";
+ parameter REGMODE_A = "NOREG";
+ parameter REGMODE_B = "NOREG";
+ parameter WRITEMODE_A = "NORMAL";
+ parameter WRITEMODE_B = "NORMAL";
+ parameter SRMODE = "SYNC";
+ parameter CSAMUX = "SIG";
+ parameter CSBMUX = "SIG";
+ parameter OCEAMUX = "SIG";
+ parameter OCEBMUX = "SIG";
+ parameter RSTAMUX = "SIG";
+ parameter RSTBMUX = "SIG";
+ parameter CLKAMUX = "SIG";
+ parameter CLKBMUX = "SIG";
+ parameter WEAMUX = "SIG";
+ parameter WEBMUX = "SIG";
+ parameter READBACK = "OFF";
+ parameter INIT_FILE = "";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_40 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_41 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_42 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_43 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_44 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_45 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_46 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_47 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_48 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_49 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_50 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_51 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_52 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_53 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_54 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_55 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_56 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_57 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_58 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_59 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_60 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_61 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_62 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_63 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_64 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_65 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_66 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_67 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_68 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_69 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_70 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_71 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_72 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_73 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_74 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_75 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_76 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_77 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_78 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_79 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+endmodule
+
+(* blackbox *)
+module EG_PHY_FIFO(
+ input [8:0] dia,
+ input [8:0] dib,
+ input [2:0] csr,
+ input [2:0] csw,
+ input we,
+ input re,
+ input clkw,
+ input clkr,
+ input rst,
+ input rprst,
+ input orea,
+ input oreb,
+ output [8:0] dob,
+ output [8:0] doa,
+ output empty_flag,
+ output aempty_flag,
+ output afull_flag,
+ output full_flag
+);
+ parameter MODE = "FIFO8K";
+ parameter DATA_WIDTH_A = "18";
+ parameter DATA_WIDTH_B = "18";
+ parameter READBACK = "OFF";
+ parameter REGMODE_A = "NOREG";
+ parameter REGMODE_B = "NOREG";
+ parameter [13:0] AE = 14'b00000001100000;
+ parameter [13:0] AF = 14'b01111110010000;
+ parameter [13:0] F = 14'b01111111110000;
+ parameter [13:0] AEP1 = 14'b00000001110000;
+ parameter [13:0] AFM1 = 14'b01111110000000;
+ parameter [13:0] FM1 = 14'b01111111100000;
+ parameter [4:0] E = 5'b00000;
+ parameter [5:0] EP1 = 6'b010000;
+ parameter GSR = "ENABLE";
+ parameter RESETMODE = "ASYNC";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+ parameter CEA = "SIG";
+ parameter CEB = "SIG";
+ parameter OCEA = "SIG";
+ parameter OCEB = "SIG";
+ parameter RSTA = "SIG";
+ parameter RSTB = "SIG";
+ parameter CLKA = "SIG";
+ parameter CLKB = "SIG";
+ parameter WEA = "SIG";
+ parameter WEB = "SIG";
+ parameter CSA0 = "SIG";
+ parameter CSA1 = "SIG";
+ parameter CSA2 = "SIG";
+ parameter CSB0 = "SIG";
+ parameter CSB1 = "SIG";
+ parameter CSB2 = "SIG";
+endmodule
+
+(* blackbox *)
+module EG_PHY_MULT18(
+ output [17:0] acout,
+ output [17:0] bcout,
+ output [35:0] p,
+ input signeda,
+ input signedb,
+ input [17:0] a,
+ input [17:0] b,
+ input [17:0] acin,
+ input [17:0] bcin,
+ input cea,
+ input ceb,
+ input cepd,
+ input clk,
+ input rstan,
+ input rstbn,
+ input rstpdn,
+ input sourcea,
+ input sourceb
+);
+ parameter INPUTREGA = "ENABLE";
+ parameter INPUTREGB = "ENABLE";
+ parameter OUTPUTREG = "ENABLE";
+ parameter SRMODE = "ASYNC";
+ parameter MODE = "MULT18X18C";
+ parameter CEAMUX = "SIG";
+ parameter CEBMUX = "SIG";
+ parameter CEPDMUX = "SIG";
+ parameter RSTANMUX = "SIG";
+ parameter RSTBNMUX = "SIG";
+ parameter RSTPDNMUX = "SIG";
+ parameter CLKMUX = "SIG";
+ parameter SIGNEDAMUX = "SIG";
+ parameter SIGNEDBMUX = "SIG";
+ parameter SOURCEAMUX = "SIG";
+ parameter SOURCEBMUX = "SIG";
+endmodule
+
+(* blackbox *)
+module EG_PHY_GCLK(
+ input clki,
+ output clko
+);
+endmodule
+
+(* blackbox *)
+module EG_PHY_IOCLK(
+ input clki,
+ input stop,
+ output clko
+);
+ parameter STOPCLK = "DISABLE";
+endmodule
+
+(* blackbox *)
+module EG_PHY_CLKDIV(
+ output clkdiv1,
+ output clkdivx,
+ input clki,
+ input rst,
+ input rls
+);
+ parameter GSR = "DISABLE";
+ parameter DIV = 2;
+endmodule
+
+(* blackbox *)
+module EG_PHY_CONFIG(
+ output jrstn,
+ output [1:0] jrti,
+ output jshift,
+ output jtck,
+ output jtdi,
+ output jupdate,
+ output [1:0] jscanen,
+ output jtms,
+ input [1:0] jtdo,
+ input [7:0] jtag8_ipa,
+ input [7:0] jtag8_ipb,
+ output done,
+ output highz,
+ output cclk,
+ input cclk_en,
+ input gsrn_sync_clk,
+ input usr_gsrn,
+ output dna_dout,
+ input dna_clk,
+ input dna_din,
+ input dna_shift_en,
+ input mboot_rebootn,
+ input [7:0] mboot_dynamic_addr
+);
+ parameter MBOOT_AUTO_SEL = "DISABLE";
+ parameter ADDR_SOURCE_SEL = "STATIC";
+ parameter STATIC_ADDR = 8'b0;
+ parameter DONE_PERSISTN = "ENABLE";
+ parameter INIT_PERSISTN = "ENABLE";
+ parameter PROGRAMN_PERSISTN = "DISABLE";
+ parameter JTAG_PERSISTN = "DISABLE";
+ parameter GSRN_SYNC_SEL = "DISABLE";
+ parameter FREQ = "2.5";
+ parameter USR_GSRN_EN = "DISABLE";
+endmodule
+
+(* blackbox *)
+module EG_PHY_OSC(
+ input osc_dis,
+ output osc_clk
+);
+ parameter STDBY = "DISABLE";
+endmodule
+
+(* blackbox *)
+module EG_PHY_PWRMNT(
+ output pwr_dwn_n,
+ input sel_pwr,
+ input pwr_mnt_pd
+);
+ parameter MNT_LVL = 0;
+endmodule
+
+(* blackbox *)
+module EG_PHY_DDR_8M_16(
+ input clk,
+ input clk_n,
+ input ras_n,
+ input cas_n,
+ input we_n,
+ input cs_n,
+ input [11:0] addr,
+ input [1:0] ba,
+ inout [15:0] dq,
+ input ldqs,
+ input udqs,
+ input ldm,
+ input udm,
+ input cke
+);
+endmodule
+
+(* blackbox *)
+module EG_PHY_SDRAM_2M_32(
+ input clk,
+ input ras_n,
+ input cas_n,
+ input we_n,
+ input [10:0] addr,
+ input [1:0] ba,
+ inout [31:0] dq,
+ input cs_n,
+ input dm0,
+ input dm1,
+ input dm2,
+ input dm3,
+ input cke
+);
+endmodule
+
+(* blackbox *)
+module EG_PHY_PAD(
+ input ipad,
+ output opad,
+ inout bpad,
+ input rst,
+ input ce,
+ input isclk,
+ input ipclk,
+ input osclk,
+ input opclk,
+ input ts,
+ input [3:0] do,
+ output di,
+ output [3:0] diq
+);
+ parameter DEDCLK = "DISABLE";
+ parameter GSR = "ENABLE";
+ parameter SRMODE = "SYNC";
+ parameter TSMUX = "1";
+ parameter INSCLKMUX = "0";
+ parameter INPCLKMUX = "CLK";
+ parameter INCEMUX = "CE";
+ parameter INRSTMUX = "0";
+ parameter IN_REGSET = "RESET";
+ parameter IN_DFFMODE = "NONE";
+ parameter IDDRMODE = "OFF";
+ parameter IDDRPIPEMODE = "NONE";
+ parameter INDELMUX = "NODEL";
+ parameter INDEL = 0;
+ parameter OUTSCLKMUX = "0";
+ parameter OUTPCLKMUX = "CLK";
+ parameter OUTCEMUX = "CE";
+ parameter OUTRSTMUX = "0";
+ parameter DO_REGSET = "RESET";
+ parameter DO_DFFMODE = "NONE";
+ parameter ODDRMODE = "OFF";
+ parameter OUTDELMUX = "NODEL";
+ parameter OUTDEL = 0;
+ parameter TO_REGSET = "RESET";
+ parameter TO_DFFMODE = "NONE";
+ parameter MODE = "IN";
+ parameter DRIVE = "NONE";
+ parameter IOTYPE = "LVCMOS25";
+endmodule
+
+(* blackbox *)
+module EG_PHY_MSLICE(
+ input [1:0] a,
+ input [1:0] b,
+ input [1:0] c,
+ input [1:0] d,
+ input [1:0] mi,
+ input clk,
+ input ce,
+ input sr,
+ input fci,
+ output [1:0] f,
+ output [1:0] fx,
+ output [1:0] q,
+ output fco,
+ input dpram_mode,
+ input [1:0] dpram_di,
+ input dpram_we,
+ input dpram_wclk,
+ input [3:0] dpram_waddr
+);
+ parameter INIT_LUT0 = 16'h0000;
+ parameter INIT_LUT1 = 16'h0000;
+ parameter MODE = "LOGIC";
+ parameter ALUTYPE = "ADD";
+ parameter MSFXMUX = "OFF";
+ parameter GSR = "ENABLE";
+ parameter TESTMODE = "OFF";
+ parameter CEMUX = "CE";
+ parameter SRMUX = "SR";
+ parameter CLKMUX = "CLK";
+ parameter SRMODE = "ASYNC";
+ parameter DFFMODE = "FF";
+ parameter REG0_SD = "MI";
+ parameter REG1_SD = "MI";
+ parameter REG0_REGSET = "SET";
+ parameter REG1_REGSET = "SET";
+endmodule
+
+(* blackbox *)
+module EG_PHY_LSLICE(
+ input [1:0] a,
+ input [1:0] b,
+ input [1:0] c,
+ input [1:0] d,
+ input [1:0] e,
+ input [1:0] mi,
+ input clk,
+ input ce,
+ input sr,
+ input fci,
+ output [1:0] f,
+ output [1:0] fx,
+ output [1:0] q,
+ output fco,
+ output [3:0] dpram_di,
+ output [3:0] dpram_waddr,
+ output dpram_wclk,
+ output dpram_we,
+ output dpram_mode
+);
+ parameter INIT_LUTF0 = 16'h0000;
+ parameter INIT_LUTG0 = 16'h0000;
+ parameter INIT_LUTF1 = 16'h0000;
+ parameter INIT_LUTG1 = 16'h0000;
+ parameter MODE = "LOGIC";
+ parameter GSR = "ENABLE";
+ parameter TESTMODE = "OFF";
+ parameter CEMUX = "1";
+ parameter SRMUX = "SR";
+ parameter CLKMUX = "CLK";
+ parameter SRMODE = "ASYNC";
+ parameter DFFMODE = "FF";
+ parameter REG0_SD = "MI";
+ parameter REG1_SD = "MI";
+ parameter REG0_REGSET = "SET";
+ parameter REG1_REGSET = "SET";
+ parameter DEMUX0 = "D";
+ parameter DEMUX1 = "D";
+ parameter CMIMUX0 = "C";
+ parameter CMIMUX1 = "C";
+ parameter LSFMUX0 = "LUTF";
+ parameter LSFXMUX0 = "LUTG";
+ parameter LSFMUX1 = "LUTF";
+ parameter LSFXMUX1 = "LUTG";
+endmodule
+
+(* blackbox *)
+module EG_PHY_PLL(
+ output [4:0] clkc,
+ output extlock,
+ input stdby,
+ input refclk,
+ input fbclk,
+ input reset,
+ output psdone,
+ input psclk,
+ input psdown,
+ input psstep,
+ input [2:0] psclksel,
+ output [7:0] do,
+ input dclk,
+ input dcs,
+ input dwe,
+ input [7:0] di,
+ input [5:0] daddr
+);
+ parameter DYNCFG = "DISABLE";
+ parameter IF_ESCLKSTSW = "DISABLE";
+ parameter REFCLK_SEL = "INTERNAL";
+ parameter FIN = "100.0000";
+ parameter REFCLK_DIV = 1;
+ parameter FBCLK_DIV = 1;
+ parameter CLKC0_DIV = 1;
+ parameter CLKC1_DIV = 1;
+ parameter CLKC2_DIV = 1;
+ parameter CLKC3_DIV = 1;
+ parameter CLKC4_DIV = 1;
+ parameter CLKC0_ENABLE = "DISABLE";
+ parameter CLKC1_ENABLE = "DISABLE";
+ parameter CLKC2_ENABLE = "DISABLE";
+ parameter CLKC3_ENABLE = "DISABLE";
+ parameter CLKC4_ENABLE = "DISABLE";
+ parameter CLKC0_DIV2_ENABLE = "DISABLE";
+ parameter CLKC1_DIV2_ENABLE = "DISABLE";
+ parameter CLKC2_DIV2_ENABLE = "DISABLE";
+ parameter CLKC3_DIV2_ENABLE = "DISABLE";
+ parameter CLKC4_DIV2_ENABLE = "DISABLE";
+ parameter FEEDBK_MODE = "NORMAL";
+ parameter FEEDBK_PATH = "VCO_PHASE_0";
+ parameter STDBY_ENABLE = "ENABLE";
+ parameter CLKC0_FPHASE = 0;
+ parameter CLKC1_FPHASE = 0;
+ parameter CLKC2_FPHASE = 0;
+ parameter CLKC3_FPHASE = 0;
+ parameter CLKC4_FPHASE = 0;
+ parameter CLKC0_CPHASE = 1;
+ parameter CLKC1_CPHASE = 1;
+ parameter CLKC2_CPHASE = 1;
+ parameter CLKC3_CPHASE = 1;
+ parameter CLKC4_CPHASE = 1;
+ parameter GMC_GAIN = 7;
+ parameter GMC_TEST = 14;
+ parameter ICP_CURRENT = 14;
+ parameter KVCO = 7;
+ parameter LPF_CAPACITOR = 3;
+ parameter LPF_RESISTOR = 1;
+ parameter PLLRST_ENA = "ENABLE";
+ parameter PLLMRST_ENA = "DISABLE";
+ parameter PLLC2RST_ENA = "DISABLE";
+ parameter PLLC34RST_ENA = "DISABLE";
+ parameter PREDIV_MUXC0 = "VCO";
+ parameter PREDIV_MUXC1 = "VCO";
+ parameter PREDIV_MUXC2 = "VCO";
+ parameter PREDIV_MUXC3 = "VCO";
+ parameter PREDIV_MUXC4 = "VCO";
+ parameter ODIV_MUXC0 = "DIV";
+ parameter ODIV_MUXC1 = "DIV";
+ parameter ODIV_MUXC2 = "DIV";
+ parameter ODIV_MUXC3 = "DIV";
+ parameter ODIV_MUXC4 = "DIV";
+ parameter FREQ_LOCK_ACCURACY = 2;
+ parameter PLL_LOCK_MODE = 0;
+ parameter INTFB_WAKE = "DISABLE";
+ parameter DPHASE_SOURCE = "DISABLE";
+ parameter VCO_NORESET = "DISABLE";
+ parameter STDBY_VCO_ENA = "DISABLE";
+ parameter NORESET = "DISABLE";
+ parameter SYNC_ENABLE = "ENABLE";
+ parameter DERIVE_PLL_CLOCKS = "DISABLE";
+ parameter GEN_BASIC_CLOCK = "DISABLE";
+endmodule
+
+(* blackbox *)
+module EG_PHY_ADC(
+ input clk,
+ input pd,
+ input [2:0] s,
+ input soc,
+ output eoc,
+ output [11:0] dout
+);
+ parameter CH0 = "DISABLE";
+ parameter CH1 = "DISABLE";
+ parameter CH2 = "DISABLE";
+ parameter CH3 = "DISABLE";
+ parameter CH4 = "DISABLE";
+ parameter CH5 = "DISABLE";
+ parameter CH6 = "DISABLE";
+ parameter CH7 = "DISABLE";
+ parameter VREF = "DISABLE";
+endmodule
diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc
new file mode 100644
index 000000000..f4ef88770
--- /dev/null
+++ b/techlibs/anlogic/synth_anlogic.cc
@@ -0,0 +1,205 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/register.h"
+#include "kernel/celltypes.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthAnlogicPass : public ScriptPass
+{
+ SynthAnlogicPass() : ScriptPass("synth_anlogic", "synthesis for Anlogic FPGAs") { }
+
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_anlogic [options]\n");
+ log("\n");
+ log("This command runs synthesis for Anlogic FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -edif <file>\n");
+ log(" write the design to the specified EDIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\n");
+ log(" only run the commands between the labels (see below). an empty\n");
+ log(" from label is synonymous to 'begin', and empty to label is\n");
+ log(" synonymous to the end of the command list.\n");
+ log("\n");
+ log(" -noflatten\n");
+ log(" do not flatten design before synthesis\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, edif_file, json_file;
+ bool flatten, retime;
+
+ void clear_flags() YS_OVERRIDE
+ {
+ top_opt = "-auto-top";
+ edif_file = "";
+ json_file = "";
+ flatten = true;
+ retime = false;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-edif" && argidx+1 < args.size()) {
+ edif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-run" && argidx+1 < args.size()) {
+ size_t pos = args[argidx+1].find(':');
+ if (pos == std::string::npos)
+ break;
+ run_from = args[++argidx].substr(0, pos);
+ run_to = args[argidx].substr(pos+1);
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ flatten = false;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This comannd only operates on fully selected designs!\n");
+
+ log_header(design, "Executing SYNTH_ANLOGIC pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() YS_OVERRIDE
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib +/anlogic/cells_sim.v +/anlogic/eagle_bb.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (flatten && check_label("flatten", "(unless -noflatten)"))
+ {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ }
+
+ if (check_label("coarse"))
+ {
+ run("synth -run coarse");
+ }
+
+ if (check_label("fine"))
+ {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
+ run("techmap -map +/techmap.v -map +/anlogic/arith_map.v");
+ if (retime || help_mode)
+ run("abc -dff", "(only if -retime)");
+ }
+
+ if (check_label("map_ffs"))
+ {
+ run("dffsr2dff");
+ run("techmap -D NO_LUT -map +/anlogic/cells_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ }
+
+ if (check_label("map_luts"))
+ {
+ run("abc -lut 6");
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("techmap -map +/anlogic/cells_map.v");
+ run("clean");
+ run("anlogic_eqn");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("edif"))
+ {
+ if (!edif_file.empty() || help_mode)
+ run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file.c_str()));
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode)
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+ }
+} SynthAnlogicPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc
index ab961ac0b..70074f653 100644
--- a/techlibs/common/Makefile.inc
+++ b/techlibs/common/Makefile.inc
@@ -25,5 +25,6 @@ $(eval $(call add_share_file,share,techlibs/common/techmap.v))
$(eval $(call add_share_file,share,techlibs/common/pmux2mux.v))
$(eval $(call add_share_file,share,techlibs/common/adff2dff.v))
$(eval $(call add_share_file,share,techlibs/common/dff2ff.v))
+$(eval $(call add_share_file,share,techlibs/common/gate2lut.v))
$(eval $(call add_share_file,share,techlibs/common/cells.lib))
diff --git a/techlibs/common/gate2lut.v b/techlibs/common/gate2lut.v
new file mode 100644
index 000000000..99c123f4a
--- /dev/null
+++ b/techlibs/common/gate2lut.v
@@ -0,0 +1,87 @@
+(* techmap_celltype = "$_NOT_" *)
+module _90_lut_not (A, Y);
+ input A;
+ output Y;
+
+ wire [`LUT_WIDTH-1:0] AA;
+ assign AA = {A};
+
+ \$lut #(
+ .WIDTH(`LUT_WIDTH),
+ .LUT(4'b01)
+ ) lut (
+ .A(AA),
+ .Y(Y)
+ );
+endmodule
+
+(* techmap_celltype = "$_OR_" *)
+module _90_lut_or (A, B, Y);
+ input A, B;
+ output Y;
+
+ wire [`LUT_WIDTH-1:0] AA;
+ assign AA = {B, A};
+
+ \$lut #(
+ .WIDTH(`LUT_WIDTH),
+ .LUT(4'b1110)
+ ) lut (
+ .A(AA),
+ .Y(Y)
+ );
+endmodule
+
+(* techmap_celltype = "$_AND_" *)
+module _90_lut_and (A, B, Y);
+ input A, B;
+ output Y;
+
+ wire [`LUT_WIDTH-1:0] AA;
+ assign AA = {B, A};
+
+ \$lut #(
+ .WIDTH(`LUT_WIDTH),
+ .LUT(4'b1000)
+ ) lut (
+ .A(AA),
+ .Y(Y)
+ );
+endmodule
+
+(* techmap_celltype = "$_XOR_" *)
+module _90_lut_xor (A, B, Y);
+ input A, B;
+ output Y;
+
+ wire [`LUT_WIDTH-1:0] AA;
+ assign AA = {B, A};
+
+ \$lut #(
+ .WIDTH(`LUT_WIDTH),
+ .LUT(4'b0110)
+ ) lut (
+ .A(AA),
+ .Y(Y)
+ );
+endmodule
+
+(* techmap_celltype = "$_MUX_" *)
+module _90_lut_mux (A, B, S, Y);
+ input A, B, S;
+ output Y;
+
+ wire [`LUT_WIDTH-1:0] AA;
+ assign AA = {S, B, A};
+
+ \$lut #(
+ .WIDTH(`LUT_WIDTH),
+ // A 1010 1010
+ // B 1100 1100
+ // S 1111 0000
+ .LUT(8'b_1100_1010)
+ ) lut (
+ .A(AA),
+ .Y(Y)
+ );
+endmodule
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index 937512e7c..289673e82 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -465,7 +465,7 @@ endmodule
//-
//- $_SR_NP_ (S, R, Q)
//-
-//- A set-reset latch with negative polarity SET and positive polarioty RESET.
+//- A set-reset latch with negative polarity SET and positive polarity RESET.
//-
//- Truth table: S R | Q
//- -----+---
@@ -489,7 +489,7 @@ endmodule
//-
//- $_SR_PN_ (S, R, Q)
//-
-//- A set-reset latch with positive polarity SET and negative polarioty RESET.
+//- A set-reset latch with positive polarity SET and negative polarity RESET.
//-
//- Truth table: S R | Q
//- -----+---
diff --git a/techlibs/gowin/Makefile.inc b/techlibs/gowin/Makefile.inc
index 679d7eff5..2f82def7d 100644
--- a/techlibs/gowin/Makefile.inc
+++ b/techlibs/gowin/Makefile.inc
@@ -3,4 +3,5 @@ OBJS += techlibs/gowin/synth_gowin.o
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v))
+$(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v))
diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v
new file mode 100644
index 000000000..25e789e4a
--- /dev/null
+++ b/techlibs/gowin/arith_map.v
@@ -0,0 +1,59 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+(* techmap_celltype = "$alu" *)
+module _80_gw1n_alu(A, B, CI, BI, X, Y, CO);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ input [A_WIDTH-1:0] A;
+ input [B_WIDTH-1:0] B;
+ output [Y_WIDTH-1:0] X, Y;
+
+ input CI, BI;
+ output [Y_WIDTH-1:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+
+ wire [Y_WIDTH-1:0] A_buf, B_buf;
+ \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
+ \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+ wire [Y_WIDTH-1:0] AA = A_buf;
+ wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
+ wire [Y_WIDTH-1:0] C = {CO, CI};
+
+ genvar i;
+ generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
+ ALU #(.ALU_MODE(32'b0))
+ alu(.I0(AA[i]),
+ .I1(BB[i]),
+ .I3(1'b0),
+ .CIN(C[i]),
+ .COUT(CO[i]),
+ .SUM(Y[i])
+ );
+ end endgenerate
+ assign X = AA ^ BB;
+endmodule
+
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 947942626..14441c2fc 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -57,3 +57,9 @@ endmodule
module GSR (input GSRI);
wire GSRO = GSRI;
endmodule
+
+module ALU (input I0, input I1, input I3, input CIN, output COUT, output SUM);
+ parameter [3:0] ALU_MODE = 0; // default 0 = ADD
+ assign {COUT, SUM} = CIN + I1 + I0;
+endmodule // alu
+
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 793f345be..e3d924e26 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -49,6 +49,9 @@ struct SynthGowinPass : public ScriptPass
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
+ log(" -nobram\n");
+ log(" do not use BRAM cells in output netlist\n");
+ log("\n");
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
@@ -59,13 +62,14 @@ struct SynthGowinPass : public ScriptPass
}
string top_opt, vout_file;
- bool retime;
+ bool retime, nobram;
void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
vout_file = "";
retime = false;
+ nobram = true;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@@ -96,6 +100,10 @@ struct SynthGowinPass : public ScriptPass
retime = true;
continue;
}
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -119,7 +127,7 @@ struct SynthGowinPass : public ScriptPass
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
- if (check_label("flatten"))
+ if (check_label("flatten") && check_label("flatten", "(unless -noflatten)"))
{
run("proc");
run("flatten");
@@ -131,13 +139,18 @@ struct SynthGowinPass : public ScriptPass
{
run("synth -run coarse");
}
-
+ if (!nobram && check_label("bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/gowin/bram.txt");
+ run("techmap -map +/gowin/brams_map.v");
+ }
if (check_label("fine"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
- run("techmap");
+ run("techmap -map +/techmap.v -map +/gowin/arith_map.v");
+ run("opt -fine");
run("clean -purge");
run("splitnets -ports");
run("setundef -undriven -zero");
diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc
index 14761c6c8..2750901c8 100644
--- a/techlibs/ice40/Makefile.inc
+++ b/techlibs/ice40/Makefile.inc
@@ -3,6 +3,7 @@ OBJS += techlibs/ice40/synth_ice40.o
OBJS += techlibs/ice40/ice40_ffssr.o
OBJS += techlibs/ice40/ice40_ffinit.o
OBJS += techlibs/ice40/ice40_opt.o
+OBJS += techlibs/ice40/ice40_unlut.o
GENFILES += techlibs/ice40/brams_init1.vh
GENFILES += techlibs/ice40/brams_init2.vh
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index e0a07af32..38ed45981 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -409,6 +409,7 @@ module SB_RAM40_4K (
initial begin
for (i=0; i<16; i=i+1) begin
+`ifdef YOSYS
memory[ 0*16 + i] <= INIT_0[16*i +: 16];
memory[ 1*16 + i] <= INIT_1[16*i +: 16];
memory[ 2*16 + i] <= INIT_2[16*i +: 16];
@@ -425,6 +426,24 @@ module SB_RAM40_4K (
memory[13*16 + i] <= INIT_D[16*i +: 16];
memory[14*16 + i] <= INIT_E[16*i +: 16];
memory[15*16 + i] <= INIT_F[16*i +: 16];
+`else
+ memory[ 0*16 + i] = INIT_0[16*i +: 16];
+ memory[ 1*16 + i] = INIT_1[16*i +: 16];
+ memory[ 2*16 + i] = INIT_2[16*i +: 16];
+ memory[ 3*16 + i] = INIT_3[16*i +: 16];
+ memory[ 4*16 + i] = INIT_4[16*i +: 16];
+ memory[ 5*16 + i] = INIT_5[16*i +: 16];
+ memory[ 6*16 + i] = INIT_6[16*i +: 16];
+ memory[ 7*16 + i] = INIT_7[16*i +: 16];
+ memory[ 8*16 + i] = INIT_8[16*i +: 16];
+ memory[ 9*16 + i] = INIT_9[16*i +: 16];
+ memory[10*16 + i] = INIT_A[16*i +: 16];
+ memory[11*16 + i] = INIT_B[16*i +: 16];
+ memory[12*16 + i] = INIT_C[16*i +: 16];
+ memory[13*16 + i] = INIT_D[16*i +: 16];
+ memory[14*16 + i] = INIT_E[16*i +: 16];
+ memory[15*16 + i] = INIT_F[16*i +: 16];
+`endif
end
end
@@ -928,6 +947,7 @@ module SB_SPRAM256KA (
output reg [15:0] DATAOUT
);
`ifndef BLACKBOX
+`ifndef EQUIV
reg [15:0] mem [0:16383];
wire off = SLEEP || !POWEROFF;
integer i;
@@ -954,6 +974,7 @@ module SB_SPRAM256KA (
end
end
`endif
+`endif
endmodule
(* blackbox *)
diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc
index 668df09dd..a7649d7a0 100644
--- a/techlibs/ice40/ice40_ffssr.cc
+++ b/techlibs/ice40/ice40_ffssr.cc
@@ -81,6 +81,9 @@ struct Ice40FfssrPass : public Pass {
for (auto cell : ff_cells)
{
+ if (cell->get_bool_attribute("\\dont_touch"))
+ continue;
+
SigSpec sig_d = cell->getPort("\\D");
if (GetSize(sig_d) < 1)
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index 162740059..f528607d6 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -33,7 +33,7 @@ static SigBit get_bit_or_zero(const SigSpec &sig)
return sig[0];
}
-static void run_ice40_opts(Module *module, bool unlut_mode)
+static void run_ice40_opts(Module *module)
{
pool<SigBit> optimized_co;
vector<Cell*> sb_lut_cells;
@@ -95,9 +95,6 @@ static void run_ice40_opts(Module *module, bool unlut_mode)
inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
sigmap.apply(inbits);
- if (unlut_mode)
- goto remap_lut;
-
if (optimized_co.count(inbits[0])) goto remap_lut;
if (optimized_co.count(inbits[1])) goto remap_lut;
if (optimized_co.count(inbits[2])) goto remap_lut;
@@ -152,14 +149,10 @@ struct Ice40OptPass : public Pass {
log(" opt_clean\n");
log(" while <changed design>\n");
log("\n");
- log("When called with the option -unlut, this command will transform all already\n");
- log("mapped SB_LUT4 cells back to logic.\n");
- log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string opt_expr_args = "-mux_undef -undriven";
- bool unlut_mode = false;
log_header(design, "Executing ICE40_OPT pass (performing simple optimizations).\n");
log_push();
@@ -170,10 +163,6 @@ struct Ice40OptPass : public Pass {
opt_expr_args += " -full";
continue;
}
- if (args[argidx] == "-unlut") {
- unlut_mode = true;
- continue;
- }
break;
}
extra_args(args, argidx, design);
@@ -184,7 +173,7 @@ struct Ice40OptPass : public Pass {
log_header(design, "Running ICE40 specific optimizations.\n");
for (auto module : design->selected_modules())
- run_ice40_opts(module, unlut_mode);
+ run_ice40_opts(module);
Pass::call(design, "opt_expr " + opt_expr_args);
Pass::call(design, "opt_merge");
diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc
new file mode 100644
index 000000000..2428a8e78
--- /dev/null
+++ b/techlibs/ice40/ice40_unlut.cc
@@ -0,0 +1,106 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+static SigBit get_bit_or_zero(const SigSpec &sig)
+{
+ if (GetSize(sig) == 0)
+ return State::S0;
+ return sig[0];
+}
+
+static void run_ice40_unlut(Module *module)
+{
+ SigMap sigmap(module);
+
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type == "\\SB_LUT4")
+ {
+ SigSpec inbits;
+
+ inbits.append(get_bit_or_zero(cell->getPort("\\I0")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I1")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I2")));
+ inbits.append(get_bit_or_zero(cell->getPort("\\I3")));
+ sigmap.apply(inbits);
+
+ log("Mapping SB_LUT4 cell %s.%s to $lut.\n", log_id(module), log_id(cell));
+
+ cell->type ="$lut";
+ cell->setParam("\\WIDTH", 4);
+ cell->setParam("\\LUT", cell->getParam("\\LUT_INIT"));
+ cell->unsetParam("\\LUT_INIT");
+
+ cell->setPort("\\A", SigSpec({
+ get_bit_or_zero(cell->getPort("\\I3")),
+ get_bit_or_zero(cell->getPort("\\I2")),
+ get_bit_or_zero(cell->getPort("\\I1")),
+ get_bit_or_zero(cell->getPort("\\I0"))
+ }));
+ cell->setPort("\\Y", cell->getPort("\\O")[0]);
+ cell->unsetPort("\\I0");
+ cell->unsetPort("\\I1");
+ cell->unsetPort("\\I2");
+ cell->unsetPort("\\I3");
+ cell->unsetPort("\\O");
+
+ cell->check();
+ }
+ }
+}
+
+struct Ice40UnlutPass : public Pass {
+ Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: perform simple optimizations") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" ice40_unlut [options] [selection]\n");
+ log("\n");
+ log("This command transforms all SB_LUT4 cells to generic $lut cells.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing ICE40_UNLUT pass (convert SB_LUT4 to $lut).\n");
+ log_push();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ // if (args[argidx] == "-???") {
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ run_ice40_unlut(module);
+ }
+} Ice40UnlutPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index b0687e5e3..37b924dfd 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -63,15 +63,25 @@ struct SynthIce40Pass : public ScriptPass
log(" -retime\n");
log(" run 'abc' with -dff option\n");
log("\n");
+ log(" -relut\n");
+ log(" combine LUTs after synthesis\n");
+ log("\n");
log(" -nocarry\n");
log(" do not use SB_CARRY cells in output netlist\n");
log("\n");
log(" -nodffe\n");
log(" do not use SB_DFFE* cells in output netlist\n");
log("\n");
+ log(" -dffe_min_ce_use <min_ce_use>\n");
+ log(" do not use SB_DFFE* cells if the resulting CE line would go to less\n");
+ log(" than min_ce_use SB_DFFE*in output netlist\n");
+ log("\n");
log(" -nobram\n");
log(" do not use SB_RAM40_4K* cells in output netlist\n");
log("\n");
+ log(" -noabc\n");
+ log(" use built-in Yosys LUT techmapping instead of abc\n");
+ log("\n");
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
log("\n");
@@ -86,7 +96,8 @@ struct SynthIce40Pass : public ScriptPass
}
string top_opt, blif_file, edif_file, json_file;
- bool nocarry, nodffe, nobram, flatten, retime, abc2, vpr;
+ bool nocarry, nodffe, nobram, flatten, retime, relut, noabc, abc2, vpr;
+ int min_ce_use;
void clear_flags() YS_OVERRIDE
{
@@ -96,9 +107,12 @@ struct SynthIce40Pass : public ScriptPass
json_file = "";
nocarry = false;
nodffe = false;
+ min_ce_use = -1;
nobram = false;
flatten = true;
retime = false;
+ relut = false;
+ noabc = false;
abc2 = false;
vpr = false;
}
@@ -147,6 +161,10 @@ struct SynthIce40Pass : public ScriptPass
retime = true;
continue;
}
+ if (args[argidx] == "-relut") {
+ relut = true;
+ continue;
+ }
if (args[argidx] == "-nocarry") {
nocarry = true;
continue;
@@ -155,10 +173,18 @@ struct SynthIce40Pass : public ScriptPass
nodffe = true;
continue;
}
+ if (args[argidx] == "-dffe_min_ce_use" && argidx+1 < args.size()) {
+ min_ce_use = std::stoi(args[++argidx]);
+ continue;
+ }
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
+ if (args[argidx] == "-noabc") {
+ noabc = true;
+ continue;
+ }
if (args[argidx] == "-abc2") {
abc2 = true;
continue;
@@ -214,6 +240,10 @@ struct SynthIce40Pass : public ScriptPass
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
+ }
+
+ if (check_label("map_gates"))
+ {
if (nocarry)
run("techmap");
else
@@ -228,6 +258,10 @@ struct SynthIce40Pass : public ScriptPass
run("dffsr2dff");
if (!nodffe)
run("dff2dffe -direct-match $_DFF_*");
+ if (min_ce_use >= 0) {
+ run("opt_merge");
+ run(stringf("dff2dffe -unmap-mince %d", min_ce_use));
+ }
run("techmap -D NO_LUT -map +/ice40/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
@@ -243,8 +277,18 @@ struct SynthIce40Pass : public ScriptPass
run("ice40_opt", "(only if -abc2)");
}
run("techmap -map +/ice40/latches_map.v");
- run("abc -lut 4");
+ if (noabc || help_mode) {
+ run("simplemap", " (only if -noabc)");
+ run("techmap -map +/gate2lut.v -D LUT_WIDTH=4", "(only if -noabc)");
+ }
+ if (!noabc) {
+ run("abc -lut 4", "(skip if -noabc)");
+ }
run("clean");
+ if (relut || help_mode) {
+ run("ice40_unlut", " (only if -relut)");
+ run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3", "(only if -relut)");
+ }
}
if (check_label("map_cells"))
diff --git a/techlibs/intel/common/brams_map.v b/techlibs/intel/common/brams_map.v
index fae4af2ab..d0f07c1de 100644
--- a/techlibs/intel/common/brams_map.v
+++ b/techlibs/intel/common/brams_map.v
@@ -2,8 +2,8 @@ module \$__M9K_ALTSYNCRAM_SINGLEPORT_FULL (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1A
parameter CFG_ABITS = 8;
parameter CFG_DBITS = 36;
- parameter ABITS = "1";
- parameter DBITS = "1";
+ parameter ABITS = 1;
+ parameter DBITS = 1;
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
@@ -63,21 +63,21 @@ module \$__M9K_ALTSYNCRAM_SINGLEPORT_FULL (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1A
.width_byteena_a (1), // Forced value
.numwords_b ( NUMWORDS ),
.numwords_a ( NUMWORDS ),
- .widthad_b ( CFG_ABITS ),
- .width_b ( CFG_DBITS ),
- .widthad_a ( CFG_ABITS ),
- .width_a ( CFG_DBITS )
+ .widthad_b ( CFG_DBITS ),
+ .width_b ( CFG_ABITS ),
+ .widthad_a ( CFG_DBITS ),
+ .width_a ( CFG_ABITS )
) _TECHMAP_REPLACE_ (
.data_a(B1DATA),
.address_a(B1ADDR),
.wren_a(B1EN),
.rden_a(A1EN),
.q_a(A1DATA),
- .data_b(1'b0),
+ .data_b(B1DATA),
.address_b(0),
.wren_b(1'b0),
.rden_b(1'b0),
- .q_b(1'b0),
+ .q_b(),
.clock0(CLK2),
.clock1(1'b1), // Unused in single port mode
.clocken0(1'b1),
diff --git a/tests/lut/.gitignore b/tests/lut/.gitignore
new file mode 100644
index 000000000..397b4a762
--- /dev/null
+++ b/tests/lut/.gitignore
@@ -0,0 +1 @@
+*.log
diff --git a/tests/lut/check_map.ys b/tests/lut/check_map.ys
new file mode 100644
index 000000000..dc0aaffc2
--- /dev/null
+++ b/tests/lut/check_map.ys
@@ -0,0 +1,4 @@
+simplemap
+equiv_opt -assert techmap -map +/gate2lut.v -D LUT_WIDTH=4
+design -load postopt
+select -assert-count 1 t:$lut
diff --git a/tests/lut/map_and.v b/tests/lut/map_and.v
new file mode 100644
index 000000000..68ae33fd6
--- /dev/null
+++ b/tests/lut/map_and.v
@@ -0,0 +1,5 @@
+module top(...);
+ input a, b;
+ output y;
+ assign y = a&b;
+endmodule
diff --git a/tests/lut/map_mux.v b/tests/lut/map_mux.v
new file mode 100644
index 000000000..ccecf3023
--- /dev/null
+++ b/tests/lut/map_mux.v
@@ -0,0 +1,5 @@
+module top(...);
+ input a, b, s;
+ output y;
+ assign y = s?a:b;
+endmodule
diff --git a/tests/lut/map_not.v b/tests/lut/map_not.v
new file mode 100644
index 000000000..385997414
--- /dev/null
+++ b/tests/lut/map_not.v
@@ -0,0 +1,5 @@
+module top(...);
+ input a;
+ output y;
+ assign y = ~a;
+endmodule
diff --git a/tests/lut/map_or.v b/tests/lut/map_or.v
new file mode 100644
index 000000000..8b8c55188
--- /dev/null
+++ b/tests/lut/map_or.v
@@ -0,0 +1,5 @@
+module top(...);
+ input a, b;
+ output y;
+ assign y = a|b;
+endmodule
diff --git a/tests/lut/map_xor.v b/tests/lut/map_xor.v
new file mode 100644
index 000000000..708a05789
--- /dev/null
+++ b/tests/lut/map_xor.v
@@ -0,0 +1,5 @@
+module top(...);
+ input a, b;
+ output y;
+ assign y = a^b;
+endmodule
diff --git a/tests/lut/run-test.sh b/tests/lut/run-test.sh
new file mode 100644
index 000000000..207417fa6
--- /dev/null
+++ b/tests/lut/run-test.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+for x in *.v; do
+ echo "Running $x.."
+ ../../yosys -q -s check_map.ys -l ${x%.v}.log $x
+done
diff --git a/tests/opt/.gitignore b/tests/opt/.gitignore
new file mode 100644
index 000000000..397b4a762
--- /dev/null
+++ b/tests/opt/.gitignore
@@ -0,0 +1 @@
+*.log
diff --git a/tests/opt/opt_lut.v b/tests/opt/opt_lut.v
new file mode 100644
index 000000000..b13db367d
--- /dev/null
+++ b/tests/opt/opt_lut.v
@@ -0,0 +1,18 @@
+module top(
+ input [8:0] a,
+ input [8:0] b,
+ output [8:0] o1,
+ output [2:0] o2,
+ input [2:0] c,
+ input [2:0] d,
+ output [2:0] o3,
+ output [2:0] o4,
+ input s
+);
+
+assign o1 = (s ? 0 : a + b);
+assign o2 = (s ? a : a - b);
+assign o3 = (s ? 4'b1111 : d + c);
+assign o4 = (s ? d : c - d);
+
+endmodule
diff --git a/tests/opt/opt_lut.ys b/tests/opt/opt_lut.ys
new file mode 100644
index 000000000..59b12c351
--- /dev/null
+++ b/tests/opt/opt_lut.ys
@@ -0,0 +1,4 @@
+read_verilog opt_lut.v
+synth_ice40
+ice40_unlut
+equiv_opt -map +/ice40/cells_sim.v -assert opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3
diff --git a/tests/opt/opt_lut_port.il b/tests/opt/opt_lut_port.il
new file mode 100644
index 000000000..7eb71890f
--- /dev/null
+++ b/tests/opt/opt_lut_port.il
@@ -0,0 +1,18 @@
+module $1
+ wire width 4 input 2 \_0_
+ wire output 4 \_1_
+ wire input 3 \_2_
+ wire output 1 \o
+ cell $lut \_3_
+ parameter \LUT 16'0011000000000011
+ parameter \WIDTH 4
+ connect \A { \_0_ [3] \o 2'00 }
+ connect \Y \_1_
+ end
+ cell $lut \_4_
+ parameter \LUT 4'0001
+ parameter \WIDTH 4
+ connect \A { 3'000 \_2_ }
+ connect \Y \o
+ end
+end
diff --git a/tests/opt/opt_lut_port.ys b/tests/opt/opt_lut_port.ys
new file mode 100644
index 000000000..51dfd988b
--- /dev/null
+++ b/tests/opt/opt_lut_port.ys
@@ -0,0 +1,2 @@
+read_ilang opt_lut_port.il
+select -assert-count 2 t:$lut
diff --git a/tests/opt/run-test.sh b/tests/opt/run-test.sh
new file mode 100755
index 000000000..44ce7e674
--- /dev/null
+++ b/tests/opt/run-test.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+for x in *.ys; do
+ echo "Running $x.."
+ ../../yosys -ql ${x%.ys}.log $x
+done
diff --git a/tests/svinterfaces/.gitignore b/tests/svinterfaces/.gitignore
new file mode 100644
index 000000000..a5b7927d1
--- /dev/null
+++ b/tests/svinterfaces/.gitignore
@@ -0,0 +1,8 @@
+/a.out
+/dut_result.txt
+/reference_result.txt
+/*.diff
+/*.log_stderr
+/*.log_stdout
+/*_ref_syn.v
+/*_syn.v