aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG21
-rw-r--r--Makefile14
-rw-r--r--README.md12
-rw-r--r--backends/btor/btor.cc1
-rw-r--r--backends/cxxrtl/cxxrtl.h21
-rw-r--r--backends/cxxrtl/cxxrtl_backend.cc2
-rw-r--r--backends/smt2/smt2.cc1
-rw-r--r--frontends/verific/verific.cc33
-rw-r--r--kernel/rtlil.h2
-rw-r--r--manual/command-reference-manual.tex79
-rw-r--r--passes/hierarchy/hierarchy.cc23
-rw-r--r--passes/memory/memory_map.cc20
-rw-r--r--passes/opt/opt_dff.cc22
-rw-r--r--passes/sat/async2sync.cc3
-rw-r--r--passes/techmap/abc.cc6
-rw-r--r--passes/techmap/abc9_exe.cc6
-rw-r--r--techlibs/gatemate/.gitignore4
-rw-r--r--techlibs/gatemate/Makefile.inc16
-rw-r--r--techlibs/gatemate/cells_sim.v44
-rw-r--r--techlibs/gatemate/gatemate_foldinv.cc219
-rw-r--r--techlibs/gatemate/inv_map.v4
-rw-r--r--techlibs/gatemate/make_lut_tree_lib.py323
-rw-r--r--techlibs/gatemate/synth_gatemate.cc32
-rw-r--r--techlibs/gowin/synth_gowin.cc1
-rw-r--r--tests/arch/gatemate/gen_luttrees.py48
-rw-r--r--tests/arch/gatemate/luttrees.v752
-rw-r--r--tests/arch/gatemate/luttrees.ys13
27 files changed, 1635 insertions, 87 deletions
diff --git a/CHANGELOG b/CHANGELOG
index e32d9d053..54c385cd8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,9 +2,28 @@
List of major changes and improvements between releases
=======================================================
-Yosys 0.18 .. Yosys 0.18-dev
+Yosys 0.19 .. Yosys 0.19-dev
--------------------------
+Yosys 0.18 .. Yosys 0.19
+--------------------------
+ * New commands and options
+ - Added option "-rom-only" to "memory_libmap" pass
+ - Added option "-smtcheck" to "hierarchy" pass
+ - Added option "-keepdc" to "memory_libmap" pass
+ - Added option "-suffix" to "rename" pass
+ - Added "gatemate_foldinv" pass
+
+ * Formal Verification
+ - Added support for $pos cell in btor backend
+ - Added the "smtlib2_module" and "smtlib2_comb_expr" attributes
+
+ * GateMate support
+ - Added LUT tree mapping
+
+ * Verific support
+ - Added option "-pp" to "verific -import"
+
Yosys 0.17 .. Yosys 0.18
--------------------------
* Various
diff --git a/Makefile b/Makefile
index 3c659b9aa..e32434141 100644
--- a/Makefile
+++ b/Makefile
@@ -129,7 +129,7 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.18+29
+YOSYS_VER := 0.19+14
# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
@@ -145,7 +145,7 @@ endif
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
- sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 19ce3b4.. | wc -l`/;" Makefile
+ sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline a45c131.. | wc -l`/;" Makefile
# set 'ABCREV = default' to use abc/ as it is
#
@@ -153,10 +153,10 @@ bumpversion:
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
-ABCREV = 09a7e6d
+ABCREV = 5f40c47
ABCPULL = 1
ABCURL ?= https://github.com/YosysHQ/abc
-ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 VERBOSE=$(Q)
+ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
# set ABCEXTERNAL = <abc-command> to use an external ABC instance
# Note: The in-tree ABC (yosys-abc) will not be installed when ABCEXTERNAL is set.
@@ -201,7 +201,7 @@ ifeq ($(CONFIG),clang)
CXX = clang
LD = clang++
CXXFLAGS += -std=$(CXXSTD) -Os
-ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -Wno-c++11-narrowing"
ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
@@ -260,7 +260,7 @@ else ifeq ($(CONFIG),emcc)
CXX = emcc
LD = emcc
CXXFLAGS := -std=$(CXXSTD) $(filter-out -fPIC -ggdb,$(CXXFLAGS))
-ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8"
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8 -Wno-c++11-narrowing"
EMCC_CXXFLAGS := -Os -Wno-warn-absolute-paths
EMCC_LDFLAGS := --memory-init-file 0 --embed-file share
EMCC_LDFLAGS += -s NO_EXIT_RUNTIME=1
@@ -314,7 +314,7 @@ CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) -Os $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LDFLAGS))
LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)"
-ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING"
+ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING -Wno-c++11-narrowing"
ABCMKARGS += OPTFLAGS="-Os"
EXE = .wasm
diff --git a/README.md b/README.md
index 0232a5ed0..f916b38ad 100644
--- a/README.md
+++ b/README.md
@@ -505,6 +505,18 @@ Verilog Attributes and non-standard features
module. Modules with such cells will be reprocessed during the ``hierarchy``
pass once the referenced module definition(s) become available.
+- The ``smtlib2_module`` attribute can be set on a blackbox module to specify a
+ formal model directly using SMT-LIB 2. For such a module, the
+ ``smtlib2_comb_expr`` attribute can be used on output ports to define their
+ value using an SMT-LIB 2 expression. For example:
+
+ (* blackbox *)
+ (* smtlib2_module *)
+ module submod(a, b);
+ input [7:0] a;
+ (* smtlib2_comb_expr = "(bvnot a)" *)
+ output [7:0] b;
+ endmodule
Non-standard or SystemVerilog features for formal verification
==============================================================
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index 7dec70545..831a3ada2 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -1405,7 +1405,6 @@ struct BtorBackend : public Backend {
log_header(design, "Executing BTOR backend.\n");
log_push();
- Pass::call(design, "memory_map -rom-only");
Pass::call(design, "bmuxmap");
Pass::call(design, "demuxmap");
log_pop();
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index b4ffa87cd..073921cc4 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -1575,6 +1575,27 @@ value<BitsY> mod_ss(const value<BitsA> &a, const value<BitsB> &b) {
return divmod_ss<BitsY>(a, b).second;
}
+template<size_t BitsY, size_t BitsA, size_t BitsB>
+CXXRTL_ALWAYS_INLINE
+value<BitsY> modfloor_uu(const value<BitsA> &a, const value<BitsB> &b) {
+ return divmod_uu<BitsY>(a, b).second;
+}
+
+// GHDL Modfloor operator. Returns r=a mod b, such that r has the same sign as b and
+// a=b*N+r where N is some integer
+// In practical terms, when a and b have different signs and the remainder returned by divmod_ss is not 0
+// then return the remainder + b
+template<size_t BitsY, size_t BitsA, size_t BitsB>
+CXXRTL_ALWAYS_INLINE
+value<BitsY> modfloor_ss(const value<BitsA> &a, const value<BitsB> &b) {
+ value<BitsY> r;
+ r = divmod_ss<BitsY>(a, b).second;
+ if((b.is_neg() != a.is_neg()) && !r.is_zero())
+ return add_ss<BitsY>(b, r);
+ return r;
+}
+
+
// Memory helper
struct memory_index {
bool valid;
diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc
index 404755b1e..62768bd33 100644
--- a/backends/cxxrtl/cxxrtl_backend.cc
+++ b/backends/cxxrtl/cxxrtl_backend.cc
@@ -185,7 +185,7 @@ bool is_binary_cell(RTLIL::IdString type)
ID($and), ID($or), ID($xor), ID($xnor), ID($logic_and), ID($logic_or),
ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx),
ID($eq), ID($ne), ID($eqx), ID($nex), ID($gt), ID($ge), ID($lt), ID($le),
- ID($add), ID($sub), ID($mul), ID($div), ID($mod));
+ ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($modfloor));
}
bool is_extending_cell(RTLIL::IdString type)
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index 6e70f9043..7481e0510 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -1609,7 +1609,6 @@ struct Smt2Backend : public Backend {
log_header(design, "Executing SMT2 backend.\n");
log_push();
- Pass::call(design, "memory_map -rom-only");
Pass::call(design, "bmuxmap");
Pass::call(design, "demuxmap");
log_pop();
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index bbf860c96..fd6208e86 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -57,7 +57,7 @@ USING_YOSYS_NAMESPACE
#include "FileSystem.h"
#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
-#include "InitialAssertions.h"
+#include "VerificExtensions.h"
#endif
#ifndef YOSYSHQ_VERIFIC_API_VERSION
@@ -2246,7 +2246,7 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
verific_params.Insert(i.first.c_str(), i.second.c_str());
#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
- InitialAssertions::Rewrite("work", &verific_params);
+ VerificExtensions::ElaborateAndRewrite("work", &verific_params);
#endif
if (top.empty()) {
@@ -2312,6 +2312,9 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
nl_todo.erase(it);
}
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+ VerificExtensions::Reset();
+#endif
hier_tree::DeleteHierarchicalTree();
veri_file::Reset();
#ifdef VERIFIC_VHDL_SUPPORT
@@ -2494,6 +2497,9 @@ struct VerificPass : public Pass {
log(" -v, -vv\n");
log(" Verbose log messages. (-vv is even more verbose than -v.)\n");
log("\n");
+ log(" -pp <filename>\n");
+ log(" Pretty print design after elaboration to specified file.\n");
+ log("\n");
log("The following additional import options are useful for debugging the Verific\n");
log("bindings (for Yosys and/or Verific developers):\n");
log("\n");
@@ -2539,6 +2545,9 @@ struct VerificPass : public Pass {
log("Get/set Verific runtime flags.\n");
log("\n");
log("\n");
+#if defined(YOSYS_ENABLE_VERIFIC) and defined(YOSYSHQ_VERIFIC_EXTENSIONS)
+ VerificExtensions::Help();
+#endif
log("Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n");
log("https://www.yosyshq.com/\n");
log("\n");
@@ -2922,6 +2931,7 @@ struct VerificPass : public Pass {
bool mode_autocover = false, mode_fullinit = false;
bool flatten = false, extnets = false;
string dumpfile;
+ string ppfile;
Map parameters(STRING_HASH);
for (argidx++; argidx < GetSize(args); argidx++) {
@@ -2990,6 +3000,10 @@ struct VerificPass : public Pass {
dumpfile = args[++argidx];
continue;
}
+ if (args[argidx] == "-pp" && argidx+1 < GetSize(args)) {
+ ppfile = args[++argidx];
+ continue;
+ }
break;
}
@@ -2999,8 +3013,11 @@ struct VerificPass : public Pass {
std::set<std::string> top_mod_names;
#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
- InitialAssertions::Rewrite(work, &parameters);
+ VerificExtensions::ElaborateAndRewrite(work, &parameters);
#endif
+ if (!ppfile.empty())
+ veri_file::PrettyPrint(ppfile.c_str(), nullptr, work.c_str());
+
if (mode_all)
{
log("Running hier_tree::ElaborateAll().\n");
@@ -3113,6 +3130,9 @@ struct VerificPass : public Pass {
nl_todo.erase(it);
}
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+ VerificExtensions::Reset();
+#endif
hier_tree::DeleteHierarchicalTree();
veri_file::Reset();
#ifdef VERIFIC_VHDL_SUPPORT
@@ -3187,6 +3207,13 @@ struct VerificPass : public Pass {
}
}
}
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+ if (VerificExtensions::Execute(args, argidx, work,
+ [this](const std::vector<std::string> &args, size_t argidx, std::string msg)
+ { cmd_error(args, argidx, msg); } )) {
+ goto check_error;
+ }
+#endif
cmd_error(args, argidx, "Missing or unsupported mode parameter.\n");
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 7a0b6b9c7..ee918441e 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -168,7 +168,7 @@ namespace RTLIL
log_assert(p[1] != 0);
for (const char *c = p; *c; c++)
if ((unsigned)*c <= (unsigned)' ')
- log_error("Found control character or space (0x%02hhx) in string '%s' which is not allowed in RTLIL identifiers\n", *c, p);
+ log_error("Found control character or space (0x%02x) in string '%s' which is not allowed in RTLIL identifiers\n", *c, p);
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) {
diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex
index edc8af6e6..28b99f3a6 100644
--- a/manual/command-reference-manual.tex
+++ b/manual/command-reference-manual.tex
@@ -2256,6 +2256,16 @@ and simulus signal from FST file
number of clock cycles to simulate (default: 20)
\end{lstlisting}
+\section{gatemate\_foldinv -- fold inverters into Gatemate LUT trees}
+\label{cmd:gatemate_foldinv}
+\begin{lstlisting}[numbers=left,frame=single]
+ gatemate_foldinv [selection]
+
+
+This pass searches for $__CC_NOT cells and folds them into CC_LUT2, CC_L2T4
+and CC_L2T5 cells as created by LUT tree mapping.
+\end{lstlisting}
+
\section{glift -- create GLIFT models and optimization problems}
\label{cmd:glift}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2379,6 +2389,9 @@ resolves positional module parameters, unrolls array instances, and more.
like -check, but also throw an error if blackbox modules are
instantiated, and throw an error if the design has no top module.
+ -smtcheck
+ like -simcheck, but allow smtlib2_module modules.
+
-purge_lib
by default the hierarchy command will not remove library (blackbox)
modules. use this option to also remove unused blackbox modules.
@@ -2947,6 +2960,12 @@ pass to word-wide DFFs and address decoders.
-iattr
for -attr, ignore case of <value>.
+
+ -rom-only
+ only perform conversion for ROMs (memories with no write ports).
+
+ -keepdc
+ when mapping ROMs, keep x-bits shared across read ports.
\end{lstlisting}
\section{memory\_memx -- emulate vlog sim behavior for mem ports}
@@ -4223,10 +4242,12 @@ Assign names auto-generated from the src attribute to all selected wires and
cells with private names.
- rename -wire [selection]
+ rename -wire [selection] [-suffix <suffix>]
Assign auto-generated names based on the wires they drive to all selected
cells with private names. Ignores cells driving privatly named wires.
+By default, the cell is named after the wire with the cell type as suffix.
+The -suffix option can be used to set the suffix to the given string instead.
rename -enumerate [-pattern <pattern>] [selection]
@@ -5985,6 +6006,9 @@ This command runs synthesis for Cologne Chip AG GateMate FPGAs.
-nomx8, -nomx4
do not use CC_MX{8,4} multiplexer cells in output netlist.
+ -luttree
+ use new LUT tree mapping approach (EXPERIMENTAL).
+
-dff
run 'abc' with -dff option
@@ -6064,7 +6088,11 @@ The following commands are executed by this synthesis command:
techmap -map +/gatemate/mux_map.v
map_luts:
- abc -dress -lut 4
+ abc -genlib +/gatemate/lut_tree_cells.genlib (with -luttree)
+ techmap -map +/gatemate/lut_tree_map.v (with -luttree)
+ gatemate_foldinv (with -luttree)
+ techmap -map +/gatemate/inv_map.v (with -luttree)
+ abc -dress -lut 4 (without -luttree)
clean
map_cells:
@@ -7898,6 +7926,9 @@ Import options:
-v, -vv
Verbose log messages. (-vv is even more verbose than -v.)
+ -pp <filename>
+ Pretty print design after elaboration to specified file.
+
The following additional import options are useful for debugging the Verific
bindings (for Yosys and/or Verific developers):
@@ -7938,50 +7969,6 @@ Pretty print options:
Save output for VHDL design units.
- verific -app <application>..
-
-Execute YosysHQ formal application on loaded Verilog files.
-
-Application options:
-
- -module <module>
- Run formal application only on specified module.
-
- -blacklist <filename[:lineno]>
- Do not run application on modules from files that match the filename
- or filename and line number if provided in such format.
- Parameter can also contain comma separated list of file locations.
-
- -blfile <file>
- Do not run application on locations specified in file, they can
- represent filename or filename and location in file.
-
-Applications:
-
- WARNING: Applications only available in commercial build.
-
-
- verific -template <name> <top_module>..
-
-Generate template for specified top module of loaded design.
-
-Template options:
-
- -out
- Specifies output file for generated template, by default output is stdout
-
- -chparam name value
- Generate template using this parameter value. Otherwise default parameter
- values will be used for templat generate functionality. This option
- can be specified multiple times to override multiple parameters.
- String values must be passed in double quotes (").
-
-Templates:
-
- WARNING: Templates only available in commercial build.
-
-
-
verific -cfg [<name> [<value>]]
Get/set Verific runtime flags.
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index d40d6e59f..d27fddf1c 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -439,7 +439,8 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI
}
}
-bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, std::vector<std::string> &libdirs)
+bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, bool flag_smtcheck,
+ std::vector<std::string> &libdirs)
{
bool did_something = false;
std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
@@ -477,7 +478,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
RTLIL::Module *mod = design->module(cell->type);
if (!mod)
{
- mod = get_module(*design, *cell, *module, flag_check || flag_simcheck, libdirs);
+ mod = get_module(*design, *cell, *module, flag_check || flag_simcheck || flag_smtcheck, libdirs);
// If we still don't have a module, treat the cell as a black box and skip
// it. Otherwise, we either loaded or derived something so should set the
@@ -495,11 +496,11 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
// interfaces.
if_expander.visit_connections(*cell, *mod);
- if (flag_check || flag_simcheck)
+ if (flag_check || flag_simcheck || flag_smtcheck)
check_cell_connections(*module, *cell, *mod);
if (mod->get_blackbox_attribute()) {
- if (flag_simcheck)
+ if (flag_simcheck || (flag_smtcheck && !mod->get_bool_attribute(ID::smtlib2_module)))
log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n",
cell->type.c_str(), module->name.c_str(), cell->name.c_str());
continue;
@@ -737,6 +738,9 @@ struct HierarchyPass : public Pass {
log(" like -check, but also throw an error if blackbox modules are\n");
log(" instantiated, and throw an error if the design has no top module.\n");
log("\n");
+ log(" -smtcheck\n");
+ log(" like -simcheck, but allow smtlib2_module modules.\n");
+ log("\n");
log(" -purge_lib\n");
log(" by default the hierarchy command will not remove library (blackbox)\n");
log(" modules. use this option to also remove unused blackbox modules.\n");
@@ -803,6 +807,7 @@ struct HierarchyPass : public Pass {
bool flag_check = false;
bool flag_simcheck = false;
+ bool flag_smtcheck = false;
bool purge_lib = false;
RTLIL::Module *top_mod = NULL;
std::string load_top_mod;
@@ -821,7 +826,7 @@ struct HierarchyPass : public Pass {
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
- if (args[argidx] == "-generate" && !flag_check && !flag_simcheck && !top_mod) {
+ if (args[argidx] == "-generate" && !flag_check && !flag_simcheck && !flag_smtcheck && !top_mod) {
generate_mode = true;
log("Entering generate mode.\n");
while (++argidx < args.size()) {
@@ -868,6 +873,10 @@ struct HierarchyPass : public Pass {
flag_simcheck = true;
continue;
}
+ if (args[argidx] == "-smtcheck") {
+ flag_smtcheck = true;
+ continue;
+ }
if (args[argidx] == "-purge_lib") {
purge_lib = true;
continue;
@@ -1013,7 +1022,7 @@ struct HierarchyPass : public Pass {
}
}
- if (flag_simcheck && top_mod == nullptr)
+ if ((flag_simcheck || flag_smtcheck) && top_mod == nullptr)
log_error("Design has no top module.\n");
if (top_mod != NULL) {
@@ -1039,7 +1048,7 @@ struct HierarchyPass : public Pass {
}
for (auto module : used_modules) {
- if (expand_module(design, module, flag_check, flag_simcheck, libdirs))
+ if (expand_module(design, module, flag_check, flag_simcheck, flag_smtcheck, libdirs))
did_something = true;
}
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index ccfb8c94f..fd5b1f1ad 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -31,6 +31,7 @@ struct MemoryMapWorker
{
bool attr_icase = false;
bool rom_only = false;
+ bool keepdc = false;
dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
RTLIL::Design *design;
@@ -190,14 +191,15 @@ struct MemoryMapWorker
{
int addr = i + mem.start_offset;
int idx = addr & ((1 << abits) - 1);
+ SigSpec w_init = init_data.extract(i*mem.width, mem.width);
if (static_cells_map.count(addr) > 0)
{
data_reg_out[idx] = static_cells_map[addr];
count_static++;
}
- else if (mem.wr_ports.empty())
+ else if (mem.wr_ports.empty() && (!keepdc || w_init.is_fully_def()))
{
- data_reg_out[idx] = init_data.extract(i*mem.width, mem.width);
+ data_reg_out[idx] = w_init;
}
else
{
@@ -220,13 +222,15 @@ struct MemoryMapWorker
w_out_name = genid(mem.memid, "", addr, "$q");
RTLIL::Wire *w_out = module->addWire(w_out_name, mem.width);
- SigSpec w_init = init_data.extract(i*mem.width, mem.width);
if (!w_init.is_fully_undef())
w_out->attributes[ID::init] = w_init.as_const();
data_reg_out[idx] = w_out;
c->setPort(ID::Q, w_out);
+
+ if (mem.wr_ports.empty())
+ module->connect(RTLIL::SigSig(w_in, w_out));
}
}
@@ -380,11 +384,15 @@ struct MemoryMapPass : public Pass {
log(" -rom-only\n");
log(" only perform conversion for ROMs (memories with no write ports).\n");
log("\n");
+ log(" -keepdc\n");
+ log(" when mapping ROMs, keep x-bits shared across read ports.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
bool attr_icase = false;
bool rom_only = false;
+ bool keepdc = false;
dict<RTLIL::IdString, std::vector<RTLIL::Const>> attributes;
log_header(design, "Executing MEMORY_MAP pass (converting memories to logic and flip-flops).\n");
@@ -426,6 +434,11 @@ struct MemoryMapPass : public Pass {
rom_only = true;
continue;
}
+ if (args[argidx] == "-keepdc")
+ {
+ keepdc = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -435,6 +448,7 @@ struct MemoryMapPass : public Pass {
worker.attr_icase = attr_icase;
worker.attributes = attributes;
worker.rom_only = rom_only;
+ worker.keepdc = keepdc;
worker.run();
}
}
diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc
index 0ad4acec2..6ff2d1b4b 100644
--- a/passes/opt/opt_dff.cc
+++ b/passes/opt/opt_dff.cc
@@ -491,12 +491,17 @@ struct OptDffWorker
ff.has_srst = false;
ff.sig_d = ff.val_srst;
changed = true;
- } else {
+ } else if (!opt.keepdc || ff.val_init.is_fully_def()) {
log("Handling never-active EN on %s (%s) from module %s (removing D path).\n",
log_id(cell), log_id(cell->type), log_id(module));
// The D input path is effectively useless, so remove it (this will be a D latch, SR latch, or a const driver).
ff.has_ce = ff.has_clk = ff.has_srst = false;
changed = true;
+ } else {
+ // We need to keep the undefined initival around as such
+ ff.sig_d = ff.sig_q;
+ ff.has_ce = ff.has_srst = false;
+ changed = true;
}
} else if (ff.sig_ce == (ff.pol_ce ? State::S1 : State::S0)) {
// Always-active enable. Just remove it.
@@ -508,13 +513,20 @@ struct OptDffWorker
}
}
- if (ff.has_clk) {
- if (ff.sig_clk.is_fully_const()) {
+ if (ff.has_clk && ff.sig_clk.is_fully_const()) {
+ if (!opt.keepdc || ff.val_init.is_fully_def()) {
// Const clock — the D input path is effectively useless, so remove it (this will be a D latch, SR latch, or a const driver).
log("Handling const CLK on %s (%s) from module %s (removing D path).\n",
log_id(cell), log_id(cell->type), log_id(module));
ff.has_ce = ff.has_clk = ff.has_srst = false;
changed = true;
+ } else {
+ // Const clock, but we need to keep the undefined initval around as such
+ if (ff.has_ce || ff.has_srst || ff.sig_d != ff.sig_q) {
+ ff.sig_d = ff.sig_q;
+ ff.has_ce = ff.has_srst = false;
+ changed = true;
+ }
}
}
@@ -550,7 +562,7 @@ struct OptDffWorker
ff.has_srst = false;
ff.sig_d = ff.val_srst;
changed = true;
- } else {
+ } else if (!opt.keepdc || ff.val_init.is_fully_def()) {
// The D input path is effectively useless, so remove it (this will be a const-input D latch, SR latch, or a const driver).
log("Handling D = Q on %s (%s) from module %s (removing D path).\n",
log_id(cell), log_id(cell->type), log_id(module));
@@ -567,7 +579,7 @@ struct OptDffWorker
}
// The cell has been simplified as much as possible already. Now try to spice it up with enables / sync resets.
- if (ff.has_clk) {
+ if (ff.has_clk && ff.sig_d != ff.sig_q) {
if (!ff.has_arst && !ff.has_sr && (!ff.has_srst || !ff.has_ce || ff.ce_over_srst) && !opt.nosdff) {
// Try to merge sync resets.
std::map<ctrls_t, std::vector<int>> groups;
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc
index 46c76eba9..6fdf470b1 100644
--- a/passes/sat/async2sync.cc
+++ b/passes/sat/async2sync.cc
@@ -75,6 +75,9 @@ struct Async2syncPass : public Pass {
if (ff.has_gclk)
continue;
+ if (ff.has_clk && ff.sig_clk.is_fully_const())
+ ff.has_ce = ff.has_clk = ff.has_srst = false;
+
if (ff.has_clk)
{
if (ff.has_sr) {
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 61ee99ee7..0b9c327c0 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -65,7 +65,9 @@
#include "frontends/blif/blifparse.h"
#ifdef YOSYS_LINK_ABC
-extern "C" int Abc_RealMain(int argc, char *argv[]);
+namespace abc {
+ int Abc_RealMain(int argc, char *argv[]);
+}
#endif
USING_YOSYS_NAMESPACE
@@ -1098,7 +1100,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
abc_argv[2] = strdup("-f");
abc_argv[3] = strdup(tmp_script_name.c_str());
abc_argv[4] = 0;
- int ret = Abc_RealMain(4, abc_argv);
+ int ret = abc::Abc_RealMain(4, abc_argv);
free(abc_argv[0]);
free(abc_argv[1]);
free(abc_argv[2]);
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index a66e95e21..7dc0a364b 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -31,7 +31,9 @@
#endif
#ifdef YOSYS_LINK_ABC
-extern "C" int Abc_RealMain(int argc, char *argv[]);
+namespace abc {
+ int Abc_RealMain(int argc, char *argv[]);
+}
#endif
std::string fold_abc9_cmd(std::string str)
@@ -277,7 +279,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
abc9_argv[2] = strdup("-f");
abc9_argv[3] = strdup(tmp_script_name.c_str());
abc9_argv[4] = 0;
- int ret = Abc_RealMain(4, abc9_argv);
+ int ret = abc::Abc_RealMain(4, abc9_argv);
free(abc9_argv[0]);
free(abc9_argv[1]);
free(abc9_argv[2]);
diff --git a/techlibs/gatemate/.gitignore b/techlibs/gatemate/.gitignore
new file mode 100644
index 000000000..f260d6e9d
--- /dev/null
+++ b/techlibs/gatemate/.gitignore
@@ -0,0 +1,4 @@
+lut_tree_cells.genlib
+lut_tree_map.v
+lut_tree_lib.mk
+
diff --git a/techlibs/gatemate/Makefile.inc b/techlibs/gatemate/Makefile.inc
index d1341d7bb..aeb318cc9 100644
--- a/techlibs/gatemate/Makefile.inc
+++ b/techlibs/gatemate/Makefile.inc
@@ -1,5 +1,6 @@
OBJS += techlibs/gatemate/synth_gatemate.o
+OBJS += techlibs/gatemate/gatemate_foldinv.o
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/reg_map.v))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mux_map.v))
@@ -12,3 +13,18 @@ $(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_map.v))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams.txt))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_20.vh))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_40.vh))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/inv_map.v))
+
+EXTRA_OBJS += techlibs/gatemate/lut_tree_lib.mk
+.SECONDARY: techlibs/gatemate/lut_tree_lib.mk
+
+techlibs/gatemate/lut_tree_lib.mk: techlibs/gatemate/make_lut_tree_lib.py
+ $(Q) mkdir -p techlibs/gatemate
+ $(P) $(PYTHON_EXECUTABLE) $<
+ $(Q) touch $@
+
+techlibs/gatemate/lut_tree_cells.genlib: techlibs/gatemate/lut_tree_lib.mk
+techlibs/gatemate/lut_tree_map.v: techlibs/gatemate/lut_tree_lib.mk
+
+$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_cells.genlib))
+$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_map.v))
diff --git a/techlibs/gatemate/cells_sim.v b/techlibs/gatemate/cells_sim.v
index 1de3d1c7a..7e88fd7cf 100644
--- a/techlibs/gatemate/cells_sim.v
+++ b/techlibs/gatemate/cells_sim.v
@@ -1409,3 +1409,47 @@ module CC_BRAM_40K (
end
endgenerate
endmodule
+
+// Models of the LUT2 tree primitives
+module CC_L2T4(
+ output O,
+ input I0, I1, I2, I3
+);
+ parameter [3:0] INIT_L00 = 4'b0000;
+ parameter [3:0] INIT_L01 = 4'b0000;
+ parameter [3:0] INIT_L10 = 4'b0000;
+
+ wire [1:0] l00_s1 = I1 ? INIT_L00[3:2] : INIT_L00[1:0];
+ wire l00 = I0 ? l00_s1[1] : l00_s1[0];
+
+ wire [1:0] l01_s1 = I3 ? INIT_L01[3:2] : INIT_L01[1:0];
+ wire l01 = I2 ? l01_s1[1] : l01_s1[0];
+
+ wire [1:0] l10_s1 = l01 ? INIT_L10[3:2] : INIT_L10[1:0];
+ assign O = l00 ? l10_s1[1] : l10_s1[0];
+
+endmodule
+
+
+module CC_L2T5(
+ output O,
+ input I0, I1, I2, I3, I4
+);
+ parameter [3:0] INIT_L02 = 4'b0000;
+ parameter [3:0] INIT_L03 = 4'b0000;
+ parameter [3:0] INIT_L11 = 4'b0000;
+ parameter [3:0] INIT_L20 = 4'b0000;
+
+ wire [1:0] l02_s1 = I1 ? INIT_L02[3:2] : INIT_L02[1:0];
+ wire l02 = I0 ? l02_s1[1] : l02_s1[0];
+
+ wire [1:0] l03_s1 = I3 ? INIT_L03[3:2] : INIT_L03[1:0];
+ wire l03 = I2 ? l03_s1[1] : l03_s1[0];
+
+ wire [1:0] l11_s1 = l03 ? INIT_L11[3:2] : INIT_L11[1:0];
+ wire l11 = l02 ? l11_s1[1] : l11_s1[0];
+
+ wire [1:0] l20_s1 = l11 ? INIT_L20[3:2] : INIT_L20[1:0];
+ assign O = I4 ? l20_s1[1] : l20_s1[0];
+
+endmodule
diff --git a/techlibs/gatemate/gatemate_foldinv.cc b/techlibs/gatemate/gatemate_foldinv.cc
new file mode 100644
index 000000000..752f8aac0
--- /dev/null
+++ b/techlibs/gatemate/gatemate_foldinv.cc
@@ -0,0 +1,219 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 gatecat <gatecat@ds0.me>
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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 LUTPin {
+ int input_bit;
+ IdString init_param;
+};
+
+struct LUTType {
+ dict<IdString, LUTPin> inputs;
+ IdString output_param;
+};
+
+struct FoldInvWorker {
+ FoldInvWorker(Module *module) : module(module), sigmap(module) {};
+ Module *module;
+ SigMap sigmap;
+
+ // Mapping from inverter output to inverter input
+ dict<SigBit, SigBit> inverted_bits;
+ // Mapping from inverter input to inverter
+ dict<SigBit, Cell*> inverter_input;
+
+ const dict<IdString, LUTType> lut_types = {
+ {ID(CC_LUT2), {{
+ {ID(I0), {0, ID(INIT)}},
+ {ID(I1), {1, ID(INIT)}},
+ }, ID(INIT)}},
+ {ID(CC_L2T4), {{
+ {ID(I0), {0, ID(INIT_L00)}},
+ {ID(I1), {1, ID(INIT_L00)}},
+ {ID(I2), {0, ID(INIT_L01)}},
+ {ID(I3), {1, ID(INIT_L01)}},
+ }, ID(INIT_L10)}},
+ {ID(CC_L2T5), {{
+ {ID(I0), {0, ID(INIT_L02)}},
+ {ID(I1), {1, ID(INIT_L02)}},
+ {ID(I2), {0, ID(INIT_L03)}},
+ {ID(I3), {1, ID(INIT_L03)}},
+ {ID(I4), {0, ID(INIT_L20)}},
+ }, ID(INIT_L20)}},
+ };
+
+
+ void find_inverted_bits()
+ {
+ for (auto cell : module->selected_cells()) {
+ if (cell->type != ID($__CC_NOT))
+ continue;
+ SigBit a = sigmap(cell->getPort(ID::A)[0]);
+ SigBit y = sigmap(cell->getPort(ID::Y)[0]);
+ inverted_bits[y] = a;
+ inverter_input[a] = cell;
+ }
+ }
+
+ Const invert_lut_input(Const lut, int bit)
+ {
+ Const result(State::S0, GetSize(lut));
+ for (int i = 0; i < GetSize(lut); i++) {
+ int j = i ^ (1 << bit);
+ result[j] = lut[i];
+ }
+ return result;
+ }
+
+ Const invert_lut_output(Const lut)
+ {
+ Const result(State::S0, GetSize(lut));
+ for (int i = 0; i < GetSize(lut); i++)
+ result[i] = (lut[i] == State::S1) ? State::S0 : State::S1;
+ return result;
+ }
+
+ void fold_input_inverters()
+ {
+ for (auto cell : module->selected_cells()) {
+ auto found_type = lut_types.find(cell->type);
+ if (found_type == lut_types.end())
+ continue;
+ const auto &type = found_type->second;
+ for (const auto &ipin : type.inputs) {
+ if (!cell->hasPort(ipin.first))
+ continue;
+ auto sig = cell->getPort(ipin.first);
+ if (GetSize(sig) == 0)
+ continue;
+ SigBit bit = sigmap(sig[0]);
+ auto inv = inverted_bits.find(bit);
+ if (inv == inverted_bits.end())
+ continue; // not the output of an inverter
+ // Rewire to inverter input
+ cell->unsetPort(ipin.first);
+ cell->setPort(ipin.first, inv->second);
+ // Rewrite init
+ cell->setParam(ipin.second.init_param,
+ invert_lut_input(cell->getParam(ipin.second.init_param), ipin.second.input_bit));
+ }
+ }
+ }
+
+ void fold_output_inverters()
+ {
+ pool<SigBit> used_bits;
+ // Find bits that are actually used
+ for (auto cell : module->selected_cells()) {
+ for (auto conn : cell->connections()) {
+ if (cell->output(conn.first))
+ continue;
+ for (auto bit : sigmap(conn.second))
+ used_bits.insert(bit);
+ }
+ }
+ // Find LUTs driving inverters
+ // (create a vector to avoid iterate-and-modify issues)
+ std::vector<std::pair<Cell *, Cell*>> lut_inv;
+ for (auto cell : module->selected_cells()) {
+ auto found_type = lut_types.find(cell->type);
+ if (found_type == lut_types.end())
+ continue;
+ if (!cell->hasPort(ID::O))
+ continue;
+ auto o_sig = cell->getPort(ID::O);
+ if (GetSize(o_sig) == 0)
+ continue;
+ SigBit o = sigmap(o_sig[0]);
+ auto found_inv = inverter_input.find(o);
+ if (found_inv == inverter_input.end())
+ continue; // doesn't drive an inverter
+ lut_inv.emplace_back(cell, found_inv->second);
+ }
+ for (auto pair : lut_inv) {
+ Cell *orig_lut = pair.first;
+ Cell *inv = pair.second;
+ // Find the inverter output
+ SigBit inv_y = sigmap(inv->getPort(ID::Y)[0]);
+ // Inverter output might not actually be used; if all users were folded into inputs already
+ if (!used_bits.count(inv_y))
+ continue;
+ // Create a duplicate of the LUT with an inverted output
+ // (if the uninverted version becomes unused it will be swept away)
+ Cell *dup_lut = module->addCell(NEW_ID, orig_lut->type);
+ inv->unsetPort(ID::Y);
+ dup_lut->setPort(ID::O, inv_y);
+ for (auto conn : orig_lut->connections()) {
+ if (conn.first == ID::O)
+ continue;
+ dup_lut->setPort(conn.first, conn.second);
+ }
+ for (auto param : orig_lut->parameters) {
+ if (param.first == lut_types.at(orig_lut->type).output_param)
+ dup_lut->parameters[param.first] = invert_lut_output(param.second);
+ else
+ dup_lut->parameters[param.first] = param.second;
+ }
+ }
+ }
+
+ void operator()()
+ {
+ find_inverted_bits();
+ fold_input_inverters();
+ fold_output_inverters();
+ }
+};
+
+struct GatemateFoldInvPass : public Pass {
+ GatemateFoldInvPass() : Pass("gatemate_foldinv", "fold inverters into Gatemate LUT trees") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" gatemate_foldinv [selection]\n");
+ log("\n");
+ log("\n");
+ log("This pass searches for $__CC_NOT cells and folds them into CC_LUT2, CC_L2T4\n");
+ log("and CC_L2T5 cells as created by LUT tree mapping.\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing GATEMATE_FOLDINV pass (folding LUT tree inverters).\n");
+
+ size_t argidx = 1;
+ extra_args(args, argidx, design);
+
+ for (Module *module : design->selected_modules()) {
+ FoldInvWorker worker(module);
+ worker();
+ }
+ }
+} GatemateFoldInvPass;
+
+PRIVATE_NAMESPACE_END
+
diff --git a/techlibs/gatemate/inv_map.v b/techlibs/gatemate/inv_map.v
new file mode 100644
index 000000000..8a5051747
--- /dev/null
+++ b/techlibs/gatemate/inv_map.v
@@ -0,0 +1,4 @@
+// Any inverters not folded into LUTs are mapped to a LUT of their own
+module \$__CC_NOT (input A, output Y);
+ CC_LUT1 #(.INIT(2'b01)) _TECHMAP_REPLACE_ (.I0(A), .O(Y));
+endmodule
diff --git a/techlibs/gatemate/make_lut_tree_lib.py b/techlibs/gatemate/make_lut_tree_lib.py
new file mode 100644
index 000000000..25ca88882
--- /dev/null
+++ b/techlibs/gatemate/make_lut_tree_lib.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python3
+
+class FNode:
+ def __init__(self, fun, *args):
+ self.fun = fun
+ self.args = args
+
+ if len(self.args) == 0:
+ assert fun not in ("BUF", "NOT", "AND", "OR", "XOR", "MUX")
+
+ if len(self.args) == 1:
+ assert fun in ("BUF", "NOT")
+
+ if len(self.args) == 2:
+ assert fun in ("AND", "OR", "XOR")
+
+ if len(self.args) == 3:
+ assert fun in ("MUX")
+
+ def __str__(self):
+ if len(self.args) == 0:
+ return self.fun
+ if self.fun == "NOT" and len(self.args[0].args) == 0:
+ return "!" + self.args[0].fun
+ return self.fun + "(" + ",".join([str(a) for a in self.args]) + ")"
+
+ def as_genlib_term(self):
+ if len(self.args) == 0:
+ return self.fun
+ if self.fun == "NOT":
+ assert len(self.args[0].args) == 0
+ return "!" + self.args[0].fun
+ if self.fun == "AND":
+ return "(" + self.args[0].as_genlib_term() + "*" + self.args[1].as_genlib_term() + ")"
+ if self.fun == "OR":
+ return "(" + self.args[0].as_genlib_term() + "+" + self.args[1].as_genlib_term() + ")"
+ assert False
+
+ def mapMux(self):
+ if self.fun == "MUX":
+ A, B, C = self.args
+ return OR(AND(A, NOT(C)), AND(B, C)).mapMux()
+ return FNode(self.fun, *[a.mapMux() for a in self.args])
+
+ def mapXor(self):
+ if self.fun == "XOR":
+ A, B = self.args
+ return OR(AND(A, NOT(B)), AND(NOT(A), B)).mapXor()
+ return FNode(self.fun, *[a.mapXor() for a in self.args])
+
+ def mapNot(self):
+ if self.fun == "BUF":
+ return self.arg1.mapNot()
+ if self.fun == "NOT":
+ if self.args[0].fun == "AND":
+ return OR(NOT(self.args[0].args[0]),NOT(self.args[0].args[1])).mapNot()
+ if self.args[0].fun == "OR":
+ return AND(NOT(self.args[0].args[0]),NOT(self.args[0].args[1])).mapNot()
+ if self.args[0].fun == "NOT":
+ return self.args[0].args[0].mapNot()
+ return FNode(self.fun, *[a.mapNot() for a in self.args])
+
+ def map(self):
+ n = self
+ n = n.mapMux()
+ n = n.mapXor()
+ n = n.mapNot()
+ return n
+
+ def isInv(self):
+ if len(self.args) == 0:
+ return False
+ if self.fun == "XOR":
+ return False
+ if self.fun == "NOT":
+ return self.args[0].isNonInv()
+ for a in self.args:
+ if not a.isInv():
+ return False
+ return True
+
+ def isNonInv(self):
+ if len(self.args) == 0:
+ return True
+ if self.fun == "XOR":
+ return False
+ if self.fun == "NOT":
+ return self.args[0].isInv()
+ for a in self.args:
+ if not a.isNonInv():
+ return False
+ return True
+
+A = FNode("A")
+B = FNode("B")
+C = FNode("C")
+D = FNode("D")
+E = FNode("E")
+
+def BUF(arg): return FNode("BUF", arg)
+def NOT(arg): return FNode("NOT", arg)
+def AND(arg1, arg2): return FNode("AND", arg1, arg2)
+def OR(arg1, arg2): return FNode( "OR", arg1, arg2)
+def XOR(arg1, arg2): return FNode("XOR", arg1, arg2)
+def MUX(arg1, arg2, arg3): return FNode("MUX", arg1, arg2, arg3)
+
+# Genlib Format:
+#
+# GATE <cell-name> <cell-area> <cell-logic-function>
+#
+# PIN <pin-name> <phase> <input-load> <max-load>
+# <rise-block-delay> <rise-fanout-delay>
+# <fall-block-delay> <fall-fanout-delay>
+#
+# phase:
+# INV, NONINV, or UNKNOWN
+#
+# cell-logic-function:
+# <output> = <term with *(AND), +(OR), !(NOT)>
+
+
+cells = [
+ ["$__CC_BUF", 5, A],
+ ["$__CC_NOT", 0, NOT(A)],
+ ["$__CC_MUX", 5, MUX(A, B, C)],
+]
+
+base_cells = [
+ ["$__CC2_A", AND(A, B)],
+ ["$__CC2_O", OR(A, B)],
+ ["$__CC2_X", XOR(A, B)],
+
+ ["$__CC3_AA", AND(AND(A, B), C)],
+ ["$__CC3_OO", OR( OR(A, B), C)],
+ ["$__CC3_XX", XOR(XOR(A, B), C)],
+ ["$__CC3_AO", OR(AND(A, B), C)],
+ ["$__CC3_OA", AND( OR(A, B), C)],
+ ["$__CC3_AX", XOR(AND(A, B), C)],
+ ["$__CC3_XA", AND(XOR(A, B), C)],
+
+# ["$__CC3_AAA", AND(AND(A,B),AND(A,C))],
+# ["$__CC3_AXA", XOR(AND(A,B),AND(A,C))],
+# ["$__CC3_XAX", AND(XOR(A,B),XOR(A,C))],
+# ["$__CC3_AAX", AND(AND(A,B),XOR(A,C))],
+# ["$__CC3_AXX", XOR(AND(A,B),XOR(A,C))],
+# ["$__CC3_XXX", XOR(XOR(A,B),XOR(A,C))],
+# ["$__CC3_AAO", AND(AND(A,B), OR(A,C))],
+# ["$__CC3_AOA", OR(AND(A,B),AND(A,C))],
+# ["$__CC3_AOX", OR(AND(A,B),XOR(A,C))],
+
+# ["$__CC3_AAA_N", AND(AND(A,B),AND(NOT(A),C))],
+# ["$__CC3_AXA_N", XOR(AND(A,B),AND(NOT(A),C))],
+# ["$__CC3_XAX_N", AND(XOR(A,B),XOR(NOT(A),C))],
+# ["$__CC3_AAX_N", AND(AND(A,B),XOR(NOT(A),C))],
+# ["$__CC3_AXX_N", XOR(AND(A,B),XOR(NOT(A),C))],
+# ["$__CC3_XXX_N", XOR(XOR(A,B),XOR(NOT(A),C))],
+# ["$__CC3_AAO_N", AND(AND(A,B), OR(NOT(A),C))],
+# ["$__CC3_AOA_N", OR(AND(A,B),AND(NOT(A),C))],
+# ["$__CC3_AOX_N", OR(AND(A,B),XOR(NOT(A),C))],
+
+ ["$__CC4_AAA", AND(AND(A,B),AND(C,D))],
+ ["$__CC4_AXA", XOR(AND(A,B),AND(C,D))],
+ ["$__CC4_XAX", AND(XOR(A,B),XOR(C,D))],
+ ["$__CC4_AAX", AND(AND(A,B),XOR(C,D))],
+ ["$__CC4_AXX", XOR(AND(A,B),XOR(C,D))],
+ ["$__CC4_XXX", XOR(XOR(A,B),XOR(C,D))],
+ ["$__CC4_AAO", AND(AND(A,B), OR(C,D))],
+ ["$__CC4_AOA", OR(AND(A,B),AND(C,D))],
+ ["$__CC4_AOX", OR(AND(A,B),XOR(C,D))],
+]
+
+for name, expr in base_cells:
+ cells.append([name, 10, expr])
+
+ name = (name
+ .replace("$__CC4_", "$__CC5_")
+ .replace("$__CC3_", "$__CC4_")
+ .replace("$__CC2_", "$__CC3_"))
+
+ # Cells such as $__CC4_AA_A are redundant, as $__CC4_AAA is equivalent
+ if name not in ("$__CC4_AA", "$__CC3_A"):
+ cells.append([name + "_A", 12, AND(E, expr)])
+ if name not in ("$__CC4_OO", "$__CC3_O"):
+ cells.append([name + "_O", 12, OR(E, expr)])
+ if name not in ("$__CC4_XX", "$__CC3_X"):
+ cells.append([name + "_X", 12, XOR(E, expr)])
+
+with open("techlibs/gatemate/lut_tree_cells.genlib", "w") as glf:
+ def mkGate(name, cost, expr, max_load=9999, block_delay = 10, fanout_delay = 5):
+ name = name.replace(" ", "")
+ expr = expr.map()
+
+ phase = "UNKNOWN"
+ if expr.isInv(): phase = "INV"
+ if expr.isNonInv(): phase = "NONINV"
+
+ print("", file=glf)
+ print("GATE %s %d Y=%s;" % (name, cost, expr.as_genlib_term()), file=glf)
+ print("PIN * %s 1 %d %d %d %d %d" % (phase, max_load, block_delay, fanout_delay, block_delay, fanout_delay), file=glf)
+ print("GATE $__ZERO 0 Y=CONST0;", file=glf)
+ print("GATE $__ONE 0 Y=CONST1;", file=glf)
+ for name, cost, expr in cells:
+ mkGate(name, cost, expr)
+
+class LUTTreeNode:
+ def __init__(self, name, width, inputs=None):
+ self.name = name
+ self.width = width
+ self.inputs = inputs
+ def is_input(self):
+ return self.width == 0
+ def map(self, expr, params, ports):
+ if self.is_input():
+ # Input to LUT tree
+ if expr is None:
+ ports[self.name] = "" # disconnected input
+ else:
+ assert(len(expr.args) == 0)
+ ports[self.name] = expr.fun
+ return
+ if expr is None:
+ # Unused part of tree
+ params[self.name] = "4'b0000"
+ for i in self.inputs:
+ i.map(None, params, ports)
+ return
+ elif len(expr.args) == 0:
+ # Input to the expression; but not LUT tree
+ # Insert a route through
+ params[self.name] = "4'b1010"
+ self.inputs[0].map(expr, params, ports)
+ for i in self.inputs[1:]:
+ i.map(None, params, ports)
+ return
+ # Map uphill LUTs; uninverting arguments and keeping track of that if needed
+ arg_inv = []
+ for (i, arg) in zip(self.inputs, expr.args):
+ if arg.fun == "NOT":
+ i.map(arg.args[0], params, ports)
+ arg_inv.append(True)
+ else:
+ i.map(arg, params, ports)
+ arg_inv.append(False)
+ # Determine base init value
+ assert self.width == 2
+ if expr.fun == "AND":
+ init = 0b1000
+ elif expr.fun == "OR":
+ init = 0b1110
+ elif expr.fun == "XOR":
+ init = 0b0110
+ else:
+ assert False, expr.fun
+ # Swap bits if init inverted
+ swapped_init = 0b0000
+ for b in range(4):
+ if ((init >> b) & 0x1) == 0: continue
+ for i in range(2):
+ if arg_inv[i]:
+ b ^= (1 << i)
+ swapped_init |= (1 << b)
+ # Set init param
+ params[self.name] = "4'b{:04b}".format(swapped_init)
+
+def LUT2(name, i0, i1): return LUTTreeNode(name, 2, [i0, i1])
+def I(name): return LUTTreeNode(name, 0)
+
+lut_prims = {
+ "CC_LUT2": LUT2("INIT", I("I0"), I("I1")),
+ "CC_L2T4": LUT2(
+ "INIT_L10",
+ LUT2("INIT_L00", I("I0"), I("I1")),
+ LUT2("INIT_L01", I("I2"), I("I3")),
+ ),
+ "CC_L2T5": LUT2(
+ "INIT_L20", I("I4"), LUT2("INIT_L11",
+ LUT2("INIT_L02", I("I0"), I("I1")),
+ LUT2("INIT_L03", I("I2"), I("I3")),
+ )
+ )
+}
+
+with open("techlibs/gatemate/lut_tree_map.v", "w") as vf:
+ # Non-automatic rules
+ print("""
+module \\$__ZERO (output Y); assign Y = 1'b0; endmodule
+module \\$__ONE (output Y); assign Y = 1'b1; endmodule
+
+module \\$__CC_BUF (input A, output Y); assign Y = A; endmodule
+
+module \\$__CC_MUX (input A, B, C, output Y);
+ CC_MX2 _TECHMAP_REPLACE_ (
+ .D0(A), .D1(B), .S0(C),
+ .Y(Y)
+ );
+endmodule
+""", file=vf)
+ for name, cost, expr in cells:
+ expr = expr.mapMux().mapNot() # Don't map XOR
+ if name in ("$__CC_BUF", "$__CC_NOT", "$__CC_MUX"):
+ # Special cases
+ continue
+ if name.startswith("$__CC2_"):
+ prim = "CC_LUT2"
+ elif name.startswith("$__CC5_") or (name.startswith("$__CC4_") and cost == 12):
+ prim = "CC_L2T5"
+ else:
+ prim = "CC_L2T4"
+ ports = {}
+ params = {}
+ lut_prims[prim].map(expr, params, ports)
+ print("", file=vf)
+ print("module \\%s (input %s, output Y);" % (name,
+ ", ".join(sorted(set(x for x in ports.values() if x)))), file=vf)
+ print(" %s #(" % prim, file=vf)
+ for k, v in sorted(params.items(), key=lambda x: x[0]):
+ print(" .%s(%s)," % (k, v), file=vf)
+ print(" ) _TECHMAP_REPLACE_ (", file=vf)
+ print(" %s," % ", ".join(".%s(%s)" % (k, v) for k, v in sorted(ports.items(), key=lambda x:x[0])),
+ file=vf)
+ print(" .O(Y)", file=vf)
+ print(" );", file=vf)
+ print("endmodule", file=vf)
diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc
index 93b16b2e0..dd4fde643 100644
--- a/techlibs/gatemate/synth_gatemate.cc
+++ b/techlibs/gatemate/synth_gatemate.cc
@@ -67,7 +67,10 @@ struct SynthGateMatePass : public ScriptPass
log("\n");
log(" -nomx8, -nomx4\n");
log(" do not use CC_MX{8,4} multiplexer cells in output netlist.\n");
- log("\n");;
+ log("\n");
+ log(" -luttree\n");
+ log(" use new LUT tree mapping approach (EXPERIMENTAL).\n");
+ log("\n");
log(" -dff\n");
log(" run 'abc' with -dff option\n");
log("\n");
@@ -87,7 +90,7 @@ struct SynthGateMatePass : public ScriptPass
}
string top_opt, vlog_file, json_file;
- bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, dff, retime, noiopad, noclkbuf;
+ bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf;
void clear_flags() override
{
@@ -100,6 +103,7 @@ struct SynthGateMatePass : public ScriptPass
nomult = false;
nomx4 = false;
nomx8 = false;
+ luttree = false;
dff = false;
retime = false;
noiopad = false;
@@ -158,6 +162,10 @@ struct SynthGateMatePass : public ScriptPass
nomx8 = true;
continue;
}
+ if (args[argidx] == "-luttree") {
+ luttree = true;
+ continue;
+ }
if (args[argidx] == "-dff") {
dff = true;
continue;
@@ -298,11 +306,23 @@ struct SynthGateMatePass : public ScriptPass
if (check_label("map_luts"))
{
- std::string abc_args = " -dress -lut 4";
- if (dff) {
- abc_args += " -dff";
+ if (luttree || help_mode) {
+ std::string abc_args = " -genlib +/gatemate/lut_tree_cells.genlib";
+ if (dff) {
+ abc_args += " -dff";
+ }
+ run("abc " + abc_args, "(with -luttree)");
+ run("techmap -map +/gatemate/lut_tree_map.v", "(with -luttree)");
+ run("gatemate_foldinv", "(with -luttree)");
+ run("techmap -map +/gatemate/inv_map.v", "(with -luttree)");
+ }
+ if (!luttree || help_mode) {
+ std::string abc_args = " -dress -lut 4";
+ if (dff) {
+ abc_args += " -dff";
+ }
+ run("abc " + abc_args, "(without -luttree)");
}
- run("abc " + abc_args);
run("clean");
}
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 15a0c41e0..0dffdf498 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -131,7 +131,6 @@ struct SynthGowinPass : public ScriptPass
if (args[argidx] == "-json" && argidx+1 < args.size()) {
json_file = args[++argidx];
nobram = true;
- nolutram = true;
continue;
}
if (args[argidx] == "-run" && argidx+1 < args.size()) {
diff --git a/tests/arch/gatemate/gen_luttrees.py b/tests/arch/gatemate/gen_luttrees.py
new file mode 100644
index 000000000..27d2225a2
--- /dev/null
+++ b/tests/arch/gatemate/gen_luttrees.py
@@ -0,0 +1,48 @@
+from random import Random
+
+def main():
+ r = Random(1)
+
+ N = 750
+ with open("tests/arch/gatemate/luttrees.v", "w") as v:
+ print(f"module luttrees(input [{N-1}:0] a, b, c, d, e, output [{N-1}:0] q);", file=v)
+ for i in range(N):
+ def f():
+ return r.choice(["&", "|", "^"])
+
+ def a(x):
+ return f"({r.choice(['', '!'])}{x}[{i}])"
+
+ # Bias towards testing bigger functions
+ k = r.choice([2, 3, 4, 4, 4, 5, 5, 5])
+ if k == 2:
+ expr = f"{a('a')}{f()}{a('b')}"
+ elif k == 3:
+ expr = f"({a('a')}{f()}{a('b')}){f()}{a('c')}"
+ elif k == 4:
+ # Two types of 4-input function
+ if r.choice([False, True]):
+ expr = f"(({a('a')}{f()}{a('b')}){f()}{a('c')}){f()}{a('d')}"
+ else:
+ expr = f"({a('a')}{f()}{a('b')}){f()}({a('c')}{f()}{a('d')})"
+ elif k == 5:
+ expr = f"(({a('a')}{f()}{a('b')}){f()}({a('c')}{f()}{a('d')})){f()}{a('e')}"
+ print(f" assign q[{i}] = {expr};", file=v)
+ print("endmodule", file=v)
+ with open("tests/arch/gatemate/luttrees.ys", "w") as s:
+ print(f"""
+read_verilog luttrees.v
+design -save read
+
+hierarchy -top luttrees
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -nomx4 -nomx8 # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd luttrees # Constrain all select calls below inside the top module
+
+select -assert-count {N} t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %%
+select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D
+""", file=s)
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/arch/gatemate/luttrees.v b/tests/arch/gatemate/luttrees.v
new file mode 100644
index 000000000..7fc02916d
--- /dev/null
+++ b/tests/arch/gatemate/luttrees.v
@@ -0,0 +1,752 @@
+module luttrees(input [749:0] a, b, c, d, e, output [749:0] q);
+ assign q[0] = ((!a[0])&(!b[0]))|((!c[0])^(!d[0]));
+ assign q[1] = ((!a[1])&(!b[1]))|((c[1])^(!d[1]));
+ assign q[2] = ((a[2])|(b[2]))&((c[2])^(d[2]));
+ assign q[3] = (((a[3])|(b[3]))^((c[3])|(!d[3])))^(e[3]);
+ assign q[4] = (((a[4])^(b[4]))|((!c[4])&(!d[4])))^(e[4]);
+ assign q[5] = (((a[5])^(!b[5]))^(!c[5]))^(d[5]);
+ assign q[6] = (((!a[6])^(!b[6]))^(c[6]))|(d[6]);
+ assign q[7] = (((!a[7])^(b[7]))|((!c[7])&(!d[7])))^(e[7]);
+ assign q[8] = (((!a[8])|(b[8]))|(c[8]))|(!d[8]);
+ assign q[9] = ((a[9])&(b[9]))^((c[9])|(!d[9]));
+ assign q[10] = (((!a[10])|(b[10]))|((c[10])^(d[10])))|(e[10]);
+ assign q[11] = (((!a[11])^(b[11]))^((!c[11])|(!d[11])))|(!e[11]);
+ assign q[12] = (!a[12])|(b[12]);
+ assign q[13] = ((a[13])&(!b[13]))&((c[13])&(d[13]));
+ assign q[14] = (((a[14])|(b[14]))|((c[14])^(d[14])))|(!e[14]);
+ assign q[15] = ((a[15])&(!b[15]))^(c[15]);
+ assign q[16] = (((!a[16])^(!b[16]))|(!c[16]))&(d[16]);
+ assign q[17] = (((!a[17])|(b[17]))|(c[17]))|(d[17]);
+ assign q[18] = (((a[18])&(b[18]))|((c[18])&(d[18])))|(!e[18]);
+ assign q[19] = (((a[19])^(b[19]))|(!c[19]))^(!d[19]);
+ assign q[20] = (!a[20])&(b[20]);
+ assign q[21] = (!a[21])&(b[21]);
+ assign q[22] = (((a[22])|(!b[22]))&(c[22]))^(d[22]);
+ assign q[23] = (((a[23])^(b[23]))|(c[23]))|(d[23]);
+ assign q[24] = (((a[24])|(b[24]))^(!c[24]))|(!d[24]);
+ assign q[25] = (!a[25])^(!b[25]);
+ assign q[26] = ((a[26])&(!b[26]))^((c[26])|(!d[26]));
+ assign q[27] = (((a[27])|(!b[27]))^(!c[27]))^(d[27]);
+ assign q[28] = ((a[28])&(b[28]))&(c[28]);
+ assign q[29] = (((!a[29])^(!b[29]))|(!c[29]))|(d[29]);
+ assign q[30] = ((!a[30])&(b[30]))|((c[30])|(d[30]));
+ assign q[31] = (((a[31])&(!b[31]))&((!c[31])&(d[31])))^(e[31]);
+ assign q[32] = (((!a[32])^(b[32]))|(!c[32]))&(d[32]);
+ assign q[33] = ((a[33])&(!b[33]))&((c[33])&(d[33]));
+ assign q[34] = (((a[34])&(!b[34]))&((c[34])&(d[34])))|(!e[34]);
+ assign q[35] = (((!a[35])|(b[35]))&(!c[35]))&(d[35]);
+ assign q[36] = (!a[36])^(!b[36]);
+ assign q[37] = (((!a[37])|(!b[37]))&((c[37])|(!d[37])))&(!e[37]);
+ assign q[38] = (((!a[38])|(b[38]))^(c[38]))|(d[38]);
+ assign q[39] = (((a[39])|(b[39]))|(c[39]))^(!d[39]);
+ assign q[40] = (((!a[40])&(!b[40]))&(!c[40]))^(!d[40]);
+ assign q[41] = (((a[41])^(b[41]))&(c[41]))&(d[41]);
+ assign q[42] = (((a[42])|(b[42]))^((c[42])&(d[42])))|(!e[42]);
+ assign q[43] = (((!a[43])&(b[43]))^((!c[43])&(d[43])))&(e[43]);
+ assign q[44] = (((!a[44])&(!b[44]))&(c[44]))&(d[44]);
+ assign q[45] = (((a[45])&(!b[45]))|((c[45])&(d[45])))|(e[45]);
+ assign q[46] = (((!a[46])^(!b[46]))^((!c[46])^(!d[46])))&(!e[46]);
+ assign q[47] = (((a[47])|(!b[47]))&((!c[47])^(d[47])))&(!e[47]);
+ assign q[48] = ((a[48])|(!b[48]))|((!c[48])&(d[48]));
+ assign q[49] = (((a[49])&(!b[49]))^(!c[49]))^(d[49]);
+ assign q[50] = (((!a[50])^(!b[50]))&(!c[50]))|(!d[50]);
+ assign q[51] = ((a[51])^(!b[51]))&((c[51])|(!d[51]));
+ assign q[52] = (((a[52])^(!b[52]))^(c[52]))&(!d[52]);
+ assign q[53] = ((!a[53])|(b[53]))^((c[53])|(!d[53]));
+ assign q[54] = (((!a[54])^(b[54]))^((c[54])^(d[54])))|(e[54]);
+ assign q[55] = ((a[55])^(b[55]))|((c[55])|(!d[55]));
+ assign q[56] = (((a[56])|(!b[56]))&((!c[56])&(d[56])))|(!e[56]);
+ assign q[57] = ((!a[57])|(b[57]))|(c[57]);
+ assign q[58] = (((a[58])&(b[58]))|(c[58]))&(!d[58]);
+ assign q[59] = ((!a[59])|(!b[59]))^((!c[59])&(!d[59]));
+ assign q[60] = (((!a[60])&(b[60]))^((!c[60])&(!d[60])))&(e[60]);
+ assign q[61] = ((a[61])^(!b[61]))^(c[61]);
+ assign q[62] = ((!a[62])^(!b[62]))|(!c[62]);
+ assign q[63] = (((a[63])&(!b[63]))^((!c[63])|(!d[63])))^(!e[63]);
+ assign q[64] = (((!a[64])&(!b[64]))|((c[64])^(d[64])))|(e[64]);
+ assign q[65] = (((!a[65])^(!b[65]))^((c[65])|(d[65])))|(e[65]);
+ assign q[66] = (((!a[66])|(!b[66]))^((c[66])|(d[66])))^(!e[66]);
+ assign q[67] = (!a[67])^(b[67]);
+ assign q[68] = (((!a[68])&(b[68]))^((c[68])|(!d[68])))^(!e[68]);
+ assign q[69] = ((!a[69])|(!b[69]))&((!c[69])^(d[69]));
+ assign q[70] = ((!a[70])&(!b[70]))&((!c[70])&(d[70]));
+ assign q[71] = ((!a[71])^(!b[71]))^((!c[71])&(d[71]));
+ assign q[72] = (((!a[72])&(b[72]))^(!c[72]))|(d[72]);
+ assign q[73] = (((!a[73])|(b[73]))|(!c[73]))&(!d[73]);
+ assign q[74] = (((a[74])|(b[74]))^(c[74]))^(!d[74]);
+ assign q[75] = (((!a[75])&(!b[75]))&((c[75])^(d[75])))^(!e[75]);
+ assign q[76] = (((!a[76])^(b[76]))&(c[76]))^(!d[76]);
+ assign q[77] = (((!a[77])|(b[77]))&((c[77])^(!d[77])))&(e[77]);
+ assign q[78] = (((!a[78])|(b[78]))&(c[78]))&(d[78]);
+ assign q[79] = ((!a[79])^(!b[79]))|((!c[79])&(d[79]));
+ assign q[80] = ((a[80])|(b[80]))|(!c[80]);
+ assign q[81] = (((a[81])&(b[81]))|((!c[81])^(!d[81])))&(!e[81]);
+ assign q[82] = (((!a[82])^(b[82]))&(c[82]))&(d[82]);
+ assign q[83] = (!a[83])|(!b[83]);
+ assign q[84] = ((!a[84])&(b[84]))&((c[84])|(d[84]));
+ assign q[85] = (!a[85])|(b[85]);
+ assign q[86] = ((!a[86])^(!b[86]))&(c[86]);
+ assign q[87] = (a[87])&(!b[87]);
+ assign q[88] = ((!a[88])&(b[88]))&(!c[88]);
+ assign q[89] = (((a[89])^(!b[89]))|(!c[89]))^(!d[89]);
+ assign q[90] = ((a[90])&(b[90]))|((!c[90])^(d[90]));
+ assign q[91] = (((!a[91])^(b[91]))^((!c[91])^(d[91])))^(!e[91]);
+ assign q[92] = ((!a[92])&(b[92]))&(c[92]);
+ assign q[93] = (((a[93])&(b[93]))^(!c[93]))^(!d[93]);
+ assign q[94] = ((!a[94])&(b[94]))^(c[94]);
+ assign q[95] = (((a[95])|(!b[95]))&((!c[95])&(!d[95])))|(e[95]);
+ assign q[96] = ((!a[96])&(!b[96]))|((c[96])|(!d[96]));
+ assign q[97] = ((!a[97])&(!b[97]))&(c[97]);
+ assign q[98] = (((!a[98])^(!b[98]))^((!c[98])&(d[98])))^(!e[98]);
+ assign q[99] = (!a[99])^(b[99]);
+ assign q[100] = (((!a[100])^(!b[100]))&(!c[100]))|(d[100]);
+ assign q[101] = ((a[101])|(!b[101]))|(!c[101]);
+ assign q[102] = (((!a[102])|(!b[102]))^((c[102])^(d[102])))&(!e[102]);
+ assign q[103] = (((!a[103])^(b[103]))|((!c[103])|(!d[103])))|(!e[103]);
+ assign q[104] = ((a[104])&(b[104]))^(!c[104]);
+ assign q[105] = ((!a[105])|(!b[105]))|((!c[105])|(!d[105]));
+ assign q[106] = ((a[106])|(b[106]))^((c[106])&(d[106]));
+ assign q[107] = (((a[107])&(!b[107]))^((c[107])&(!d[107])))&(e[107]);
+ assign q[108] = ((a[108])^(b[108]))^(!c[108]);
+ assign q[109] = (!a[109])|(!b[109]);
+ assign q[110] = ((!a[110])&(!b[110]))|((!c[110])^(d[110]));
+ assign q[111] = (((a[111])|(!b[111]))&((c[111])^(!d[111])))^(!e[111]);
+ assign q[112] = ((!a[112])^(!b[112]))&(!c[112]);
+ assign q[113] = (((a[113])&(!b[113]))^((c[113])^(d[113])))|(!e[113]);
+ assign q[114] = (((!a[114])^(!b[114]))|(!c[114]))&(!d[114]);
+ assign q[115] = ((!a[115])^(b[115]))|((c[115])|(!d[115]));
+ assign q[116] = (((!a[116])^(b[116]))&((c[116])&(!d[116])))|(!e[116]);
+ assign q[117] = (((!a[117])|(!b[117]))|(c[117]))|(!d[117]);
+ assign q[118] = (((a[118])&(b[118]))|(!c[118]))&(!d[118]);
+ assign q[119] = (((!a[119])^(!b[119]))^((!c[119])^(!d[119])))|(!e[119]);
+ assign q[120] = (((a[120])^(!b[120]))|((!c[120])&(d[120])))&(e[120]);
+ assign q[121] = ((a[121])&(!b[121]))&((!c[121])&(!d[121]));
+ assign q[122] = ((a[122])|(b[122]))^((c[122])^(!d[122]));
+ assign q[123] = (((a[123])^(b[123]))^((!c[123])^(d[123])))|(!e[123]);
+ assign q[124] = (((a[124])&(b[124]))|(c[124]))^(!d[124]);
+ assign q[125] = (((!a[125])&(!b[125]))&(c[125]))|(d[125]);
+ assign q[126] = (((!a[126])^(!b[126]))|(c[126]))^(!d[126]);
+ assign q[127] = (((a[127])&(!b[127]))^((!c[127])&(!d[127])))|(e[127]);
+ assign q[128] = (((!a[128])^(b[128]))|(c[128]))&(!d[128]);
+ assign q[129] = (((a[129])^(b[129]))|(!c[129]))|(!d[129]);
+ assign q[130] = (((!a[130])&(!b[130]))|(!c[130]))&(!d[130]);
+ assign q[131] = ((!a[131])^(b[131]))&((!c[131])^(d[131]));
+ assign q[132] = (((!a[132])|(!b[132]))&(c[132]))&(!d[132]);
+ assign q[133] = ((a[133])^(b[133]))^((c[133])&(d[133]));
+ assign q[134] = (((!a[134])&(b[134]))|(c[134]))&(d[134]);
+ assign q[135] = (((!a[135])^(!b[135]))&(c[135]))|(!d[135]);
+ assign q[136] = ((!a[136])&(b[136]))|((c[136])&(d[136]));
+ assign q[137] = (((a[137])|(b[137]))|(c[137]))&(d[137]);
+ assign q[138] = (((!a[138])^(b[138]))&((!c[138])|(d[138])))^(!e[138]);
+ assign q[139] = ((!a[139])^(b[139]))^(!c[139]);
+ assign q[140] = (((a[140])^(!b[140]))^((!c[140])^(!d[140])))|(e[140]);
+ assign q[141] = ((a[141])^(b[141]))&((c[141])&(!d[141]));
+ assign q[142] = ((!a[142])^(!b[142]))^((!c[142])|(d[142]));
+ assign q[143] = (((a[143])^(!b[143]))&((!c[143])^(d[143])))^(!e[143]);
+ assign q[144] = (((a[144])&(b[144]))^((c[144])^(d[144])))|(!e[144]);
+ assign q[145] = (((!a[145])&(b[145]))|((!c[145])|(d[145])))^(e[145]);
+ assign q[146] = (((a[146])^(b[146]))^(c[146]))|(d[146]);
+ assign q[147] = (((a[147])|(!b[147]))|((!c[147])|(!d[147])))^(!e[147]);
+ assign q[148] = (a[148])|(b[148]);
+ assign q[149] = (a[149])&(b[149]);
+ assign q[150] = (((!a[150])^(!b[150]))|((c[150])^(d[150])))&(!e[150]);
+ assign q[151] = ((a[151])^(!b[151]))|((!c[151])|(d[151]));
+ assign q[152] = (((!a[152])|(!b[152]))|((!c[152])|(d[152])))^(e[152]);
+ assign q[153] = (!a[153])^(b[153]);
+ assign q[154] = (((!a[154])^(b[154]))^(c[154]))|(d[154]);
+ assign q[155] = (((a[155])|(b[155]))&((c[155])|(!d[155])))^(e[155]);
+ assign q[156] = (((!a[156])|(!b[156]))^((c[156])|(!d[156])))|(e[156]);
+ assign q[157] = (((!a[157])&(b[157]))&((!c[157])|(d[157])))&(e[157]);
+ assign q[158] = (((!a[158])^(!b[158]))&(c[158]))^(d[158]);
+ assign q[159] = ((!a[159])|(b[159]))^((!c[159])&(d[159]));
+ assign q[160] = (((a[160])^(b[160]))|((c[160])&(d[160])))&(!e[160]);
+ assign q[161] = (a[161])|(b[161]);
+ assign q[162] = (a[162])^(b[162]);
+ assign q[163] = (((!a[163])&(b[163]))|(c[163]))^(d[163]);
+ assign q[164] = (((a[164])^(b[164]))&((c[164])|(!d[164])))|(!e[164]);
+ assign q[165] = ((!a[165])^(!b[165]))^((!c[165])^(d[165]));
+ assign q[166] = (((!a[166])&(!b[166]))|((!c[166])&(!d[166])))^(!e[166]);
+ assign q[167] = ((!a[167])|(b[167]))|((!c[167])|(!d[167]));
+ assign q[168] = (((!a[168])^(!b[168]))&((c[168])&(!d[168])))&(e[168]);
+ assign q[169] = ((a[169])^(!b[169]))^(c[169]);
+ assign q[170] = (((!a[170])^(b[170]))&(c[170]))&(d[170]);
+ assign q[171] = (!a[171])|(!b[171]);
+ assign q[172] = ((a[172])&(!b[172]))&((!c[172])&(!d[172]));
+ assign q[173] = (((a[173])&(!b[173]))^((c[173])|(!d[173])))^(!e[173]);
+ assign q[174] = ((!a[174])&(!b[174]))&(!c[174]);
+ assign q[175] = ((!a[175])|(!b[175]))^(c[175]);
+ assign q[176] = (!a[176])&(b[176]);
+ assign q[177] = ((a[177])|(b[177]))^(c[177]);
+ assign q[178] = (((a[178])^(b[178]))|((c[178])^(!d[178])))^(e[178]);
+ assign q[179] = ((a[179])^(!b[179]))^(!c[179]);
+ assign q[180] = (((a[180])^(b[180]))^(c[180]))|(!d[180]);
+ assign q[181] = (((!a[181])|(!b[181]))&((c[181])&(d[181])))|(e[181]);
+ assign q[182] = (((a[182])|(!b[182]))&((c[182])&(d[182])))|(!e[182]);
+ assign q[183] = ((a[183])^(!b[183]))^((!c[183])&(d[183]));
+ assign q[184] = (((a[184])|(b[184]))|((c[184])^(d[184])))&(!e[184]);
+ assign q[185] = (((a[185])^(b[185]))^((!c[185])&(!d[185])))^(!e[185]);
+ assign q[186] = (((!a[186])|(!b[186]))&((!c[186])&(!d[186])))|(!e[186]);
+ assign q[187] = (((a[187])^(!b[187]))|(!c[187]))^(d[187]);
+ assign q[188] = ((a[188])^(b[188]))&(!c[188]);
+ assign q[189] = (((!a[189])^(b[189]))^((!c[189])^(d[189])))|(e[189]);
+ assign q[190] = (((!a[190])^(b[190]))&((!c[190])|(d[190])))&(e[190]);
+ assign q[191] = ((!a[191])|(!b[191]))|(!c[191]);
+ assign q[192] = (((a[192])^(b[192]))^(c[192]))|(!d[192]);
+ assign q[193] = ((a[193])^(b[193]))|((!c[193])&(d[193]));
+ assign q[194] = (((a[194])&(b[194]))|(!c[194]))&(!d[194]);
+ assign q[195] = ((!a[195])|(!b[195]))^((c[195])&(!d[195]));
+ assign q[196] = (((a[196])&(!b[196]))|((c[196])^(d[196])))^(!e[196]);
+ assign q[197] = ((a[197])&(b[197]))^((c[197])^(!d[197]));
+ assign q[198] = (((a[198])&(!b[198]))|((!c[198])^(!d[198])))&(e[198]);
+ assign q[199] = (!a[199])&(b[199]);
+ assign q[200] = ((a[200])&(b[200]))^((c[200])&(d[200]));
+ assign q[201] = (((!a[201])&(!b[201]))^(!c[201]))|(!d[201]);
+ assign q[202] = ((a[202])^(b[202]))&(!c[202]);
+ assign q[203] = (((!a[203])|(b[203]))|((c[203])&(!d[203])))^(!e[203]);
+ assign q[204] = (((a[204])^(!b[204]))&((!c[204])^(!d[204])))^(!e[204]);
+ assign q[205] = (((a[205])|(!b[205]))^((!c[205])^(!d[205])))|(!e[205]);
+ assign q[206] = (a[206])|(!b[206]);
+ assign q[207] = (((a[207])^(!b[207]))&((!c[207])|(d[207])))|(!e[207]);
+ assign q[208] = (a[208])|(b[208]);
+ assign q[209] = ((!a[209])|(b[209]))|((!c[209])|(d[209]));
+ assign q[210] = ((!a[210])&(b[210]))&((!c[210])|(!d[210]));
+ assign q[211] = ((a[211])^(!b[211]))|((!c[211])|(!d[211]));
+ assign q[212] = (((a[212])&(!b[212]))&((c[212])^(d[212])))^(e[212]);
+ assign q[213] = (((!a[213])&(b[213]))^(!c[213]))^(!d[213]);
+ assign q[214] = (!a[214])|(!b[214]);
+ assign q[215] = ((a[215])|(!b[215]))^((!c[215])^(!d[215]));
+ assign q[216] = (((a[216])^(!b[216]))^((!c[216])|(d[216])))|(e[216]);
+ assign q[217] = (((a[217])^(b[217]))^((!c[217])|(!d[217])))&(e[217]);
+ assign q[218] = ((a[218])&(!b[218]))&(c[218]);
+ assign q[219] = ((a[219])|(b[219]))&((c[219])&(d[219]));
+ assign q[220] = (((!a[220])&(b[220]))^((c[220])|(d[220])))|(!e[220]);
+ assign q[221] = ((a[221])&(!b[221]))&((c[221])^(!d[221]));
+ assign q[222] = (!a[222])|(!b[222]);
+ assign q[223] = ((a[223])^(b[223]))^(c[223]);
+ assign q[224] = ((a[224])&(!b[224]))&((c[224])|(d[224]));
+ assign q[225] = ((!a[225])&(b[225]))&(!c[225]);
+ assign q[226] = (((a[226])^(b[226]))|((c[226])&(d[226])))&(e[226]);
+ assign q[227] = ((a[227])&(b[227]))|((!c[227])^(!d[227]));
+ assign q[228] = ((!a[228])&(!b[228]))|((!c[228])|(!d[228]));
+ assign q[229] = (((a[229])|(b[229]))|((!c[229])&(d[229])))&(e[229]);
+ assign q[230] = (((!a[230])^(!b[230]))|((!c[230])|(!d[230])))|(!e[230]);
+ assign q[231] = (((!a[231])|(b[231]))|((c[231])|(d[231])))|(e[231]);
+ assign q[232] = ((!a[232])^(b[232]))&((c[232])&(!d[232]));
+ assign q[233] = (((!a[233])&(!b[233]))|(!c[233]))&(!d[233]);
+ assign q[234] = (((!a[234])&(b[234]))^(!c[234]))&(d[234]);
+ assign q[235] = (((a[235])&(b[235]))^((!c[235])^(!d[235])))^(!e[235]);
+ assign q[236] = (((!a[236])^(b[236]))&((!c[236])&(!d[236])))^(e[236]);
+ assign q[237] = (a[237])|(!b[237]);
+ assign q[238] = (((a[238])|(b[238]))&((!c[238])^(d[238])))&(e[238]);
+ assign q[239] = ((!a[239])^(!b[239]))&((c[239])&(d[239]));
+ assign q[240] = (((!a[240])^(!b[240]))&(!c[240]))&(!d[240]);
+ assign q[241] = ((!a[241])&(b[241]))&(c[241]);
+ assign q[242] = ((a[242])|(!b[242]))&((c[242])|(d[242]));
+ assign q[243] = ((a[243])|(b[243]))^((!c[243])&(d[243]));
+ assign q[244] = (((!a[244])^(b[244]))&(!c[244]))|(!d[244]);
+ assign q[245] = (((a[245])^(!b[245]))^(!c[245]))^(!d[245]);
+ assign q[246] = ((!a[246])|(!b[246]))&(!c[246]);
+ assign q[247] = ((!a[247])&(b[247]))|(c[247]);
+ assign q[248] = (((!a[248])|(!b[248]))|((!c[248])&(!d[248])))&(!e[248]);
+ assign q[249] = (a[249])|(!b[249]);
+ assign q[250] = (((!a[250])^(!b[250]))^(!c[250]))^(!d[250]);
+ assign q[251] = (((a[251])|(b[251]))|(!c[251]))^(d[251]);
+ assign q[252] = (((!a[252])&(!b[252]))^((c[252])&(d[252])))&(e[252]);
+ assign q[253] = (!a[253])^(!b[253]);
+ assign q[254] = (((a[254])^(!b[254]))|((c[254])|(!d[254])))&(!e[254]);
+ assign q[255] = (!a[255])|(!b[255]);
+ assign q[256] = (((a[256])|(!b[256]))&(c[256]))&(!d[256]);
+ assign q[257] = (!a[257])^(!b[257]);
+ assign q[258] = (((!a[258])&(b[258]))^(c[258]))|(d[258]);
+ assign q[259] = (((!a[259])&(!b[259]))|(c[259]))&(!d[259]);
+ assign q[260] = ((!a[260])&(!b[260]))|((!c[260])^(!d[260]));
+ assign q[261] = (((a[261])|(b[261]))^(c[261]))|(d[261]);
+ assign q[262] = (((!a[262])^(b[262]))^((!c[262])|(!d[262])))|(e[262]);
+ assign q[263] = (a[263])^(b[263]);
+ assign q[264] = ((!a[264])&(!b[264]))|(c[264]);
+ assign q[265] = (((!a[265])^(b[265]))^((c[265])^(!d[265])))|(!e[265]);
+ assign q[266] = (((a[266])^(!b[266]))&(c[266]))^(d[266]);
+ assign q[267] = ((a[267])|(!b[267]))|(!c[267]);
+ assign q[268] = ((!a[268])&(!b[268]))|(!c[268]);
+ assign q[269] = (((!a[269])^(b[269]))&((!c[269])^(!d[269])))^(!e[269]);
+ assign q[270] = (((a[270])|(b[270]))^(c[270]))&(d[270]);
+ assign q[271] = (((a[271])&(b[271]))|((c[271])|(d[271])))|(!e[271]);
+ assign q[272] = (((a[272])|(!b[272]))^(!c[272]))|(!d[272]);
+ assign q[273] = (((!a[273])|(b[273]))&((!c[273])&(!d[273])))&(!e[273]);
+ assign q[274] = ((a[274])^(!b[274]))|(!c[274]);
+ assign q[275] = (((!a[275])^(!b[275]))|((!c[275])^(!d[275])))^(e[275]);
+ assign q[276] = ((a[276])^(b[276]))&((!c[276])^(d[276]));
+ assign q[277] = (((!a[277])&(!b[277]))|((!c[277])^(!d[277])))&(!e[277]);
+ assign q[278] = (((!a[278])^(!b[278]))^(c[278]))&(!d[278]);
+ assign q[279] = (((a[279])&(b[279]))^((!c[279])|(d[279])))^(!e[279]);
+ assign q[280] = ((!a[280])&(!b[280]))&(!c[280]);
+ assign q[281] = ((a[281])|(b[281]))|((!c[281])|(!d[281]));
+ assign q[282] = ((a[282])&(b[282]))&((c[282])|(d[282]));
+ assign q[283] = (((a[283])|(!b[283]))^((c[283])&(!d[283])))&(e[283]);
+ assign q[284] = (((!a[284])&(b[284]))&(!c[284]))^(d[284]);
+ assign q[285] = (((a[285])|(!b[285]))&(!c[285]))|(d[285]);
+ assign q[286] = (((a[286])^(b[286]))&((c[286])^(!d[286])))&(!e[286]);
+ assign q[287] = ((a[287])&(!b[287]))|((c[287])|(!d[287]));
+ assign q[288] = ((!a[288])|(!b[288]))|((!c[288])|(!d[288]));
+ assign q[289] = ((a[289])&(b[289]))&((c[289])&(!d[289]));
+ assign q[290] = (((!a[290])^(b[290]))&((c[290])^(d[290])))&(!e[290]);
+ assign q[291] = (((a[291])&(!b[291]))|(!c[291]))^(d[291]);
+ assign q[292] = (((a[292])^(!b[292]))^((c[292])|(d[292])))&(e[292]);
+ assign q[293] = (((a[293])&(!b[293]))&((c[293])|(d[293])))|(e[293]);
+ assign q[294] = (((a[294])^(!b[294]))&((!c[294])^(d[294])))&(!e[294]);
+ assign q[295] = (((a[295])^(!b[295]))|((!c[295])|(d[295])))&(e[295]);
+ assign q[296] = (((a[296])&(!b[296]))&((c[296])&(d[296])))&(!e[296]);
+ assign q[297] = ((!a[297])|(b[297]))^((!c[297])^(!d[297]));
+ assign q[298] = (((a[298])^(b[298]))|((!c[298])|(d[298])))|(!e[298]);
+ assign q[299] = (((!a[299])^(b[299]))|((c[299])^(!d[299])))|(!e[299]);
+ assign q[300] = (((!a[300])^(!b[300]))^(!c[300]))|(d[300]);
+ assign q[301] = ((a[301])&(!b[301]))&((!c[301])|(!d[301]));
+ assign q[302] = ((a[302])^(b[302]))|((c[302])|(!d[302]));
+ assign q[303] = (((!a[303])&(b[303]))^((c[303])|(d[303])))|(!e[303]);
+ assign q[304] = (!a[304])^(b[304]);
+ assign q[305] = (((a[305])&(!b[305]))^((!c[305])&(!d[305])))^(!e[305]);
+ assign q[306] = (a[306])&(b[306]);
+ assign q[307] = ((a[307])&(!b[307]))&(c[307]);
+ assign q[308] = ((a[308])&(!b[308]))^((!c[308])|(d[308]));
+ assign q[309] = ((a[309])^(!b[309]))&((c[309])|(!d[309]));
+ assign q[310] = (((!a[310])|(b[310]))&((c[310])^(d[310])))^(!e[310]);
+ assign q[311] = (((!a[311])|(b[311]))&((c[311])&(d[311])))|(e[311]);
+ assign q[312] = (((!a[312])&(b[312]))|((c[312])^(!d[312])))&(!e[312]);
+ assign q[313] = (!a[313])|(!b[313]);
+ assign q[314] = ((a[314])^(!b[314]))^((c[314])|(!d[314]));
+ assign q[315] = (a[315])&(!b[315]);
+ assign q[316] = ((!a[316])^(!b[316]))&(!c[316]);
+ assign q[317] = ((a[317])&(!b[317]))^(c[317]);
+ assign q[318] = (((!a[318])^(!b[318]))|(!c[318]))&(!d[318]);
+ assign q[319] = (((a[319])&(!b[319]))|(!c[319]))^(d[319]);
+ assign q[320] = (((!a[320])^(!b[320]))|(c[320]))|(d[320]);
+ assign q[321] = ((a[321])|(!b[321]))|((c[321])|(d[321]));
+ assign q[322] = ((!a[322])^(!b[322]))&(!c[322]);
+ assign q[323] = (((!a[323])&(b[323]))|(c[323]))|(d[323]);
+ assign q[324] = ((!a[324])&(!b[324]))^((c[324])|(d[324]));
+ assign q[325] = ((a[325])&(!b[325]))|(!c[325]);
+ assign q[326] = ((!a[326])^(!b[326]))|(c[326]);
+ assign q[327] = (((a[327])|(b[327]))&((c[327])|(!d[327])))^(!e[327]);
+ assign q[328] = ((!a[328])|(b[328]))&((c[328])&(d[328]));
+ assign q[329] = (((a[329])&(b[329]))^(c[329]))|(!d[329]);
+ assign q[330] = ((a[330])|(b[330]))|((c[330])^(!d[330]));
+ assign q[331] = (((!a[331])|(b[331]))&(c[331]))&(d[331]);
+ assign q[332] = (((!a[332])&(b[332]))|((!c[332])^(d[332])))&(e[332]);
+ assign q[333] = (((a[333])^(!b[333]))|(!c[333]))|(!d[333]);
+ assign q[334] = ((a[334])&(!b[334]))&((c[334])&(!d[334]));
+ assign q[335] = (((!a[335])&(b[335]))^((c[335])&(d[335])))&(e[335]);
+ assign q[336] = (!a[336])^(b[336]);
+ assign q[337] = (((a[337])^(b[337]))&(c[337]))&(d[337]);
+ assign q[338] = (((a[338])^(!b[338]))&(!c[338]))&(!d[338]);
+ assign q[339] = (((!a[339])^(!b[339]))|((!c[339])|(d[339])))&(!e[339]);
+ assign q[340] = (((a[340])^(b[340]))^((c[340])^(d[340])))|(e[340]);
+ assign q[341] = (((!a[341])&(!b[341]))^(!c[341]))^(d[341]);
+ assign q[342] = (a[342])^(!b[342]);
+ assign q[343] = (((!a[343])^(b[343]))&((c[343])|(!d[343])))|(e[343]);
+ assign q[344] = ((a[344])&(b[344]))&((!c[344])&(d[344]));
+ assign q[345] = (((!a[345])&(b[345]))&((c[345])^(!d[345])))|(e[345]);
+ assign q[346] = (((a[346])^(!b[346]))&(c[346]))&(!d[346]);
+ assign q[347] = (((!a[347])^(!b[347]))|((c[347])|(!d[347])))|(!e[347]);
+ assign q[348] = (((a[348])|(b[348]))&((!c[348])&(d[348])))|(!e[348]);
+ assign q[349] = (!a[349])&(b[349]);
+ assign q[350] = (((!a[350])^(b[350]))|((c[350])|(!d[350])))&(e[350]);
+ assign q[351] = (((!a[351])^(!b[351]))^((c[351])|(!d[351])))&(!e[351]);
+ assign q[352] = ((!a[352])|(b[352]))^(c[352]);
+ assign q[353] = (((a[353])&(!b[353]))^((c[353])&(!d[353])))|(!e[353]);
+ assign q[354] = (((!a[354])^(b[354]))^((!c[354])^(d[354])))^(e[354]);
+ assign q[355] = (a[355])|(b[355]);
+ assign q[356] = (((a[356])^(!b[356]))^(!c[356]))&(!d[356]);
+ assign q[357] = (((a[357])&(!b[357]))^((c[357])&(!d[357])))^(e[357]);
+ assign q[358] = (((a[358])&(b[358]))&((!c[358])&(d[358])))|(e[358]);
+ assign q[359] = (((a[359])&(!b[359]))&((!c[359])^(!d[359])))&(e[359]);
+ assign q[360] = (((!a[360])|(!b[360]))|((!c[360])|(d[360])))&(!e[360]);
+ assign q[361] = (((a[361])|(b[361]))^((c[361])|(!d[361])))^(!e[361]);
+ assign q[362] = (((!a[362])|(!b[362]))|(c[362]))|(d[362]);
+ assign q[363] = ((a[363])|(!b[363]))&((!c[363])^(!d[363]));
+ assign q[364] = (((a[364])&(!b[364]))&((c[364])&(d[364])))|(e[364]);
+ assign q[365] = ((a[365])|(!b[365]))&((c[365])|(d[365]));
+ assign q[366] = (((a[366])|(!b[366]))&((!c[366])|(!d[366])))^(!e[366]);
+ assign q[367] = ((a[367])^(!b[367]))^((!c[367])|(!d[367]));
+ assign q[368] = (((!a[368])&(b[368]))&((!c[368])|(!d[368])))&(!e[368]);
+ assign q[369] = ((a[369])^(b[369]))|((c[369])|(d[369]));
+ assign q[370] = (((a[370])^(b[370]))^(!c[370]))|(!d[370]);
+ assign q[371] = (((a[371])^(b[371]))&((!c[371])&(d[371])))&(!e[371]);
+ assign q[372] = (((!a[372])|(!b[372]))|((!c[372])&(d[372])))&(!e[372]);
+ assign q[373] = ((a[373])&(b[373]))&((!c[373])&(!d[373]));
+ assign q[374] = (((!a[374])^(!b[374]))^((!c[374])&(!d[374])))|(e[374]);
+ assign q[375] = ((!a[375])&(b[375]))^(!c[375]);
+ assign q[376] = (!a[376])|(b[376]);
+ assign q[377] = (((!a[377])^(b[377]))^((!c[377])^(!d[377])))^(e[377]);
+ assign q[378] = (((a[378])|(!b[378]))^((c[378])^(d[378])))&(!e[378]);
+ assign q[379] = (((a[379])|(b[379]))&((!c[379])^(!d[379])))^(e[379]);
+ assign q[380] = (((!a[380])^(!b[380]))^((c[380])|(!d[380])))&(!e[380]);
+ assign q[381] = (((!a[381])^(b[381]))^(c[381]))^(!d[381]);
+ assign q[382] = (((!a[382])^(b[382]))^(!c[382]))&(!d[382]);
+ assign q[383] = (((!a[383])&(!b[383]))&((c[383])^(d[383])))|(e[383]);
+ assign q[384] = (((a[384])&(b[384]))&((c[384])&(d[384])))^(e[384]);
+ assign q[385] = ((a[385])|(!b[385]))&(!c[385]);
+ assign q[386] = ((a[386])|(b[386]))&(!c[386]);
+ assign q[387] = (((!a[387])^(b[387]))|(c[387]))^(d[387]);
+ assign q[388] = (!a[388])&(!b[388]);
+ assign q[389] = ((a[389])^(b[389]))^(!c[389]);
+ assign q[390] = (((!a[390])|(b[390]))^(c[390]))|(d[390]);
+ assign q[391] = (!a[391])^(!b[391]);
+ assign q[392] = ((!a[392])^(b[392]))|(c[392]);
+ assign q[393] = (((!a[393])&(!b[393]))^((c[393])^(d[393])))^(e[393]);
+ assign q[394] = (((!a[394])^(b[394]))|(!c[394]))|(!d[394]);
+ assign q[395] = ((!a[395])&(!b[395]))^(!c[395]);
+ assign q[396] = ((a[396])^(b[396]))|((!c[396])|(d[396]));
+ assign q[397] = (((a[397])|(!b[397]))&((!c[397])&(d[397])))&(!e[397]);
+ assign q[398] = (((a[398])&(!b[398]))^((c[398])&(d[398])))|(!e[398]);
+ assign q[399] = (((!a[399])^(!b[399]))^((c[399])&(d[399])))|(!e[399]);
+ assign q[400] = (!a[400])&(b[400]);
+ assign q[401] = (((a[401])&(!b[401]))^(!c[401]))^(!d[401]);
+ assign q[402] = ((a[402])|(!b[402]))^((!c[402])^(!d[402]));
+ assign q[403] = (((!a[403])|(!b[403]))|((c[403])|(d[403])))^(!e[403]);
+ assign q[404] = (((!a[404])^(b[404]))&((c[404])&(d[404])))^(!e[404]);
+ assign q[405] = (((!a[405])^(b[405]))&(!c[405]))&(d[405]);
+ assign q[406] = (((!a[406])|(b[406]))|((c[406])^(!d[406])))&(!e[406]);
+ assign q[407] = (!a[407])|(b[407]);
+ assign q[408] = (((!a[408])&(!b[408]))|(!c[408]))&(!d[408]);
+ assign q[409] = (!a[409])^(!b[409]);
+ assign q[410] = (((!a[410])|(b[410]))|((!c[410])|(d[410])))|(!e[410]);
+ assign q[411] = (((!a[411])^(b[411]))|((c[411])&(d[411])))|(e[411]);
+ assign q[412] = ((!a[412])&(!b[412]))&((c[412])|(d[412]));
+ assign q[413] = (((!a[413])^(b[413]))^((c[413])&(!d[413])))&(!e[413]);
+ assign q[414] = (a[414])^(!b[414]);
+ assign q[415] = (((!a[415])^(b[415]))&(c[415]))|(!d[415]);
+ assign q[416] = ((!a[416])|(!b[416]))&(c[416]);
+ assign q[417] = (((!a[417])^(!b[417]))^((c[417])^(d[417])))|(!e[417]);
+ assign q[418] = ((!a[418])&(!b[418]))^((!c[418])&(!d[418]));
+ assign q[419] = (!a[419])&(!b[419]);
+ assign q[420] = ((a[420])^(!b[420]))|(!c[420]);
+ assign q[421] = ((!a[421])&(!b[421]))&((!c[421])^(d[421]));
+ assign q[422] = ((!a[422])^(b[422]))^((!c[422])&(!d[422]));
+ assign q[423] = (((a[423])|(b[423]))^((c[423])&(d[423])))^(!e[423]);
+ assign q[424] = (a[424])|(b[424]);
+ assign q[425] = (!a[425])^(b[425]);
+ assign q[426] = (!a[426])^(!b[426]);
+ assign q[427] = ((a[427])&(!b[427]))^((!c[427])^(!d[427]));
+ assign q[428] = (((!a[428])&(!b[428]))^(!c[428]))^(d[428]);
+ assign q[429] = (((!a[429])^(b[429]))&(c[429]))&(d[429]);
+ assign q[430] = ((!a[430])&(b[430]))^((c[430])^(d[430]));
+ assign q[431] = (((!a[431])|(b[431]))^((!c[431])|(d[431])))&(e[431]);
+ assign q[432] = (((!a[432])|(!b[432]))|((!c[432])^(d[432])))|(!e[432]);
+ assign q[433] = (((a[433])^(!b[433]))&(!c[433]))&(d[433]);
+ assign q[434] = ((!a[434])&(!b[434]))|((c[434])|(!d[434]));
+ assign q[435] = (!a[435])|(!b[435]);
+ assign q[436] = (((!a[436])^(!b[436]))&((!c[436])|(!d[436])))&(e[436]);
+ assign q[437] = (((!a[437])^(!b[437]))^(!c[437]))&(!d[437]);
+ assign q[438] = (!a[438])^(b[438]);
+ assign q[439] = ((a[439])^(!b[439]))|(c[439]);
+ assign q[440] = ((a[440])^(!b[440]))|((!c[440])&(!d[440]));
+ assign q[441] = (((a[441])&(b[441]))^((c[441])&(d[441])))|(e[441]);
+ assign q[442] = (!a[442])|(b[442]);
+ assign q[443] = (!a[443])^(b[443]);
+ assign q[444] = ((a[444])^(!b[444]))|((c[444])&(d[444]));
+ assign q[445] = (((a[445])|(!b[445]))&(c[445]))|(d[445]);
+ assign q[446] = ((a[446])&(b[446]))^((c[446])^(!d[446]));
+ assign q[447] = ((!a[447])&(!b[447]))^(!c[447]);
+ assign q[448] = (((!a[448])^(b[448]))&(c[448]))|(!d[448]);
+ assign q[449] = (((a[449])|(!b[449]))|((c[449])&(d[449])))|(!e[449]);
+ assign q[450] = (((!a[450])|(b[450]))|(c[450]))^(!d[450]);
+ assign q[451] = ((a[451])^(b[451]))|((c[451])^(d[451]));
+ assign q[452] = (((a[452])^(!b[452]))|(c[452]))|(d[452]);
+ assign q[453] = (!a[453])^(!b[453]);
+ assign q[454] = (((a[454])|(!b[454]))|(c[454]))^(d[454]);
+ assign q[455] = ((!a[455])&(b[455]))^((!c[455])|(!d[455]));
+ assign q[456] = (((a[456])^(!b[456]))|((c[456])^(d[456])))^(e[456]);
+ assign q[457] = (((a[457])&(!b[457]))^(c[457]))|(d[457]);
+ assign q[458] = (((!a[458])^(b[458]))^(c[458]))&(!d[458]);
+ assign q[459] = (((!a[459])&(b[459]))^((!c[459])&(!d[459])))&(e[459]);
+ assign q[460] = ((!a[460])^(!b[460]))|((c[460])&(!d[460]));
+ assign q[461] = ((a[461])&(!b[461]))&(c[461]);
+ assign q[462] = (((a[462])|(b[462]))^((c[462])^(d[462])))|(!e[462]);
+ assign q[463] = (((a[463])|(!b[463]))&((!c[463])|(d[463])))|(e[463]);
+ assign q[464] = (((!a[464])^(b[464]))&((!c[464])|(!d[464])))^(e[464]);
+ assign q[465] = ((!a[465])|(b[465]))&((c[465])&(d[465]));
+ assign q[466] = (((!a[466])^(b[466]))|((!c[466])&(d[466])))&(e[466]);
+ assign q[467] = (((!a[467])|(!b[467]))&((!c[467])&(!d[467])))^(!e[467]);
+ assign q[468] = ((!a[468])^(!b[468]))&((c[468])&(!d[468]));
+ assign q[469] = (((a[469])^(b[469]))^(c[469]))&(!d[469]);
+ assign q[470] = (((a[470])&(b[470]))^(c[470]))&(d[470]);
+ assign q[471] = (((!a[471])&(b[471]))^(c[471]))&(!d[471]);
+ assign q[472] = (((!a[472])|(b[472]))|((!c[472])|(!d[472])))|(!e[472]);
+ assign q[473] = (((a[473])|(b[473]))|((c[473])^(d[473])))|(e[473]);
+ assign q[474] = (a[474])^(!b[474]);
+ assign q[475] = (a[475])&(!b[475]);
+ assign q[476] = (((a[476])^(!b[476]))&((c[476])&(d[476])))|(!e[476]);
+ assign q[477] = ((a[477])^(b[477]))&(!c[477]);
+ assign q[478] = (((a[478])|(!b[478]))&((c[478])^(d[478])))|(e[478]);
+ assign q[479] = (((a[479])|(!b[479]))&((c[479])&(!d[479])))|(!e[479]);
+ assign q[480] = (((!a[480])|(b[480]))&((!c[480])|(!d[480])))|(e[480]);
+ assign q[481] = (((!a[481])&(b[481]))|((!c[481])^(d[481])))&(!e[481]);
+ assign q[482] = (a[482])^(!b[482]);
+ assign q[483] = (a[483])|(b[483]);
+ assign q[484] = (((a[484])|(!b[484]))&(c[484]))|(!d[484]);
+ assign q[485] = (((a[485])^(!b[485]))&(c[485]))|(!d[485]);
+ assign q[486] = ((!a[486])^(b[486]))&(c[486]);
+ assign q[487] = ((!a[487])&(b[487]))^((!c[487])^(!d[487]));
+ assign q[488] = ((a[488])&(b[488]))^((c[488])^(d[488]));
+ assign q[489] = (a[489])^(!b[489]);
+ assign q[490] = (((!a[490])^(b[490]))&(!c[490]))|(!d[490]);
+ assign q[491] = (a[491])^(!b[491]);
+ assign q[492] = (!a[492])|(!b[492]);
+ assign q[493] = (((!a[493])|(!b[493]))|((c[493])^(d[493])))^(e[493]);
+ assign q[494] = (((a[494])&(b[494]))^((c[494])&(!d[494])))&(e[494]);
+ assign q[495] = (((a[495])|(!b[495]))|((!c[495])^(d[495])))^(!e[495]);
+ assign q[496] = (((a[496])^(b[496]))&((!c[496])^(!d[496])))&(!e[496]);
+ assign q[497] = (((a[497])^(!b[497]))|((!c[497])&(d[497])))|(e[497]);
+ assign q[498] = (((!a[498])|(!b[498]))&(c[498]))&(!d[498]);
+ assign q[499] = (((a[499])|(b[499]))^((c[499])^(!d[499])))|(!e[499]);
+ assign q[500] = ((a[500])&(b[500]))^((!c[500])^(!d[500]));
+ assign q[501] = (((a[501])&(!b[501]))|(!c[501]))|(!d[501]);
+ assign q[502] = (((a[502])^(!b[502]))^(!c[502]))|(!d[502]);
+ assign q[503] = (((!a[503])&(b[503]))|(!c[503]))^(!d[503]);
+ assign q[504] = (((a[504])&(b[504]))|(c[504]))|(d[504]);
+ assign q[505] = (((!a[505])&(b[505]))&((c[505])&(!d[505])))^(!e[505]);
+ assign q[506] = (((!a[506])|(b[506]))|(c[506]))&(!d[506]);
+ assign q[507] = (((!a[507])^(b[507]))^(c[507]))&(d[507]);
+ assign q[508] = (((!a[508])&(b[508]))|((!c[508])|(d[508])))|(!e[508]);
+ assign q[509] = (!a[509])|(b[509]);
+ assign q[510] = (((a[510])|(!b[510]))^(c[510]))^(d[510]);
+ assign q[511] = ((!a[511])|(!b[511]))|((c[511])|(d[511]));
+ assign q[512] = ((a[512])|(!b[512]))&((!c[512])&(d[512]));
+ assign q[513] = (!a[513])&(!b[513]);
+ assign q[514] = (((a[514])|(!b[514]))^(!c[514]))&(d[514]);
+ assign q[515] = (((!a[515])|(!b[515]))^(c[515]))|(!d[515]);
+ assign q[516] = ((a[516])|(b[516]))|((c[516])&(!d[516]));
+ assign q[517] = (((a[517])^(!b[517]))^((c[517])&(!d[517])))&(e[517]);
+ assign q[518] = (((a[518])&(!b[518]))^((c[518])|(!d[518])))^(!e[518]);
+ assign q[519] = (((!a[519])^(!b[519]))&((c[519])&(d[519])))|(e[519]);
+ assign q[520] = ((a[520])^(b[520]))|((c[520])&(!d[520]));
+ assign q[521] = (((!a[521])^(!b[521]))^((!c[521])|(!d[521])))|(e[521]);
+ assign q[522] = (((a[522])|(b[522]))|(c[522]))&(!d[522]);
+ assign q[523] = (((a[523])|(b[523]))^((c[523])|(!d[523])))|(e[523]);
+ assign q[524] = ((!a[524])^(b[524]))&(c[524]);
+ assign q[525] = (a[525])&(b[525]);
+ assign q[526] = ((a[526])|(!b[526]))^((!c[526])^(!d[526]));
+ assign q[527] = ((!a[527])&(!b[527]))&((!c[527])|(!d[527]));
+ assign q[528] = ((a[528])^(b[528]))&(!c[528]);
+ assign q[529] = ((a[529])^(b[529]))|((c[529])|(!d[529]));
+ assign q[530] = ((!a[530])&(b[530]))|((c[530])&(!d[530]));
+ assign q[531] = (a[531])|(b[531]);
+ assign q[532] = (((!a[532])|(b[532]))&(c[532]))|(d[532]);
+ assign q[533] = ((a[533])&(!b[533]))&((c[533])&(!d[533]));
+ assign q[534] = (((a[534])&(!b[534]))&(!c[534]))|(d[534]);
+ assign q[535] = ((!a[535])^(b[535]))|((c[535])&(!d[535]));
+ assign q[536] = (((a[536])&(!b[536]))|((c[536])|(!d[536])))|(!e[536]);
+ assign q[537] = ((!a[537])^(b[537]))^((c[537])&(!d[537]));
+ assign q[538] = (((!a[538])&(b[538]))&(c[538]))|(d[538]);
+ assign q[539] = (a[539])|(!b[539]);
+ assign q[540] = (((!a[540])|(!b[540]))^((!c[540])|(d[540])))&(!e[540]);
+ assign q[541] = ((!a[541])&(!b[541]))&((c[541])^(d[541]));
+ assign q[542] = (((a[542])|(!b[542]))^(!c[542]))&(d[542]);
+ assign q[543] = (((!a[543])&(b[543]))&(!c[543]))^(d[543]);
+ assign q[544] = (((!a[544])|(b[544]))&((!c[544])&(d[544])))&(e[544]);
+ assign q[545] = (((a[545])^(!b[545]))|(!c[545]))&(d[545]);
+ assign q[546] = (((!a[546])|(!b[546]))^((!c[546])|(d[546])))&(!e[546]);
+ assign q[547] = (((a[547])^(!b[547]))|(c[547]))|(!d[547]);
+ assign q[548] = (((!a[548])^(b[548]))&((c[548])|(!d[548])))&(!e[548]);
+ assign q[549] = ((a[549])|(!b[549]))^((!c[549])^(d[549]));
+ assign q[550] = ((!a[550])&(!b[550]))^(c[550]);
+ assign q[551] = (((!a[551])&(b[551]))|((c[551])&(!d[551])))&(!e[551]);
+ assign q[552] = (((a[552])|(b[552]))^((!c[552])|(!d[552])))&(!e[552]);
+ assign q[553] = (((a[553])|(b[553]))|((!c[553])|(d[553])))&(e[553]);
+ assign q[554] = (((a[554])&(!b[554]))^(!c[554]))^(d[554]);
+ assign q[555] = ((!a[555])^(b[555]))|(!c[555]);
+ assign q[556] = (((!a[556])^(!b[556]))^(!c[556]))|(d[556]);
+ assign q[557] = ((a[557])&(!b[557]))|((c[557])&(d[557]));
+ assign q[558] = (((a[558])&(!b[558]))^((!c[558])^(!d[558])))^(!e[558]);
+ assign q[559] = (((!a[559])|(!b[559]))|((!c[559])|(!d[559])))^(!e[559]);
+ assign q[560] = ((!a[560])|(!b[560]))|((!c[560])^(d[560]));
+ assign q[561] = (((!a[561])|(b[561]))|(c[561]))^(!d[561]);
+ assign q[562] = ((!a[562])&(!b[562]))&((!c[562])^(!d[562]));
+ assign q[563] = (((a[563])^(b[563]))^(!c[563]))|(d[563]);
+ assign q[564] = (((!a[564])|(b[564]))|(!c[564]))|(d[564]);
+ assign q[565] = (((a[565])&(!b[565]))&((c[565])|(d[565])))|(!e[565]);
+ assign q[566] = (((a[566])&(b[566]))^(!c[566]))|(!d[566]);
+ assign q[567] = (((!a[567])&(!b[567]))&((c[567])&(!d[567])))|(!e[567]);
+ assign q[568] = (((!a[568])|(!b[568]))|(!c[568]))&(!d[568]);
+ assign q[569] = (!a[569])&(b[569]);
+ assign q[570] = ((!a[570])|(b[570]))|((!c[570])|(!d[570]));
+ assign q[571] = (((a[571])|(b[571]))&((!c[571])|(!d[571])))&(!e[571]);
+ assign q[572] = ((!a[572])&(b[572]))|((c[572])|(!d[572]));
+ assign q[573] = ((a[573])^(!b[573]))|((!c[573])|(!d[573]));
+ assign q[574] = (((!a[574])|(b[574]))&((!c[574])&(!d[574])))&(!e[574]);
+ assign q[575] = (((!a[575])&(b[575]))&((!c[575])|(!d[575])))|(!e[575]);
+ assign q[576] = (((a[576])|(!b[576]))^((c[576])^(d[576])))|(e[576]);
+ assign q[577] = (((a[577])|(b[577]))&(c[577]))^(d[577]);
+ assign q[578] = ((a[578])^(!b[578]))&(!c[578]);
+ assign q[579] = (((!a[579])&(!b[579]))^((!c[579])|(!d[579])))|(!e[579]);
+ assign q[580] = (((!a[580])|(b[580]))|(!c[580]))^(d[580]);
+ assign q[581] = ((a[581])&(b[581]))&((!c[581])|(d[581]));
+ assign q[582] = (((!a[582])^(b[582]))|(!c[582]))&(!d[582]);
+ assign q[583] = (a[583])&(b[583]);
+ assign q[584] = (((!a[584])|(b[584]))|((c[584])^(d[584])))^(e[584]);
+ assign q[585] = ((a[585])&(b[585]))|((!c[585])|(!d[585]));
+ assign q[586] = (((a[586])|(b[586]))^((!c[586])|(d[586])))^(!e[586]);
+ assign q[587] = ((a[587])|(!b[587]))&(!c[587]);
+ assign q[588] = (((!a[588])&(b[588]))^((!c[588])|(!d[588])))|(!e[588]);
+ assign q[589] = (((!a[589])|(b[589]))&((!c[589])|(d[589])))&(e[589]);
+ assign q[590] = (((a[590])^(b[590]))^((!c[590])&(d[590])))&(!e[590]);
+ assign q[591] = ((a[591])^(!b[591]))|(!c[591]);
+ assign q[592] = ((a[592])|(!b[592]))^((!c[592])^(!d[592]));
+ assign q[593] = ((!a[593])|(b[593]))&((c[593])&(!d[593]));
+ assign q[594] = ((!a[594])&(!b[594]))^(!c[594]);
+ assign q[595] = (((!a[595])^(b[595]))|(!c[595]))&(d[595]);
+ assign q[596] = (((a[596])|(!b[596]))&(!c[596]))|(!d[596]);
+ assign q[597] = (a[597])&(!b[597]);
+ assign q[598] = ((a[598])^(b[598]))|((!c[598])&(d[598]));
+ assign q[599] = ((a[599])&(b[599]))&(!c[599]);
+ assign q[600] = ((!a[600])|(b[600]))|((!c[600])^(!d[600]));
+ assign q[601] = ((a[601])&(!b[601]))|((c[601])^(!d[601]));
+ assign q[602] = ((!a[602])&(!b[602]))^(!c[602]);
+ assign q[603] = ((a[603])&(!b[603]))^((c[603])&(!d[603]));
+ assign q[604] = ((a[604])&(!b[604]))&((c[604])^(!d[604]));
+ assign q[605] = (((!a[605])|(b[605]))&((c[605])|(d[605])))|(e[605]);
+ assign q[606] = (((a[606])|(!b[606]))|((!c[606])^(d[606])))&(e[606]);
+ assign q[607] = ((a[607])&(!b[607]))^(!c[607]);
+ assign q[608] = ((a[608])^(!b[608]))&(!c[608]);
+ assign q[609] = ((a[609])^(!b[609]))&((!c[609])&(d[609]));
+ assign q[610] = ((!a[610])&(!b[610]))&(c[610]);
+ assign q[611] = (((!a[611])|(b[611]))&(!c[611]))|(!d[611]);
+ assign q[612] = (((a[612])^(!b[612]))&((!c[612])|(d[612])))^(e[612]);
+ assign q[613] = (((!a[613])|(b[613]))^((c[613])&(!d[613])))|(!e[613]);
+ assign q[614] = (a[614])^(!b[614]);
+ assign q[615] = (((!a[615])^(b[615]))|(!c[615]))^(d[615]);
+ assign q[616] = ((!a[616])&(!b[616]))|((c[616])&(!d[616]));
+ assign q[617] = (((a[617])^(b[617]))|(c[617]))|(d[617]);
+ assign q[618] = (((!a[618])^(!b[618]))^((c[618])^(d[618])))^(e[618]);
+ assign q[619] = (((!a[619])|(!b[619]))|(c[619]))^(!d[619]);
+ assign q[620] = (!a[620])^(!b[620]);
+ assign q[621] = ((!a[621])&(!b[621]))&((!c[621])|(d[621]));
+ assign q[622] = (((a[622])^(b[622]))&((!c[622])|(!d[622])))|(!e[622]);
+ assign q[623] = (((a[623])&(!b[623]))^(c[623]))&(d[623]);
+ assign q[624] = (((a[624])&(b[624]))|(c[624]))^(!d[624]);
+ assign q[625] = (((!a[625])^(!b[625]))&((!c[625])|(d[625])))&(!e[625]);
+ assign q[626] = (((!a[626])&(!b[626]))^(!c[626]))|(!d[626]);
+ assign q[627] = ((!a[627])|(b[627]))|(c[627]);
+ assign q[628] = (((!a[628])&(!b[628]))^((!c[628])|(!d[628])))^(e[628]);
+ assign q[629] = ((a[629])&(!b[629]))|((c[629])^(d[629]));
+ assign q[630] = (((!a[630])|(b[630]))^((c[630])|(!d[630])))|(!e[630]);
+ assign q[631] = (((!a[631])&(b[631]))&(!c[631]))^(!d[631]);
+ assign q[632] = (((a[632])&(!b[632]))&(!c[632]))|(!d[632]);
+ assign q[633] = (((a[633])|(b[633]))^(c[633]))|(d[633]);
+ assign q[634] = (((a[634])&(b[634]))|((c[634])|(d[634])))&(e[634]);
+ assign q[635] = (((a[635])&(!b[635]))&((c[635])&(!d[635])))&(!e[635]);
+ assign q[636] = (((!a[636])|(b[636]))^((!c[636])^(d[636])))^(e[636]);
+ assign q[637] = (((a[637])&(b[637]))&((!c[637])&(d[637])))|(!e[637]);
+ assign q[638] = ((!a[638])|(!b[638]))&(!c[638]);
+ assign q[639] = (((a[639])|(!b[639]))&((c[639])|(d[639])))^(!e[639]);
+ assign q[640] = (!a[640])&(b[640]);
+ assign q[641] = ((!a[641])^(!b[641]))^((!c[641])^(d[641]));
+ assign q[642] = (((!a[642])^(!b[642]))&(c[642]))&(!d[642]);
+ assign q[643] = (!a[643])^(!b[643]);
+ assign q[644] = ((!a[644])|(!b[644]))|((!c[644])^(!d[644]));
+ assign q[645] = (((a[645])&(b[645]))^((c[645])&(!d[645])))|(e[645]);
+ assign q[646] = ((a[646])&(!b[646]))&(c[646]);
+ assign q[647] = ((a[647])&(!b[647]))^((!c[647])^(!d[647]));
+ assign q[648] = (((!a[648])|(b[648]))&((!c[648])&(d[648])))|(e[648]);
+ assign q[649] = ((!a[649])|(b[649]))|((c[649])&(!d[649]));
+ assign q[650] = (((!a[650])&(b[650]))^(c[650]))^(d[650]);
+ assign q[651] = ((a[651])|(b[651]))^(!c[651]);
+ assign q[652] = (((a[652])^(b[652]))&((c[652])|(d[652])))|(e[652]);
+ assign q[653] = (((!a[653])|(b[653]))^(c[653]))^(d[653]);
+ assign q[654] = (((a[654])^(!b[654]))^(!c[654]))^(d[654]);
+ assign q[655] = (((!a[655])|(b[655]))|((!c[655])&(d[655])))&(e[655]);
+ assign q[656] = (((a[656])^(b[656]))|((!c[656])^(!d[656])))^(!e[656]);
+ assign q[657] = ((a[657])&(!b[657]))&(c[657]);
+ assign q[658] = (((!a[658])|(b[658]))|((!c[658])^(!d[658])))|(e[658]);
+ assign q[659] = (((a[659])&(b[659]))&((c[659])|(!d[659])))^(e[659]);
+ assign q[660] = (((!a[660])&(!b[660]))|((!c[660])|(!d[660])))&(e[660]);
+ assign q[661] = ((a[661])&(!b[661]))^((!c[661])^(!d[661]));
+ assign q[662] = (((!a[662])|(!b[662]))|((c[662])|(!d[662])))^(!e[662]);
+ assign q[663] = (a[663])^(b[663]);
+ assign q[664] = ((!a[664])&(!b[664]))|((!c[664])&(!d[664]));
+ assign q[665] = (((a[665])|(b[665]))&((!c[665])&(!d[665])))^(e[665]);
+ assign q[666] = (((a[666])&(b[666]))|((c[666])|(d[666])))|(!e[666]);
+ assign q[667] = ((a[667])&(!b[667]))&(!c[667]);
+ assign q[668] = (((!a[668])&(b[668]))^(c[668]))|(d[668]);
+ assign q[669] = (((!a[669])^(b[669]))^((!c[669])^(!d[669])))&(e[669]);
+ assign q[670] = ((!a[670])|(b[670]))&((c[670])|(!d[670]));
+ assign q[671] = (((a[671])&(!b[671]))^(c[671]))^(!d[671]);
+ assign q[672] = (((a[672])^(b[672]))^((c[672])&(!d[672])))|(!e[672]);
+ assign q[673] = (((a[673])^(!b[673]))&((c[673])|(d[673])))|(!e[673]);
+ assign q[674] = ((!a[674])|(!b[674]))|((!c[674])^(d[674]));
+ assign q[675] = ((!a[675])^(b[675]))&((!c[675])|(!d[675]));
+ assign q[676] = (((!a[676])&(!b[676]))^((!c[676])&(d[676])))|(!e[676]);
+ assign q[677] = (((!a[677])&(!b[677]))^(c[677]))&(!d[677]);
+ assign q[678] = (((!a[678])|(!b[678]))&((c[678])^(!d[678])))&(e[678]);
+ assign q[679] = (!a[679])|(b[679]);
+ assign q[680] = (a[680])&(!b[680]);
+ assign q[681] = (((!a[681])|(b[681]))|((c[681])&(d[681])))|(!e[681]);
+ assign q[682] = ((a[682])&(!b[682]))^((!c[682])|(!d[682]));
+ assign q[683] = ((!a[683])&(!b[683]))|((!c[683])^(!d[683]));
+ assign q[684] = (!a[684])&(!b[684]);
+ assign q[685] = (((a[685])&(!b[685]))|((c[685])&(!d[685])))|(!e[685]);
+ assign q[686] = (a[686])^(!b[686]);
+ assign q[687] = (((!a[687])|(b[687]))&((!c[687])|(d[687])))^(e[687]);
+ assign q[688] = (((a[688])^(!b[688]))^((!c[688])&(!d[688])))&(!e[688]);
+ assign q[689] = (((!a[689])^(b[689]))^(c[689]))&(!d[689]);
+ assign q[690] = ((a[690])^(!b[690]))|((!c[690])|(!d[690]));
+ assign q[691] = (((!a[691])^(b[691]))&((!c[691])&(!d[691])))^(!e[691]);
+ assign q[692] = ((a[692])^(!b[692]))|((c[692])|(!d[692]));
+ assign q[693] = (((a[693])&(b[693]))&((!c[693])|(d[693])))^(e[693]);
+ assign q[694] = ((!a[694])^(!b[694]))^((c[694])^(!d[694]));
+ assign q[695] = ((a[695])&(b[695]))&((!c[695])|(!d[695]));
+ assign q[696] = ((a[696])|(b[696]))&((c[696])|(d[696]));
+ assign q[697] = (((!a[697])^(b[697]))|((c[697])^(!d[697])))|(e[697]);
+ assign q[698] = (((a[698])|(b[698]))|((!c[698])&(!d[698])))^(!e[698]);
+ assign q[699] = (((!a[699])|(!b[699]))&(c[699]))|(!d[699]);
+ assign q[700] = ((!a[700])&(b[700]))|((!c[700])|(d[700]));
+ assign q[701] = (((!a[701])|(b[701]))|((c[701])^(d[701])))&(e[701]);
+ assign q[702] = (((!a[702])&(b[702]))&(c[702]))&(!d[702]);
+ assign q[703] = ((!a[703])&(!b[703]))|((c[703])|(d[703]));
+ assign q[704] = (((a[704])^(b[704]))^((c[704])&(d[704])))|(!e[704]);
+ assign q[705] = ((a[705])^(!b[705]))^((!c[705])^(!d[705]));
+ assign q[706] = (((!a[706])^(b[706]))^((!c[706])&(!d[706])))&(e[706]);
+ assign q[707] = ((a[707])&(!b[707]))|((c[707])^(d[707]));
+ assign q[708] = (((a[708])^(b[708]))|(!c[708]))|(d[708]);
+ assign q[709] = (((!a[709])&(b[709]))^((!c[709])&(!d[709])))&(!e[709]);
+ assign q[710] = ((!a[710])^(!b[710]))^(c[710]);
+ assign q[711] = (!a[711])&(b[711]);
+ assign q[712] = ((a[712])^(b[712]))&((c[712])^(!d[712]));
+ assign q[713] = (((a[713])^(b[713]))|((!c[713])^(d[713])))|(!e[713]);
+ assign q[714] = (((a[714])|(b[714]))&((c[714])^(d[714])))^(!e[714]);
+ assign q[715] = ((a[715])|(b[715]))|((!c[715])^(d[715]));
+ assign q[716] = (((a[716])|(b[716]))^(c[716]))^(!d[716]);
+ assign q[717] = (((!a[717])|(!b[717]))^((!c[717])^(!d[717])))^(e[717]);
+ assign q[718] = (((a[718])^(!b[718]))&(!c[718]))^(d[718]);
+ assign q[719] = (((!a[719])^(!b[719]))&((!c[719])|(d[719])))&(!e[719]);
+ assign q[720] = ((!a[720])^(b[720]))|(c[720]);
+ assign q[721] = ((!a[721])&(!b[721]))|((c[721])&(d[721]));
+ assign q[722] = (((!a[722])|(!b[722]))&((!c[722])&(!d[722])))&(!e[722]);
+ assign q[723] = ((a[723])|(b[723]))&((c[723])|(d[723]));
+ assign q[724] = (((!a[724])|(b[724]))^((c[724])^(!d[724])))^(e[724]);
+ assign q[725] = (((!a[725])^(!b[725]))|(!c[725]))&(!d[725]);
+ assign q[726] = ((a[726])^(!b[726]))^(c[726]);
+ assign q[727] = ((!a[727])&(!b[727]))^(c[727]);
+ assign q[728] = ((!a[728])^(!b[728]))^(c[728]);
+ assign q[729] = ((!a[729])&(b[729]))&(!c[729]);
+ assign q[730] = (((a[730])|(!b[730]))&(!c[730]))&(!d[730]);
+ assign q[731] = ((!a[731])|(!b[731]))^(c[731]);
+ assign q[732] = ((!a[732])&(!b[732]))|(c[732]);
+ assign q[733] = ((!a[733])&(!b[733]))^(!c[733]);
+ assign q[734] = (((a[734])|(b[734]))|((!c[734])^(!d[734])))|(!e[734]);
+ assign q[735] = (a[735])^(b[735]);
+ assign q[736] = ((!a[736])|(b[736]))&(!c[736]);
+ assign q[737] = (((!a[737])|(b[737]))|(c[737]))&(!d[737]);
+ assign q[738] = (((a[738])^(b[738]))^((c[738])^(!d[738])))|(e[738]);
+ assign q[739] = (!a[739])^(b[739]);
+ assign q[740] = (((a[740])|(b[740]))^((!c[740])^(!d[740])))&(!e[740]);
+ assign q[741] = ((!a[741])&(b[741]))^((!c[741])^(!d[741]));
+ assign q[742] = (((a[742])|(b[742]))|(c[742]))|(d[742]);
+ assign q[743] = (((a[743])&(b[743]))&((c[743])&(d[743])))|(!e[743]);
+ assign q[744] = (((!a[744])&(!b[744]))^((!c[744])&(d[744])))^(e[744]);
+ assign q[745] = (((!a[745])&(b[745]))^((!c[745])|(!d[745])))^(e[745]);
+ assign q[746] = (((a[746])&(b[746]))^(!c[746]))&(!d[746]);
+ assign q[747] = (((!a[747])^(b[747]))^((!c[747])^(d[747])))|(e[747]);
+ assign q[748] = (((a[748])^(b[748]))|((c[748])^(d[748])))&(!e[748]);
+ assign q[749] = (((a[749])^(b[749]))|((c[749])|(!d[749])))|(e[749]);
+endmodule
diff --git a/tests/arch/gatemate/luttrees.ys b/tests/arch/gatemate/luttrees.ys
new file mode 100644
index 000000000..545643226
--- /dev/null
+++ b/tests/arch/gatemate/luttrees.ys
@@ -0,0 +1,13 @@
+
+read_verilog luttrees.v
+design -save read
+
+hierarchy -top luttrees
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad -luttree -nomx4 -nomx8 # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd luttrees # Constrain all select calls below inside the top module
+
+select -assert-count 750 t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %%
+select -assert-none t:CC_LUT2 t:CC_L2T4 t:CC_L2T5 %% t:* %D
+