aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/test-linux.yml9
-rw-r--r--.github/workflows/test-macos.yml29
-rw-r--r--.github/workflows/vs.yml2
-rw-r--r--CHANGELOG42
-rw-r--r--CODEOWNERS1
-rw-r--r--Makefile17
-rw-r--r--README.md23
-rw-r--r--backends/aiger/aiger.cc25
-rw-r--r--backends/btor/btor.cc9
-rw-r--r--backends/cxxrtl/cxxrtl.h36
-rw-r--r--backends/cxxrtl/cxxrtl_backend.cc18
-rw-r--r--backends/firrtl/firrtl.cc6
-rw-r--r--backends/json/json.cc19
-rw-r--r--backends/smt2/smt2.cc11
-rw-r--r--backends/smt2/smtbmc.py7
-rw-r--r--backends/smt2/smtio.py10
-rw-r--r--backends/smv/smv.cc5
-rw-r--r--backends/verilog/verilog_backend.cc6
-rw-r--r--examples/smtbmc/Makefile6
-rwxr-xr-xexamples/smtbmc/glift/C7552.v4194
-rw-r--r--examples/smtbmc/glift/C7552.ys41
-rwxr-xr-xexamples/smtbmc/glift/C880.v451
-rw-r--r--examples/smtbmc/glift/C880.ys41
-rwxr-xr-xexamples/smtbmc/glift/alu2.v400
-rw-r--r--examples/smtbmc/glift/alu2.ys41
-rwxr-xr-xexamples/smtbmc/glift/alu4.v802
-rw-r--r--examples/smtbmc/glift/alu4.ys41
-rw-r--r--examples/smtbmc/glift/mux2.ys40
-rwxr-xr-xexamples/smtbmc/glift/t481.v83
-rw-r--r--examples/smtbmc/glift/t481.ys41
-rwxr-xr-xexamples/smtbmc/glift/too_large.v345
-rw-r--r--examples/smtbmc/glift/too_large.ys41
-rwxr-xr-xexamples/smtbmc/glift/ttt2.v220
-rw-r--r--examples/smtbmc/glift/ttt2.ys41
-rwxr-xr-xexamples/smtbmc/glift/x1.v380
-rw-r--r--examples/smtbmc/glift/x1.ys41
-rw-r--r--frontends/ast/ast.cc2
-rw-r--r--frontends/ast/ast.h1
-rw-r--r--frontends/ast/genrtlil.cc2
-rw-r--r--frontends/ast/simplify.cc86
-rw-r--r--frontends/json/jsonparse.cc34
-rw-r--r--frontends/verific/verific.cc69
-rw-r--r--frontends/verilog/verilog_lexer.l15
-rw-r--r--frontends/verilog/verilog_parser.y5
-rw-r--r--guidelines/Windows23
-rw-r--r--kernel/calc.cc51
-rw-r--r--kernel/celledges.cc40
-rw-r--r--kernel/celltypes.h29
-rw-r--r--kernel/consteval.h35
-rw-r--r--kernel/fstdata.cc219
-rw-r--r--kernel/fstdata.h83
-rw-r--r--kernel/mem.cc312
-rw-r--r--kernel/mem.h30
-rw-r--r--kernel/qcsat.cc2
-rw-r--r--kernel/rtlil.cc52
-rw-r--r--kernel/rtlil.h7
-rw-r--r--kernel/satgen.cc100
-rw-r--r--kernel/yosys.cc17
-rw-r--r--kernel/yosys.h3
-rw-r--r--libs/fst/block_format.txt130
-rw-r--r--libs/fst/config.h27
-rw-r--r--libs/fst/fastlz.cc528
-rw-r--r--libs/fst/fastlz.h109
-rw-r--r--libs/fst/fstapi.cc6546
-rw-r--r--libs/fst/fstapi.h500
-rw-r--r--libs/fst/lz4.cc1615
-rw-r--r--libs/fst/lz4.h367
-rw-r--r--manual/PRESENTATION_Prog/Makefile2
-rw-r--r--manual/command-reference-manual.tex161
-rw-r--r--misc/create_vcxsrc.sh11
-rw-r--r--passes/cmds/Makefile.inc1
-rw-r--r--passes/cmds/clean_zerowidth.cc2
-rw-r--r--passes/cmds/glift.cc599
-rw-r--r--passes/cmds/stat.cc4
-rw-r--r--passes/memory/memory_bram.cc28
-rw-r--r--passes/opt/opt_dff.cc210
-rw-r--r--passes/opt/opt_reduce.cc397
-rw-r--r--passes/pmgen/ice40_dsp.pmg5
-rw-r--r--passes/sat/clk2fflogic.cc29
-rw-r--r--passes/sat/sim.cc1465
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc4
-rw-r--r--passes/techmap/abc9_ops.cc15
-rw-r--r--passes/techmap/bmuxmap.cc76
-rw-r--r--passes/techmap/demuxmap.cc80
-rw-r--r--passes/techmap/iopadmap.cc2
-rw-r--r--passes/techmap/simplemap.cc26
-rw-r--r--passes/tests/test_cell.cc46
-rw-r--r--techlibs/anlogic/.gitignore2
-rw-r--r--techlibs/anlogic/Makefile.inc22
-rw-r--r--techlibs/anlogic/brams.txt43
-rw-r--r--techlibs/anlogic/brams_init.py21
-rw-r--r--techlibs/anlogic/brams_map.v162
-rw-r--r--techlibs/anlogic/synth_anlogic.cc18
-rw-r--r--techlibs/common/simlib.v72
-rw-r--r--techlibs/common/techmap.v39
-rw-r--r--techlibs/ecp5/cells_sim.v45
-rw-r--r--techlibs/gowin/cells_sim.v945
-rw-r--r--techlibs/gowin/lutrams_map.v5
-rw-r--r--techlibs/intel_alm/Makefile.inc1
-rw-r--r--techlibs/intel_alm/common/bram_m10k.txt4
-rw-r--r--techlibs/intel_alm/common/bram_m10k_map.v16
-rw-r--r--techlibs/intel_alm/common/mem_sim.v2
-rw-r--r--techlibs/intel_alm/common/quartus_rename.v9
-rw-r--r--techlibs/intel_alm/synth_intel_alm.cc3
-rw-r--r--techlibs/nexus/arith_map.v2
-rw-r--r--techlibs/nexus/cells_sim.v4
-rw-r--r--techlibs/quicklogic/synth_quicklogic.cc4
-rw-r--r--techlibs/xilinx/cells_xtra.py21
-rw-r--r--techlibs/xilinx/cells_xtra.v675
-rw-r--r--tests/arch/anlogic/blockram.ys13
-rw-r--r--tests/arch/anlogic/lutram.ys2
-rw-r--r--tests/arch/gowin/lutram.ys5
-rw-r--r--tests/arch/intel_alm/blockram.ys3
-rw-r--r--tests/opt/opt_reduce_bmux.ys117
-rw-r--r--tests/opt/opt_reduce_demux.ys91
-rw-r--r--tests/sat/.gitignore2
-rw-r--r--tests/sat/alu.v79
-rw-r--r--tests/sat/grom.ys9
-rw-r--r--tests/sat/grom_computer.v31
-rw-r--r--tests/sat/grom_cpu.v747
-rw-r--r--tests/sat/ram_memory.v39
-rw-r--r--tests/sat/sim_counter.ys48
-rw-r--r--tests/sim/.gitignore6
-rw-r--r--tests/sim/adff.v7
-rw-r--r--tests/sim/adffe.v8
-rw-r--r--tests/sim/adlatch.v8
-rw-r--r--tests/sim/aldff.v7
-rw-r--r--tests/sim/aldffe.v8
-rw-r--r--tests/sim/dff.v4
-rw-r--r--tests/sim/dffe.v5
-rw-r--r--tests/sim/dffsr.v9
-rw-r--r--tests/sim/dlatch.v6
-rw-r--r--tests/sim/dlatchsr.v11
-rwxr-xr-xtests/sim/run-test.sh12
-rw-r--r--tests/sim/sdff.v7
-rw-r--r--tests/sim/sdffce.v8
-rw-r--r--tests/sim/sdffe.v8
-rw-r--r--tests/sim/sim_adff.ys6
-rw-r--r--tests/sim/sim_adffe.ys6
-rw-r--r--tests/sim/sim_adlatch.ys10
-rw-r--r--tests/sim/sim_aldff.ys6
-rw-r--r--tests/sim/sim_aldffe.ys6
-rw-r--r--tests/sim/sim_dff.ys6
-rw-r--r--tests/sim/sim_dffe.ys6
-rw-r--r--tests/sim/sim_dffsr.ys6
-rw-r--r--tests/sim/sim_dlatch.ys6
-rw-r--r--tests/sim/sim_dlatchsr.ys10
-rw-r--r--tests/sim/sim_sdff.ys6
-rw-r--r--tests/sim/sim_sdffce.ys6
-rw-r--r--tests/sim/sim_sdffe.ys6
-rwxr-xr-xtests/sim/tb/tb_adff.v40
-rwxr-xr-xtests/sim/tb/tb_adffe.v58
-rwxr-xr-xtests/sim/tb/tb_adlatch.v70
-rwxr-xr-xtests/sim/tb/tb_aldff.v73
-rwxr-xr-xtests/sim/tb/tb_aldffe.v75
-rwxr-xr-xtests/sim/tb/tb_dff.v47
-rwxr-xr-xtests/sim/tb/tb_dffe.v42
-rwxr-xr-xtests/sim/tb/tb_dffsr.v69
-rwxr-xr-xtests/sim/tb/tb_dlatch.v50
-rwxr-xr-xtests/sim/tb/tb_dlatchsr.v65
-rwxr-xr-xtests/sim/tb/tb_sdff.v48
-rwxr-xr-xtests/sim/tb/tb_sdffce.v79
-rwxr-xr-xtests/sim/tb/tb_sdffe.v70
-rw-r--r--tests/various/.gitignore1
-rw-r--r--tests/various/json_escape_chars.ys14
-rw-r--r--tests/various/param_struct.ys3
-rw-r--r--tests/various/struct_access.sv43
-rw-r--r--tests/various/struct_access.ys5
-rw-r--r--tests/verilog/delay_time_scale.ys25
-rwxr-xr-xtests/verilog/dynamic_range_lhs.sh32
-rw-r--r--tests/verilog/dynamic_range_lhs.v76
-rw-r--r--tests/verilog/func_upto.sv77
-rw-r--r--tests/verilog/func_upto.ys7
-rw-r--r--tests/verilog/struct_access.sv5
175 files changed, 25682 insertions, 621 deletions
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
index 9aa952e45..e27ea37d2 100644
--- a/.github/workflows/test-linux.yml
+++ b/.github/workflows/test-linux.yml
@@ -11,9 +11,7 @@ jobs:
- { id: ubuntu-20.04, name: focal }
compiler:
- 'clang-12'
- - 'clang-11'
- 'gcc-11'
- - 'gcc-10'
cpp_std:
- 'c++11'
- 'c++14'
@@ -21,6 +19,12 @@ jobs:
- 'c++20'
include:
# Limit the older compilers to C++11 mode
+ - os: { id: ubuntu-20.04, name: focal }
+ compiler: 'clang-11'
+ cpp_std: 'c++11'
+ - os: { id: ubuntu-20.04, name: focal }
+ compiler: 'gcc-10'
+ cpp_std: 'c++11'
- os: { id: ubuntu-18.04, name: bionic }
compiler: 'clang-3.9'
cpp_std: 'c++11'
@@ -120,6 +124,7 @@ jobs:
make -j${{ env.procs }} CCXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
- name: Run tests
+ if: (matrix.cpp_std == 'c++11') && (matrix.compiler == 'gcc-11')
shell: bash
run: |
make -j${{ env.procs }} test CXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml
index 09ab382bf..b14ce8633 100644
--- a/.github/workflows/test-macos.yml
+++ b/.github/workflows/test-macos.yml
@@ -67,6 +67,7 @@ jobs:
make -j${{ env.procs }} CXXSTD=${{ matrix.cpp_std }} CC=cc CXX=cc LD=cc
- name: Run tests
+ if: matrix.cpp_std == 'c++11'
shell: bash
run: |
make -j${{ env.procs }} test CXXSTD=${{ matrix.cpp_std }} CC=cc CXX=cc LD=cc
@@ -119,36 +120,8 @@ jobs:
- name: Checkout Yosys
uses: actions/checkout@v2
- - name: Get iverilog
- shell: bash
- run: |
- git clone https://github.com/steveicarus/iverilog.git
-
- - name: Cache iverilog
- id: cache-iverilog-homebrew
- uses: actions/cache@v2
- with:
- path: .local/
- key: ${{ matrix.os.id }}-homebrew-${{ hashFiles('iverilog/.git/refs/heads/master') }}
-
- - name: Build iverilog
- if: steps.cache-iverilog.outputs.cache-hit != 'true'
- shell: bash
- run: |
- mkdir -p $GITHUB_WORKSPACE/.local
- cd iverilog
- autoconf
- CC=gcc CXX=g++ ./configure --prefix=$GITHUB_WORKSPACE/.local
- make -j${{ env.procs }}
- make install
-
- name: Build yosys
shell: bash
run: |
make config-gcc
make -j${{ env.procs }} CXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
-
- - name: Run tests
- shell: bash
- run: |
- make -j${{ env.procs }} test CXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
diff --git a/.github/workflows/vs.yml b/.github/workflows/vs.yml
index a48821cf8..79a8401d6 100644
--- a/.github/workflows/vs.yml
+++ b/.github/workflows/vs.yml
@@ -21,7 +21,7 @@ jobs:
path: yosys-win32-vcxsrc-latest.zip
build:
- runs-on: windows-latest
+ runs-on: windows-2019
needs: yosys-vcxsrc
steps:
- uses: actions/download-artifact@v2
diff --git a/CHANGELOG b/CHANGELOG
index ff22a01e2..d6d2c4990 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,9 +2,49 @@
List of major changes and improvements between releases
=======================================================
-Yosys 0.13 .. Yosys 0.13-dev
+Yosys 0.15 .. Yosys 0.15-dev
--------------------------
+Yosys 0.14 .. Yosys 0.15
+--------------------------
+
+ * Various
+ - clk2fflogic: nice names for autogenerated signals
+ - simulation include support for all flip-flop types.
+ - Added AIGER witness file co-simulation.
+
+ * Verilog
+ - Fixed evaluation of constant functions with variables or arguments with
+ reversed dimensions
+ - Fixed elaboration of dynamic range assignments where the vector is
+ reversed or is not zero-indexed
+ - Added frontend support for time scale delay values (e.g., `#1ns`)
+
+ * SystemVerilog
+ - Added support for accessing whole sub-structures in expressions
+
+ * New commands and options
+ - Added glift command, used to create gate-level information flow tracking
+ (GLIFT) models by the "constructive mapping" approach
+
+ * Verific support
+ - Ability to override default parser mode for verific -f command.
+
+Yosys 0.13 .. Yosys 0.14
+--------------------------
+
+ * Various
+ - Added $bmux and $demux cells and related optimization patterns.
+
+ * New commands and options
+ - Added "bmuxmap" and "dmuxmap" passes
+ - Added "-fst" option to "sim" pass for writing FST files
+ - Added "-r", "-scope", "-start", "-stop", "-at", "-sim", "-sim-gate",
+ "-sim-gold" options to "sim" pass for co-simulation
+
+ * Anlogic support
+ - Added support for BRAMs
+
Yosys 0.12 .. Yosys 0.13
--------------------------
diff --git a/CODEOWNERS b/CODEOWNERS
index 19b660dff..11a8cc026 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -42,4 +42,5 @@ backends/firrtl @ucbjrl @azidar
passes/sat/qbfsat.cc @boqwxp
passes/sat/qbfsat.h @boqwxp
passes/cmds/exec.cc @boqwxp
+passes/cmds/glift.cc @boqwxp
passes/cmds/printattrs.cc @boqwxp
diff --git a/Makefile b/Makefile
index 60777c95e..ae151dfdb 100644
--- a/Makefile
+++ b/Makefile
@@ -129,12 +129,12 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.13+3
+YOSYS_VER := 0.15+57
GIT_REV := $(shell git -C $(YOSYS_SRC) rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
- sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 8b1eafc.. | wc -l`/;" Makefile
+ sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 07a4368.. | wc -l`/;" Makefile
# set 'ABCREV = default' to use abc/ as it is
#
@@ -142,7 +142,7 @@ 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 = f6fa2dd
+ABCREV = 00b674d
ABCPULL = 1
ABCURL ?= https://github.com/YosysHQ/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 VERBOSE=$(Q)
@@ -594,9 +594,11 @@ $(eval $(call add_include_file,kernel/satgen.h))
$(eval $(call add_include_file,kernel/qcsat.h))
$(eval $(call add_include_file,kernel/ff.h))
$(eval $(call add_include_file,kernel/ffinit.h))
+$(eval $(call add_include_file,kernel/fstdata.h))
$(eval $(call add_include_file,kernel/mem.h))
$(eval $(call add_include_file,libs/ezsat/ezsat.h))
$(eval $(call add_include_file,libs/ezsat/ezminisat.h))
+$(eval $(call add_include_file,libs/fst/fstapi.h))
$(eval $(call add_include_file,libs/sha1/sha1.h))
$(eval $(call add_include_file,libs/json11/json11.hpp))
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
@@ -618,7 +620,7 @@ ifneq ($(ABCEXTERNAL),)
kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
endif
endif
-OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o
+OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/fstdata.o
kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
@@ -642,6 +644,10 @@ OBJS += libs/minisat/SimpSolver.o
OBJS += libs/minisat/Solver.o
OBJS += libs/minisat/System.o
+OBJS += libs/fst/fstapi.o
+OBJS += libs/fst/fastlz.o
+OBJS += libs/fst/lz4.o
+
include $(YOSYS_SRC)/frontends/*/Makefile.inc
include $(YOSYS_SRC)/passes/*/Makefile.inc
include $(YOSYS_SRC)/backends/*/Makefile.inc
@@ -797,6 +803,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/various && bash run-test.sh
+cd tests/select && bash run-test.sh
+cd tests/sat && bash run-test.sh
+ +cd tests/sim && bash run-test.sh
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
+cd tests/svtypes && bash run-test.sh $(SEEDOPT)
+cd tests/proc && bash run-test.sh
@@ -909,7 +916,7 @@ clean:
rm -rf tests/simple/*.out tests/simple/*.log
rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp
rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log
- rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp
+ rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp tests/various/temp
rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
rm -f tests/tools/cmp_tbdata
diff --git a/README.md b/README.md
index cc5c806fb..0232a5ed0 100644
--- a/README.md
+++ b/README.md
@@ -53,8 +53,23 @@ front-end for Yosys, SymbiYosys:
- https://github.com/YosysHQ/SymbiYosys
-Setup
-======
+Installation
+============
+
+Yosys is part of the [Tabby CAD Suite](https://www.yosyshq.com/tabby-cad-datasheet) and the [OSS CAD Suite](https://github.com/YosysHQ/oss-cad-suite-build)! The easiest way to use yosys is to install the binary software suite, which contains all required dependencies and related tools.
+
+* [Contact YosysHQ](https://www.yosyshq.com/contact) for a [Tabby CAD Suite](https://www.yosyshq.com/tabby-cad-datasheet) Evaluation License and download link
+* OR go to https://github.com/YosysHQ/oss-cad-suite-build/releases to download the free OSS CAD Suite
+* Follow the [Install Instructions on GitHub](https://github.com/YosysHQ/oss-cad-suite-build#installation)
+
+Make sure to get a Tabby CAD Suite Evaluation License if you need features such as industry-grade SystemVerilog and VHDL parsers!
+
+For more information about the difference between Tabby CAD Suite and the OSS CAD Suite, please visit https://www.yosyshq.com/tabby-cad-datasheet
+
+Many Linux distributions also provide Yosys binaries, some more up to date than others. Check with your package manager!
+
+Building from Source
+====================
You need a C++ compiler with C++11 support (up-to-date CLANG or GCC is
recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.
@@ -90,10 +105,6 @@ For Cygwin use the following command to install all prerequisites, or select the
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
-There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
-as a source distribution for Visual Studio. Visit the Yosys download page for
-more information: https://yosyshq.net/yosys/download.html
-
To configure the build system to use a specific compiler, use one of
$ make config-clang
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index 35935b847..547d131ee 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -606,7 +606,7 @@ struct AigerWriter
f << stringf("c\nGenerated by %s\n", yosys_version_str);
}
- void write_map(std::ostream &f, bool verbose_map)
+ void write_map(std::ostream &f, bool verbose_map, bool no_startoffset)
{
dict<int, string> input_lines;
dict<int, string> init_lines;
@@ -627,32 +627,33 @@ struct AigerWriter
continue;
int a = aig_map.at(sig[i]);
+ int index = no_startoffset ? i : (wire->start_offset+i);
if (verbose_map)
- wire_lines[a] += stringf("wire %d %d %s\n", a, wire->start_offset+i, log_id(wire));
+ wire_lines[a] += stringf("wire %d %d %s\n", a, index, log_id(wire));
if (wire->port_input) {
log_assert((a & 1) == 0);
- input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
+ input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, log_id(wire));
}
if (wire->port_output) {
int o = ordered_outputs.at(sig[i]);
- output_lines[o] += stringf("output %d %d %s\n", o, wire->start_offset+i, log_id(wire));
+ output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire));
}
if (init_inputs.count(sig[i])) {
int a = init_inputs.at(sig[i]);
log_assert((a & 1) == 0);
- init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
+ init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, log_id(wire));
}
if (ordered_latches.count(sig[i])) {
int l = ordered_latches.at(sig[i]);
if (zinit_mode && (aig_latchinit.at(l) == 1))
- latch_lines[l] += stringf("invlatch %d %d %s\n", l, wire->start_offset+i, log_id(wire));
+ latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, log_id(wire));
else
- latch_lines[l] += stringf("latch %d %d %s\n", l, wire->start_offset+i, log_id(wire));
+ latch_lines[l] += stringf("latch %d %d %s\n", l, index, log_id(wire));
}
}
}
@@ -713,6 +714,9 @@ struct AigerBackend : public Backend {
log(" -vmap <filename>\n");
log(" like -map, but more verbose\n");
log("\n");
+ log(" -no-startoffset\n");
+ log(" make indexes zero based, enable using map files with smt solvers.\n");
+ log("\n");
log(" -I, -O, -B, -L\n");
log(" If the design contains no input/output/assert/flip-flop then create one\n");
log(" dummy input/output/bad_state-pin or latch to make the tools reading the\n");
@@ -730,6 +734,7 @@ struct AigerBackend : public Backend {
bool omode = false;
bool bmode = false;
bool lmode = false;
+ bool no_startoffset = false;
std::string map_filename;
log_header(design, "Executing AIGER backend.\n");
@@ -762,6 +767,10 @@ struct AigerBackend : public Backend {
verbose_map = true;
continue;
}
+ if (args[argidx] == "-no-startoffset") {
+ no_startoffset = true;
+ continue;
+ }
if (args[argidx] == "-I") {
imode = true;
continue;
@@ -804,7 +813,7 @@ struct AigerBackend : public Backend {
mapf.open(map_filename.c_str(), std::ofstream::trunc);
if (mapf.fail())
log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
- writer.write_map(mapf, verbose_map);
+ writer.write_map(mapf, verbose_map, no_startoffset);
}
}
} AigerBackend;
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index 96df54a2c..73e88c049 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -678,7 +678,7 @@ struct BtorWorker
int sid = get_bv_sid(GetSize(sig_y));
int nid = next_nid++;
- btorf("%d state %d\n", nid, sid);
+ btorf("%d state %d%s\n", nid, sid, getinfo(cell).c_str());
if (cell->type == ID($anyconst)) {
int nid2 = next_nid++;
@@ -699,7 +699,7 @@ struct BtorWorker
int one_nid = get_sig_nid(State::S1);
int zero_nid = get_sig_nid(State::S0);
initstate_nid = next_nid++;
- btorf("%d state %d\n", initstate_nid, sid);
+ btorf("%d state %d%s\n", initstate_nid, sid, getinfo(cell).c_str());
btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid);
btorf("%d next %d %d %d\n", next_nid++, sid, initstate_nid, zero_nid);
}
@@ -1399,6 +1399,11 @@ struct BtorBackend : public Backend {
log_header(design, "Executing BTOR backend.\n");
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ log_pop();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index 3e1357498..b4ffa87cd 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -457,6 +457,42 @@ struct value : public expr_base<value<Bits>> {
return shr<AmountBits, /*Signed=*/true>(amount);
}
+ template<size_t ResultBits, size_t SelBits>
+ value<ResultBits> bmux(const value<SelBits> &sel) const {
+ static_assert(ResultBits << SelBits == Bits, "invalid sizes used in bmux()");
+ size_t amount = sel.data[0] * ResultBits;
+ size_t shift_chunks = amount / chunk::bits;
+ size_t shift_bits = amount % chunk::bits;
+ value<ResultBits> result;
+ chunk::type carry = 0;
+ if (ResultBits % chunk::bits + shift_bits > chunk::bits)
+ carry = data[result.chunks + shift_chunks] << (chunk::bits - shift_bits);
+ for (size_t n = 0; n < result.chunks; n++) {
+ result.data[result.chunks - 1 - n] = carry | (data[result.chunks + shift_chunks - 1 - n] >> shift_bits);
+ carry = (shift_bits == 0) ? 0
+ : data[result.chunks + shift_chunks - 1 - n] << (chunk::bits - shift_bits);
+ }
+ return result;
+ }
+
+ template<size_t ResultBits, size_t SelBits>
+ value<ResultBits> demux(const value<SelBits> &sel) const {
+ static_assert(Bits << SelBits == ResultBits, "invalid sizes used in demux()");
+ size_t amount = sel.data[0] * Bits;
+ size_t shift_chunks = amount / chunk::bits;
+ size_t shift_bits = amount % chunk::bits;
+ value<ResultBits> result;
+ chunk::type carry = 0;
+ for (size_t n = 0; n < chunks; n++) {
+ result.data[shift_chunks + n] = (data[n] << shift_bits) | carry;
+ carry = (shift_bits == 0) ? 0
+ : data[n] >> (chunk::bits - shift_bits);
+ }
+ if (Bits % chunk::bits + shift_bits > chunk::bits)
+ result.data[shift_chunks + chunks] = carry;
+ return result;
+ }
+
size_t ctpop() const {
size_t count = 0;
for (size_t n = 0; n < chunks; n++) {
diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc
index 7a336f8c1..404755b1e 100644
--- a/backends/cxxrtl/cxxrtl_backend.cc
+++ b/backends/cxxrtl/cxxrtl_backend.cc
@@ -198,7 +198,7 @@ bool is_extending_cell(RTLIL::IdString type)
bool is_inlinable_cell(RTLIL::IdString type)
{
return is_unary_cell(type) || is_binary_cell(type) || type.in(
- ID($mux), ID($concat), ID($slice), ID($pmux));
+ ID($mux), ID($concat), ID($slice), ID($pmux), ID($bmux), ID($demux));
}
bool is_ff_cell(RTLIL::IdString type)
@@ -1154,6 +1154,22 @@ struct CxxrtlWorker {
for (int part = 0; part < s_width; part++) {
f << ")";
}
+ // Big muxes
+ } else if (cell->type == ID($bmux)) {
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
+ f << ".bmux<";
+ f << cell->getParam(ID::WIDTH).as_int();
+ f << ">(";
+ dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
+ f << ").val()";
+ // Demuxes
+ } else if (cell->type == ID($demux)) {
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
+ f << ".demux<";
+ f << GetSize(cell->getPort(ID::Y));
+ f << ">(";
+ dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
+ f << ").val()";
// Concats
} else if (cell->type == ID($concat)) {
dump_sigspec_rhs(cell->getPort(ID::B), for_debug);
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index 7abe584c9..85c44824f 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -1188,6 +1188,8 @@ struct FirrtlBackend : public Backend {
log("Write a FIRRTL netlist of the current design.\n");
log("The following commands are executed by this command:\n");
log(" pmuxtree\n");
+ log(" bmuxmap\n");
+ log(" demuxmap\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
@@ -1210,7 +1212,9 @@ struct FirrtlBackend : public Backend {
log_header(design, "Executing FIRRTL backend.\n");
log_push();
- Pass::call(design, stringf("pmuxtree"));
+ Pass::call(design, "pmuxtree");
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
namecache.clear();
autoid_counter = 0;
diff --git a/backends/json/json.cc b/backends/json/json.cc
index 4aa8046d6..270d762ee 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -52,8 +52,23 @@ struct JsonWriter
string newstr = "\"";
for (char c : str) {
if (c == '\\')
+ newstr += "\\\\";
+ else if (c == '"')
+ newstr += "\\\"";
+ else if (c == '\b')
+ newstr += "\\b";
+ else if (c == '\f')
+ newstr += "\\f";
+ else if (c == '\n')
+ newstr += "\\n";
+ else if (c == '\r')
+ newstr += "\\r";
+ else if (c == '\t')
+ newstr += "\\t";
+ else if (c < 0x20)
+ newstr += stringf("\\u%04X", c);
+ else
newstr += c;
- newstr += c;
}
return newstr + "\"";
}
@@ -379,6 +394,7 @@ struct JsonBackend : public Backend {
log(" \"bits\": <bit_vector>\n");
log(" \"offset\": <the lowest bit index in use, if non-0>\n");
log(" \"upto\": <1 if the port bit indexing is MSB-first>\n");
+ log(" \"signed\": <1 if the port is signed>\n");
log(" }\n");
log("\n");
log("The \"offset\" and \"upto\" fields are skipped if their value would be 0.");
@@ -428,6 +444,7 @@ struct JsonBackend : public Backend {
log(" \"bits\": <bit_vector>\n");
log(" \"offset\": <the lowest bit index in use, if non-0>\n");
log(" \"upto\": <1 if the port bit indexing is MSB-first>\n");
+ log(" \"signed\": <1 if the port is signed>\n");
log(" }\n");
log("\n");
log("The \"hide_name\" fields are set to 1 when the name of this cell or net is\n");
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index f2fa003bc..9bf0de03e 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -985,8 +985,10 @@ struct Smt2Worker
string name_a = get_bool(cell->getPort(ID::A));
string name_en = get_bool(cell->getPort(ID::EN));
- string infostr = (cell->name[0] == '$' && cell->attributes.count(ID::src)) ? cell->attributes.at(ID::src).decode_string() : get_id(cell);
- decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, infostr.c_str()));
+ if (cell->name[0] == '$' && cell->attributes.count(ID::src))
+ decls.push_back(stringf("; yosys-smt2-%s %d %s %s\n", cell->type.c_str() + 1, id, get_id(cell), cell->attributes.at(ID::src).decode_string().c_str()));
+ else
+ decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id, get_id(cell)));
if (cell->type == ID($cover))
decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n",
@@ -1531,6 +1533,11 @@ struct Smt2Backend : public Backend {
log_header(design, "Executing SMT2 backend.\n");
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ log_pop();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index e5cfcdc08..7527f4105 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -492,7 +492,7 @@ if aimfile is not None:
got_state = True
for entry in f.read().splitlines():
- if len(entry) == 0 or entry[0] in "bcjfu.":
+ if len(entry) == 0 or entry[0] in "bcjfu.#":
continue
if not got_state:
@@ -583,7 +583,10 @@ if aimfile is not None:
if not got_topt:
skip_steps = max(skip_steps, step)
- num_steps = max(num_steps, step+1)
+ # some solvers optimize the properties so that they fail one cycle early,
+ # thus we check the properties in the cycle the aiger witness ends, and
+ # if that doesn't work, we check the cycle after that as well.
+ num_steps = max(num_steps, step+2)
step += 1
if btorwitfile is not None:
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index d73a875ba..3d458e6cf 100644
--- a/backends/smt2/smtio.py
+++ b/backends/smt2/smtio.py
@@ -536,10 +536,16 @@ class SmtIo:
self.modinfo[self.curmod].clocks[fields[2]] = "event"
if fields[1] == "yosys-smt2-assert":
- self.modinfo[self.curmod].asserts["%s_a %s" % (self.curmod, fields[2])] = fields[3]
+ if len(fields) > 4:
+ self.modinfo[self.curmod].asserts["%s_a %s" % (self.curmod, fields[2])] = f'{fields[4]} ({fields[3]})'
+ else:
+ self.modinfo[self.curmod].asserts["%s_a %s" % (self.curmod, fields[2])] = fields[3]
if fields[1] == "yosys-smt2-cover":
- self.modinfo[self.curmod].covers["%s_c %s" % (self.curmod, fields[2])] = fields[3]
+ if len(fields) > 4:
+ self.modinfo[self.curmod].covers["%s_c %s" % (self.curmod, fields[2])] = f'{fields[4]} ({fields[3]})'
+ else:
+ self.modinfo[self.curmod].covers["%s_c %s" % (self.curmod, fields[2])] = fields[3]
if fields[1] == "yosys-smt2-maximize":
self.modinfo[self.curmod].maximize.add(fields[2])
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index 7bace6912..7d4f94adc 100644
--- a/backends/smv/smv.cc
+++ b/backends/smv/smv.cc
@@ -741,6 +741,11 @@ struct SmvBackend : public Backend {
log_header(design, "Executing SMV backend.\n");
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ log_pop();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index e4781ef3e..aa1d4558c 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -432,7 +432,7 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
dump_const(f, wire->attributes.at(ID::init));
}
f << stringf(";\n");
- } else if (!wire->port_input && !wire->port_output)
+ } else
f << stringf("%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
#endif
}
@@ -2300,7 +2300,11 @@ struct VerilogBackend : public Backend {
extmem_prefix = filename.substr(0, filename.rfind('.'));
}
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
Pass::call(design, "clean_zerowidth");
+ log_pop();
design->sort();
diff --git a/examples/smtbmc/Makefile b/examples/smtbmc/Makefile
index 61994f942..af937ea74 100644
--- a/examples/smtbmc/Makefile
+++ b/examples/smtbmc/Makefile
@@ -1,5 +1,5 @@
-all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9
+all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9 glift_mux
demo1: demo1.smt2
yosys-smtbmc --dump-vcd demo1.vcd demo1.smt2
@@ -31,6 +31,9 @@ demo8: demo8.smt2
demo9: demo9.smt2
yosys-smtbmc -s z3 -t 1 -g demo9.smt2
+glift_mux:
+ yosys -ql glift_mux.yslog glift/mux2.ys
+
demo1.smt2: demo1.v
yosys -ql demo1.yslog -p 'read_verilog -formal demo1.v; prep -top demo1 -nordff; write_smt2 -wires demo1.smt2'
@@ -68,6 +71,7 @@ clean:
rm -f demo7.yslog demo7.smt2
rm -f demo8.yslog demo8.smt2
rm -f demo9.yslog demo9.smt2
+ rm -f glift_mux.ys
.PHONY: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9 clean
diff --git a/examples/smtbmc/glift/C7552.v b/examples/smtbmc/glift/C7552.v
new file mode 100755
index 000000000..47a8b0d37
--- /dev/null
+++ b/examples/smtbmc/glift/C7552.v
@@ -0,0 +1,4194 @@
+module C7552_lev2(pi000, pi001, pi002, pi003, pi004, pi005, pi006, pi007, pi008, pi009,
+ pi010, pi011, pi012, pi013, pi014, pi015, pi016, pi017, pi018, pi019,
+ pi020, pi021, pi022, pi023, pi024, pi025, pi026, pi027, pi028, pi029,
+ pi030, pi031, pi032, pi033, pi034, pi035, pi036, pi037, pi038, pi039,
+ pi040, pi041, pi042, pi043, pi044, pi045, pi046, pi047, pi048, pi049,
+ pi050, pi051, pi052, pi053, pi054, pi055, pi056, pi057, pi058, pi059,
+ pi060, pi061, pi062, pi063, pi064, pi065, pi066, pi067, pi068, pi069,
+ pi070, pi071, pi072, pi073, pi074, pi075, pi076, pi077, pi078, pi079,
+ pi080, pi081, pi082, pi083, pi084, pi085, pi086, pi087, pi088, pi089,
+ pi090, pi091, pi092, pi093, pi094, pi095, pi096, pi097, pi098, pi099,
+ pi100, pi101, pi102, pi103, pi104, pi105, pi106, pi107, pi108, pi109,
+ pi110, pi111, pi112, pi113, pi114, pi115, pi116, pi117, pi118, pi119,
+ pi120, pi121, pi122, pi123, pi124, pi125, pi126, pi127, pi128, pi129,
+ pi130, pi131, pi132, pi133, pi134, pi135, pi136, pi137, pi138, pi139,
+ pi140, pi141, pi142, pi143, pi144, pi145, pi146, pi147, pi148, pi149,
+ pi150, pi151, pi152, pi153, pi154, pi155, pi156, pi157, pi158, pi159,
+ pi160, pi161, pi162, pi163, pi164, pi165, pi166, pi167, pi168, pi169,
+ pi170, pi171, pi172, pi173, pi174, pi175, pi176, pi177, pi178, pi179,
+ pi180, pi181, pi182, pi183, pi184, pi185, pi186, pi187, pi188, pi189,
+ pi190, pi191, pi192, pi193, pi194, pi195, pi196, pi197, pi198, pi199,
+ pi200, pi201, pi202, pi203, pi204, pi205, pi206, po000, po001, po002,
+ po003, po004, po005, po006, po007, po008, po009, po010, po011, po012,
+ po013, po014, po015, po016, po017, po018, po019, po020, po021, po022,
+ po023, po024, po025, po026, po027, po028, po029, po030, po031, po032,
+ po033, po034, po035, po036, po037, po038, po039, po040, po041, po042,
+ po043, po044, po045, po046, po047, po048, po049, po050, po051, po052,
+ po053, po054, po055, po056, po057, po058, po059, po060, po061, po062,
+ po063, po064, po065, po066, po067, po068, po069, po070, po071, po072,
+ po073, po074, po075, po076, po077, po078, po079, po080, po081, po082,
+ po083, po084, po085, po086, po087, po088, po089, po090, po091, po092,
+ po093, po094, po095, po096, po097, po098, po099, po100, po101, po102,
+ po103, po104, po105, po106, po107);
+
+input pi000, pi001, pi002, pi003, pi004, pi005, pi006, pi007, pi008, pi009,
+ pi010, pi011, pi012, pi013, pi014, pi015, pi016, pi017, pi018, pi019,
+ pi020, pi021, pi022, pi023, pi024, pi025, pi026, pi027, pi028, pi029,
+ pi030, pi031, pi032, pi033, pi034, pi035, pi036, pi037, pi038, pi039,
+ pi040, pi041, pi042, pi043, pi044, pi045, pi046, pi047, pi048, pi049,
+ pi050, pi051, pi052, pi053, pi054, pi055, pi056, pi057, pi058, pi059,
+ pi060, pi061, pi062, pi063, pi064, pi065, pi066, pi067, pi068, pi069,
+ pi070, pi071, pi072, pi073, pi074, pi075, pi076, pi077, pi078, pi079,
+ pi080, pi081, pi082, pi083, pi084, pi085, pi086, pi087, pi088, pi089,
+ pi090, pi091, pi092, pi093, pi094, pi095, pi096, pi097, pi098, pi099,
+ pi100, pi101, pi102, pi103, pi104, pi105, pi106, pi107, pi108, pi109,
+ pi110, pi111, pi112, pi113, pi114, pi115, pi116, pi117, pi118, pi119,
+ pi120, pi121, pi122, pi123, pi124, pi125, pi126, pi127, pi128, pi129,
+ pi130, pi131, pi132, pi133, pi134, pi135, pi136, pi137, pi138, pi139,
+ pi140, pi141, pi142, pi143, pi144, pi145, pi146, pi147, pi148, pi149,
+ pi150, pi151, pi152, pi153, pi154, pi155, pi156, pi157, pi158, pi159,
+ pi160, pi161, pi162, pi163, pi164, pi165, pi166, pi167, pi168, pi169,
+ pi170, pi171, pi172, pi173, pi174, pi175, pi176, pi177, pi178, pi179,
+ pi180, pi181, pi182, pi183, pi184, pi185, pi186, pi187, pi188, pi189,
+ pi190, pi191, pi192, pi193, pi194, pi195, pi196, pi197, pi198, pi199,
+ pi200, pi201, pi202, pi203, pi204, pi205, pi206;
+
+output po000, po001, po002, po003, po004, po005, po006, po007, po008, po009,
+ po010, po011, po012, po013, po014, po015, po016, po017, po018, po019,
+ po020, po021, po022, po023, po024, po025, po026, po027, po028, po029,
+ po030, po031, po032, po033, po034, po035, po036, po037, po038, po039,
+ po040, po041, po042, po043, po044, po045, po046, po047, po048, po049,
+ po050, po051, po052, po053, po054, po055, po056, po057, po058, po059,
+ po060, po061, po062, po063, po064, po065, po066, po067, po068, po069,
+ po070, po071, po072, po073, po074, po075, po076, po077, po078, po079,
+ po080, po081, po082, po083, po084, po085, po086, po087, po088, po089,
+ po090, po091, po092, po093, po094, po095, po096, po097, po098, po099,
+ po100, po101, po102, po103, po104, po105, po106, po107;
+
+wire n2822, n2823, n2824, n2825, n2826, n2827, n2828, n2829, n2830, n2831,
+ n2832, n2833, n2834, n2835, n2836, n2837, n2838, n2839, n2840, n2841,
+ n2842, n2843, n2844, n2845, n2846, n2847, n2848, n2849, n2850, n2851,
+ n2852, n2853, n2854, n2855, n2856, n2857, n2858, n2859, n2860, n2861,
+ n2862, n2863, n2864, n2865, n2866, n2867, n2868, n2869, n2870, n2871,
+ n2872, n2873, n2874, n2875, n2876, n2877, n2878, n2879, n2880, n2881,
+ n2882, n2883, n2884, n2885, n2886, n2887, n2888, n2889, n2890, n2891,
+ n2892, n2893, n2894, n2895, n2896, n2897, n2898, n2899, n2900, n2901,
+ n2902, n2903, n2904, n2905, n2906, n2907, n2908, n2909, n2910, n2911,
+ n2912, n2913, n2914, n2915, n2916, n2917, n2918, n2919, n2920, n2921,
+ n2922, n2923, n2924, n2925, n2926, n2927, n2928, n2929, n2930, n2931,
+ n2932, n2933, n2934, n2935, n2936, n2937, n2938, n2939, n2940, n2941,
+ n2942, n2943, n2944, n2945, n2946, n2947, n2948, n2949, n2950, n2951,
+ n2952, n2953, n2954, n2955, n2956, n2957, n2958, n2959, n2960, n2961,
+ n2962, n2963, n2964, n2965, n2966, n2967, n2968, n2969, n2970, n2971,
+ n2972, n2973, n2974, n2975, n2976, n2977, n2978, n2979, n2980, n2981,
+ n2982, n2983, n2984, n2985, n2986, n2987, n2988, n2989, n2990, n2991,
+ n2992, n2993, n2994, n2995, n2996, n2997, n2998, n2999, n3000, n3001,
+ n3002, n3003, n3004, n3005, n3006, n3007, n3008, n3009, n3010, n3011,
+ n3012, n3013, n3014, n3015, n3016, n3017, n3018, n3019, n3020, n3021,
+ n3022, n3023, n3024, n3025, n3026, n3027, n3028, n3029, n3030, n3031,
+ n3032, n3033, n3034, n3035, n3036, n3037, n3038, n3039, n3040, n3041,
+ n3042, n3043, n3044, n3045, n3046, n3047, n3048, n3049, n3050, n3051,
+ n3052, n3053, n3054, n3055, n3056, n3057, n3058, n3059, n3060, n3061,
+ n3062, n3063, n3064, n3065, n3066, n3067, n3068, n3069, n3070, n3071,
+ n3072, n3073, n3074, n3075, n3076, n3077, n3078, n3079, n3080, n3081,
+ n3082, n3083, n3084, n3085, n3086, n3087, n3088, n3089, n3090, n3091,
+ n3092, n3093, n3094, n3095, n3096, n3097, n3098, n3099, n3100, n3101,
+ n3102, n3103, n3104, n3105, n3106, n3107, n3108, n3109, n3110, n3111,
+ n3112, n3113, n3114, n3115, n3116, n3117, n3118, n3119, n3120, n3121,
+ n3122, n3123, n3124, n3125, n3126, n3127, n3128, n3129, n3130, n3131,
+ n3132, n3133, n3134, n3135, n3136, n3137, n3138, n3139, n3140, n3141,
+ n3142, n3143, n3144, n3145, n3146, n3147, n3148, n3149, n3150, n3151,
+ n3152, n3153, n3154, n3155, n3156, n3157, n3158, n3159, n3160, n3161,
+ n3162, n3163, n3164, n3165, n3166, n3167, n3168, n3169, n3170, n3171,
+ n3172, n3173, n3174, n3175, n3176, n3177, n3178, n3179, n3180, n3181,
+ n3182, n3183, n3184, n3185, n3186, n3187, n3188, n3189, n3190, n3191,
+ n3192, n3193, n3194, n3195, n3196, n3197, n3198, n3199, n3200, n3201,
+ n3202, n3203, n3204, n3205, n3206, n3207, n3208, n3209, n3210, n3211,
+ n3212, n3213, n3214, n3215, n3216, n3217, n3218, n3219, n3220, n3221,
+ n3222, n3223, n3224, n3225, n3226, n3227, n3228, n3229, n3230, n3231,
+ n3232, n3233, n3234, n3235, n3236, n3237, n3238, n3239, n3240, n3241,
+ n3242, n3243, n3244, n3245, n3246, n3247, n3248, n3249, n3250, n3251,
+ n3252, n3253, n3254, n3255, n3256, n3257, n3258, n3259, n3260, n3261,
+ n3262, n3263, n3264, n3265, n3266, n3267, n3268, n3269, n3270, n3271,
+ n3272, n3273, n3274, n3275, n3276, n3277, n3278, n3279, n3280, n3281,
+ n3282, n3283, n3284, n3285, n3286, n3287, n3288, n3289, n3290, n3291,
+ n3292, n3293, n3294, n3295, n3296, n3297, n3298, n3299, n3300, n3301,
+ n3302, n3303, n3304, n3305, n3306, n3307, n3308, n3309, n3310, n3311,
+ n3312, n3313, n3314, n3315, n3316, n3317, n3318, n3319, n3320, n3321,
+ n3322, n3323, n3324, n3325, n3326, n3327, n3328, n3329, n3330, n3331,
+ n3332, n3333, n3334, n3335, n3336, n3337, n3338, n3339, n3340, n3341,
+ n3342, n3343, n3344, n3345, n3346, n3347, n3348, n3349, n3350, n3351,
+ n3352, n3353, n3354, n3355, n3356, n3357, n3358, n3359, n3360, n3361,
+ n3362, n3363, n3364, n3365, n3366, n3367, n3368, n3369, n3370, n3371,
+ n3372, n3373, n3374, n3375, n3376, n3377, n3378, n3379, n3380, n3381,
+ n3382, n3383, n3384, n3385, n3386, n3387, n3388, n3389, n3390, n3391,
+ n3392, n3393, n3394, n3395, n3396, n3397, n3398, n3399, n3400, n3401,
+ n3402, n3403, n3404, n3405, n3406, n3407, n3408, n3409, n3410, n3411,
+ n3412, n3413, n3414, n3415, n3416, n3417, n3418, n3419, n3420, n3421,
+ n3422, n3423, n3424, n3425, n3426, n3427, n3428, n3429, n3430, n3431,
+ n3432, n3433, n3434, n3435, n3436, n3437, n3438, n3439, n3440, n3441,
+ n3442, n3443, n3444, n3445, n3446, n3447, n3448, n3449, n3450, n3451,
+ n3452, n3453, n3454, n3455, n3456, n3457, n3458, n3459, n3460, n3461,
+ n3462, n3463, n3464, n3465, n3466, n3467, n3468, n3469, n3470, n3471,
+ n3472, n3473, n3474, n3475, n3476, n3477, n3478, n3479, n3480, n3481,
+ n3482, n3483, n3484, n3485, n3486, n3487, n3488, n3489, n3490, n3491,
+ n3492, n3493, n3494, n3495, n3496, n3497, n3498, n3499, n3500, n3501,
+ n3502, n3503, n3504, n3505, n3506, n3507, n3508, n3509, n3510, n3511,
+ n3512, n3513, n3514, n3515, n3516, n3517, n3518, n3519, n3520, n3521,
+ n3522, n3523, n3524, n3525, n3526, n3527, n3528, n3529, n3530, n3531,
+ n3532, n3533, n3534, n3535, n3536, n3537, n3538, n3539, n3540, n3541,
+ n3542, n3543, n3544, n3545, n3546, n3547, n3548, n3549, n3550, n3551,
+ n3552, n3553, n3554, n3555, n3556, n3557, n3558, n3559, n3560, n3561,
+ n3562, n3563, n3564, n3565, n3566, n3567, n3568, n3569, n3570, n3571,
+ n3572, n3573, n3574, n3575, n3576, n3577, n3578, n3579, n3580, n3581,
+ n3582, n3583, n3584, n3585, n3586, n3587, n3588, n3589, n3590, n3591,
+ n3592, n3593, n3594, n3595, n3596, n3597, n3598, n3599, n3600, n3601,
+ n3602, n3603, n3604, n3605, n3606, n3607, n3608, n3609, n3610, n3611,
+ n3612, n3613, n3614, n3615, n3616, n3617, n3618, n3619, n3620, n3621,
+ n3622, n3623, n3624, n3625, n3626, n3627, n3628, n3629, n3630, n3631,
+ n3632, n3633, n3634, n3635, n3636, n3637, n3638, n3639, n3640, n3641,
+ n3642, n3643, n3644, n3645, n3646, n3647, n3648, n3649, n3650, n3651,
+ n3652, n3653, n3654, n3655, n3656, n3657, n3658, n3659, n3660, n3661,
+ n3662, n3663, n3664, n3665, n3666, n3667, n3668, n3669, n3670, n3671,
+ n3672, n3673, n3674, n3675, n3676, n3677, n3678, n3679, n3680, n3681,
+ n3682, n3683, n3684, n3685, n3686, n3687, n3688, n3689, n3690, n3691,
+ n3692, n3693, n3694, n3695, n3696, n3697, n3698, n3699, n3700, n3701,
+ n3702, n3703, n3704, n3705, n3706, n3707, n3708, n3709, n3710, n3711,
+ n3712, n3713, n3714, n3715, n3716, n3717, n3718, n3719, n3720, n3721,
+ n3722, n3723, n3724, n3725, n3726, n3727, n3728, n3729, n3730, n3731,
+ n3732, n3733, n3734, n3735, n3736, n3737, n3738, n3739, n3740, n3741,
+ n3742, n3743, n3744, n3745, n3746, n3747, n3748, n3749, n3750, n3751,
+ n3752, n3753, n3754, n3755, n3756, n3757, n3758, n3759, n3760, n3761,
+ n3762, n3763, n3764, n3765, n3766, n3767, n3768, n3769, n3770, n3771,
+ n3772, n3773, n3774, n3775, n3776, n3777, n3778, n3779, n3780, n3781,
+ n3782, n3783, n3784, n3785, n3786, n3787, n3788, n3789, n3790, n3791,
+ n3792, n3793, n3794, n3795, n3796, n3797, n3798, n3799, n3800, n3801,
+ n3802, n3803, n3804, n3805, n3806, n3807, n3808, n3809, n3810, n3811,
+ n3812, n3813, n3814, n3815, n3816, n3817, n3818, n3819, n3820, n3821,
+ n3822, n3823, n3824, n3825, n3826, n3827, n3828, n3829, n3830, n3831,
+ n3832, n3833, n3834, n3835, n3836, n3837, n3838, n3839, n3840, n3841,
+ n3842, n3843, n3844, n3845, n3846, n3847, n3848, n3849, n3850, n3851,
+ n3852, n3853, n3854, n3855, n3856, n3857, n3858, n3859, n3860, n3861,
+ n3862, n3863, n3864, n3865, n3866, n3867, n3868, n3869, n3870, n3871,
+ n3872, n3873, n3874, n3875, n3876, n3877, n3878, n3879, n3880, n3881,
+ n3882, n3883, n3884, n3885, n3886, n3887, n3888, n3889, n3890, n3891,
+ n3892, n3893, n3894, n3895, n3896, n3897, n3898, n3899, n3900, n3901,
+ n3902, n3903, n3904, n3905, n3906, n3907, n3908, n3909, n3910, n3911,
+ n3912, n3913, n3914, n3915, n3916, n3917, n3918, n3919, n3920, n3921,
+ n3922, n3923, n3924, n3925, n3926, n3927, n3928, n3929, n3930, n3931,
+ n3932, n3933, n3934, n3935, n3936, n3937, n3938, n3939, n3940, n3941,
+ n3942, n3943, n3944, n3945, n3946, n3947, n3948, n3949, n3950, n3951,
+ n3952, n3953, n3954, n3955, n3956, n3957, n3958, n3959, n3960, n3961,
+ n3962, n3963, n3964, n3965, n3966, n3967, n3968, n3969, n3970, n3971,
+ n3972, n3973, n3974, n3975, n3976, n3977, n3978, n3979, n3980, n3981,
+ n3982, n3983, n3984, n3985, n3986, n3987, n3988, n3989, n3990, n3991,
+ n3992, n3993, n3994, n3995, n3996, n3997, n3998, n3999, n4000, n4001,
+ n4002, n4003, n4004, n4005, n4006, n4007, n4008, n4009, n4010, n4011,
+ n4012, n4013, n4014, n4015, n4016, n4017, n4018, n4019, n4020, n4021,
+ n4022, n4023, n4024, n4025, n4026, n4027, n4028, n4029, n4030, n4031,
+ n4032, n4033, n4034, n4035, n4036, n4037, n4038, n4039, n4040, n4041,
+ n4042, n4043, n4044, n4045, n4046, n4047, n4048, n4049, n4050, n4051,
+ n4052, n4053, n4054, n4055, n4056, n4057, n4058, n4059, n4060, n4061,
+ n4062, n4063, n4064, n4065, n4066, n4067, n4068, n4069, n4070, n4071,
+ n4072, n4073, n4074, n4075, n4076, n4077, n4078, n4079, n4080, n4081,
+ n4082, n4083, n4084, n4085, n4086, n4087, n4088, n4089, n4090, n4091,
+ n4092, n4093, n4094, n4095, n4096, n4097, n4098, n4099, n4100, n4101,
+ n4102, n4103, n4104, n4105, n4106, n4107, n4108, n4109, n4110, n4111,
+ n4112, n4113, n4114, n4115, n4116, n4117, n4118, n4119, n4120, n4121,
+ n4122, n4123, n4124, n4125, n4126, n4127, n4128, n4129, n4130, n4131,
+ n4132, n4133, n4134, n4135, n4136, n4137, n4138, n4139, n4140, n4141,
+ n4142, n4143, n4144, n4145, n4146, n4147, n4148, n4149, n4150, n4151,
+ n4152, n4153, n4154, n4155, n4156, n4157, n4158, n4159, n4160, n4161,
+ n4162, n4163, n4164, n4165, n4166, n4167, n4168, n4169, n4170, n4171,
+ n4172, n4173, n4174, n4175, n4176, n4177, n4178, n4179, n4180, n4181,
+ n4182, n4183, n4184, n4185, n4186, n4187, n4188, n4189, n4190, n4191,
+ n4192, n4193, n4194, n4195, n4196, n4197, n4198, n4199, n4200, n4201,
+ n4202, n4203, n4204, n4205, n4206, n4207, n4208, n4209, n4210, n4211,
+ n4212, n4213, n4214, n4215, n4216, n4217, n4218, n4219, n4220, n4221,
+ n4222, n4223, n4224, n4225, n4226, n4227, n4228, n4229, n4230, n4231,
+ n4232, n4233, n4234, n4235, n4236, n4237, n4238, n4239, n4240, n4241,
+ n4242, n4243, n4244, n4245, n4246, n4247, n4248, n4249, n4250, n4251,
+ n4252, n4253, n4254, n4255, n4256, n4257, n4258, n4259, n4260, n4261,
+ n4262, n4263, n4264, n4265, n4266, n4267, n4268, n4269, n4270, n4271,
+ n4272, n4273, n4274, n4275, n4276, n4277, n4278, n4279, n4280, n4281,
+ n4282, n4283, n4284, n4285, n4286, n4287, n4288, n4289, n4290, n4291,
+ n4292, n4293, n4294, n4295, n4296, n4297, n4298, n4299, n4300, n4301,
+ n4302, n4303, n4304, n4305, n4306, n4307, n4308, n4309, n4310, n4311,
+ n4312, n4313, n4314, n4315, n4316, n4317, n4318, n4319, n4320, n4321,
+ n4322, n4323, n4324, n4325, n4326, n4327, n4328, n4329, n4330, n4331,
+ n4332, n4333, n4334, n4335, n4336, n4337, n4338, n4339, n4340, n4341,
+ n4342, n4343, n4344, n4345, n4346, n4347, n4348, n4349, n4350, n4351,
+ n4352, n4353, n4354, n4355, n4356, n4357, n4358, n4359, n4360, n4361,
+ n4362, n4363, n4364, n4365, n4366, n4367, n4368, n4369, n4370, n4371,
+ n4372, n4373, n4374, n4375, n4376, n4377, n4378, n4379, n4380, n4381,
+ n4382, n4383, n4384, n4385, n4386, n4387, n4388, n4389, n4390, n4391,
+ n4392, n4393, n4394, n4395, n4396, n4397, n4398, n4399, n4400, n4401,
+ n4402, n4403, n4404, n4405, n4406, n4407, n4408, n4409, n4410, n4411,
+ n4412, n4413, n4414, n4415, n4416, n4417, n4418, n4419, n4420, n4421,
+ n4422, n4423, n4424, n4425, n4426, n4427, n4428, n4429, n4430, n4431,
+ n4432, n4433, n4434, n4435, n4436, n4437, n4438, n4439, n4440, n4441,
+ n4442, n4443, n4444, n4445, n4446, n4447, n4448, n4449, n4450, n4451,
+ n4452, n4453, n4454, n4455, n4456, n4457, n4458, n4459, n4460, n4461,
+ n4462, n4463, n4464, n4465, n4466, n4467, n4468, n4469, n4470, n4471,
+ n4472, n4473, n4474, n4475, n4476, n4477, n4478, n4479, n4480, n4481,
+ n4482, n4483, n4484, n4485, n4486, n4487, n4488, n4489, n4490, n4491,
+ n4492, n4493, n4494, n4495, n4496, n4497, n4498, n4499, n4500, n4501,
+ n4502, n4503, n4504, n4505, n4506, n4507, n4508, n4509, n4510, n4511,
+ n4512, n4513, n4514, n4515, n4516, n4517, n4518, n4519, n4520, n4521,
+ n4522, n4523, n4524, n4525, n4526, n4527, n4528, n4529, n4530, n4531,
+ n4532, n4533, n4534, n4535, n4536, n4537, n4538, n4539, n4540, n4541,
+ n4542, n4543, n4544, n4545, n4546, n4547, n4548, n4549, n4550, n4551,
+ n4552, n4553, n4554, n4555, n4556, n4557, n4558, n4559, n4560, n4561,
+ n4562, n4563, n4564, n4565, n4566, n4567, n4568, n4569, n4570, n4571,
+ n4572, n4573, n4574, n4575, n4576, n4577, n4578, n4579, n4580, n4581,
+ n4582, n4583, n4584, n4585, n4586, n4587, n4588, n4589, n4590, n4591,
+ n4592, n4593, n4594, n4595, n4596, n4597, n4598, n4599, n4600, n4601,
+ n4602, n4603, n4604, n4605, n4606, n4607, n4608, n4609, n4610, n4611,
+ n4612, n4613, n4614, n4615, n4616, n4617, n4618, n4619, n4620, n4621,
+ n4622, n4623, n4624, n4625, n4626, n4627, n4628, n4629, n4630, n4631,
+ n4632, n4633, n4634, n4635, n4636, n4637, n4638, n4639, n4640, n4641,
+ n4642, n4643, n4644, n4645, n4646, n4647, n4648, n4649, n4650, n4651,
+ n4652, n4653, n4654, n4655, n4656, n4657, n4658, n4659, n4660, n4661,
+ n4662, n4663, n4664, n4665, n4666, n4667, n4668, n4669, n4670, n4671,
+ n4672, n4673, n4674, n4675, n4676, n4677, n4678, n4679, n4680, n4681,
+ n4682, n4683, n4684, n4685, n4686, n4687, n4688, n4689, n4690, n4691,
+ n4692, n4693, n4694, n4695, n4696, n4697, n4698, n4699, n4700, n4701,
+ n4702, n4703, n4704, n4705, n4706, n4707, n4708, n4709, n4710, n4711,
+ n4712, n4713, n4714, n4715, n4716, n4717, n4718, n4719, n4720, n4721,
+ n4722, n4723, n4724, n4725, n4726, n4727, n4728, n4729, n4730, n4731,
+ n4732, n4733, n4734, n4735, n4736, n4737, n4738, n4739, n4740, n4741,
+ n4742, n4743, n4744, n4745, n4746, n4747, n4748, n4749, n4750, n4751,
+ n4752, n4753, n4754, n4755, n4756, n4757, n4758, n4759, n4760, n4761,
+ n4762, n4763, n4764, n4765, n4766, n4767, n4768, n4769, n4770, n4771,
+ n4772, n4773, n4774, n4775, n4776, n4777, n4778, n4779, n4780, n4781,
+ n4782, n4783, n4784, n4785, n4786, n4787, n4788, n4789, n4790, n4791,
+ n4792, n4793, n4794, n4795, n4796, n4797, n4798, n4799, n4800, n4801,
+ n4802, n4803, n4804, n4805, n4806, n4807, n4808, n4809, n4810, n4811,
+ n4812, n4813, n4814, n4815, n4816, n4817, n4818, n4819, n4820, n4821,
+ n4822, n4823, n4824, n4825, n4826, n4827, n4828, n4829, n4830, n4831,
+ n4832, n4833, n4834, n4835, n4836, n4837, n4838, n4839, n4840, n4841,
+ n4842, n4843, n4844, n4845, n4846, n4847, n4848, n4849, n4850, n4851,
+ n4852, n4853, n4854, n4855, n4856, n4857, n4858, n4859, n4860, n4861,
+ n4862, n4863, n4864, n4865, n4866, n4867, n4868, n4869, n4870, n4871,
+ n4872, n4873, n4874, n4875, n4876, n4877, n4878, n4879, n4880, n4881,
+ n4882, n4883, n4884, n4885, n4886, n4887, n4888, n4889, n4890, n4891,
+ n4892, n4893, n4894, n4895, n4896, n4897, n4898, n4899, n4900, n4901,
+ n4902, n4903, n4904, n4905, n4906, n4907, n4908, n4909, n4910, n4911,
+ n4912, n4913, n4914, n4915, n4916, n4917, n4918, n4919, n4920, n4921,
+ n4922, n4923, n4924, n4925, n4926, n4927, n4928, n4929, n4930, n4931,
+ n4932, n4933, n4934, n4935, n4936, n4937, n4938, n4939, n4940, n4941,
+ n4942, n4943, n4944, n4945, n4946, n4947, n4948, n4949, n4950, n4951,
+ n4952, n4953, n4954, n4955, n4956, n4957, n4958, n4959, n4960, n4961,
+ n4962, n4963, n4964, n4965, n4966, n4967, n4968, n4969, n4970, n4971,
+ n4972, n4973, n4974, n4975, n4976, n4977, n4978, n4979, n4980, n4981,
+ n4982, n4983, n4984, n4985, n4986, n4987, n4988, n4989, n4990, n4991,
+ n4992, n4993, n4994, n4995, n4996, n4997, n4998, n4999, n5000, n5001,
+ n5002, n5003, n5004, n5005, n5006, n5007, n5008, n5009, n5010, n5011,
+ n5012, n5013, n5014, n5015, n5016, n5017, n5018, n5019, n5020, n5021,
+ n5022, n5023, n5024, n5025, n5026, n5027, n5028, n5029, n5030, n5031,
+ n5032, n5033, n5034, n5035, n5036, n5037, n5038, n5039, n5040, n5041,
+ n5042, n5043, n5044, n5045, n5046, n5047, n5048, n5049, n5050, n5051,
+ n5052, n5053, n5054, n5055, n5056, n5057, n5058, n5059, n5060, n5061,
+ n5062, n5063, n5064, n5065, n5066, n5067, n5068, n5069, n5070, n5071,
+ n5072, n5073, n5074, n5075, n5076, n5077, n5078, n5079, n5080, n5081,
+ n5082, n5083, n5084, n5085, n5086, n5087, n5088, n5089, n5090, n5091,
+ n5092, n5093, n5094, n5095, n5096, n5097, n5098, n5099, n5100, n5101,
+ n5102, n5103, n5104, n5105, n5106, n5107, n5108, n5109, n5110, n5111,
+ n5112, n5113, n5114, n5115, n5116, n5117, n5118, n5119, n5120, n5121,
+ n5122, n5123, n5124, n5125, n5126, n5127, n5128, n5129, n5130, n5131,
+ n5132, n5133, n5134, n5135, n5136, n5137, n5138, n5139, n5140, n5141,
+ n5142, n5143, n5144, n5145, n5146, n5147, n5148, n5149, n5150, n5151,
+ n5152, n5153, n5154, n5155, n5156, n5157, n5158, n5159, n5160, n5161,
+ n5162, n5163, n5164, n5165, n5166, n5167, n5168, n5169, n5170, n5171,
+ n5172, n5173, n5174, n5175, n5176, n5177, n5178, n5179, n5180, n5181,
+ n5182, n5183, n5184, n5185, n5186, n5187, n5188, n5189, n5190, n5191,
+ n5192, n5193, n5194, n5195, n5196, n5197, n5198, n5199, n5200, n5201,
+ n5202, n5203, n5204, n5205, n5206, n5207, n5208, n5209, n5210, n5211,
+ n5212, n5213, n5214, n5215, n5216, n5217, n5218, n5219, n5220, n5221,
+ n5222, n5223, n5224, n5225, n5226, n5227, n5228, n5229, n5230, n5231,
+ n5232, n5233, n5234, n5235, n5236, n5237, n5238, n5239, n5240, n5241,
+ n5242, n5243, n5244, n5245, n5246, n5247, n5248, n5249, n5250, n5251,
+ n5252, n5253, n5254, n5255, n5256, n5257, n5258, n5259, n5260, n5261,
+ n5262, n5263, n5264, n5265, n5266, n5267, n5268, n5269, n5270, n5271,
+ n5272, n5273, n5274, n5275, n5276, n5277, n5278, n5279, n5280, n5281,
+ n5282, n5283, n5284, n5285, n5286, n5287, n5288, n5289, n5290, n5291,
+ n5292, n5293, n5294, n5295, n5296, n5297, n5298, n5299, n5300, n5301,
+ n5302, n5303, n5304, n5305, n5306, n5307, n5308, n5309, n5310, n5311,
+ n5312, n5313, n5314, n5315, n5316, n5317, n5318, n5319, n5320, n5321,
+ n5322, n5323, n5324, n5325, n5326, n5327, n5328, n5329, n5330, n5331,
+ n5332, n5333, n5334, n5335, n5336, n5337, n5338, n5339, n5340, n5341,
+ n5342, n5343, n5344, n5345, n5346, n5347, n5348, n5349, n5350, n5351,
+ n5352, n5353, n5354, n5355, n5356, n5357, n5358, n5359, n5360, n5361,
+ n5362, n5363, n5364, n5365, n5366, n5367, n5368, n5369, n5370, n5371,
+ n5372, n5373, n5374, n5375, n5376, n5377, n5378, n5379, n5380, n5381,
+ n5382, n5383, n5384, n5385, n5386, n5387, n5388, n5389, n5390, n5391,
+ n5392, n5393, n5394, n5395, n5396, n5397, n5398, n5399, n5400, n5401,
+ n5402, n5403, n5404, n5405, n5406, n5407, n5408, n5409, n5410, n5411,
+ n5412, n5413, n5414, n5415, n5416, n5417, n5418, n5419, n5420, n5421,
+ n5422, n5423, n5424, n5425, n5426, n5427, n5428, n5429, n5430, n5431,
+ n5432, n5433, n5434, n5435, n5436, n5437, n5438, n5439, n5440, n5441,
+ n5442, n5443, n5444, n5445, n5446, n5447, n5448, n5449, n5450, n5451,
+ n5452, n5453, n5454, n5455, n5456, n5457, n5458, n5459, n5460, n5461,
+ n5462, n5463, n5464, n5465, n5466, n5467, n5468, n5469, n5470, n5471,
+ n5472, n5473, n5474, n5475, n5476, n5477, n5478, n5479, n5480, n5481,
+ n5482, n5483, n5484, n5485, n5486, n5487, n5488, n5489, n5490, n5491,
+ n5492, n5493, n5494, n5495, n5496, n5497, n5498, n5499, n5500, n5501,
+ n5502, n5503, n5504, n5505, n5506, n5507, n5508, n5509, n5510, n5511,
+ n5512, n5513, n5514, n5515, n5516, n5517, n5518, n5519, n5520, n5521,
+ n5522, n5523, n5524, n5525, n5526, n5527, n5528, n5529, n5530, n5531,
+ n5532, n5533, n5534, n5535, n5536, n5537, n5538, n5539, n5540, n5541,
+ n5542, n5543, n5544, n5545, n5546, n5547, n5548, n5549, n5550, n5551,
+ n5552, n5553, n5554, n5555, n5556, n5557, n5558, n5559, n5560, n5561,
+ n5562, n5563, n5564, n5565, n5566, n5567, n5568, n5569, n5570, n5571,
+ n5572, n5573, n5574, n5575, n5576, n5577, n5578, n5579, n5580, n5581,
+ n5582, n5583, n5584, n5585, n5586, n5587, n5588, n5589, n5590, n5591,
+ n5592, n5593, n5594, n5595, n5596, n5597, n5598, n5599, n5600, n5601,
+ n5602, n5603, n5604, n5605, n5606, n5607, n5608, n5609, n5610, n5611,
+ n5612, n5613, n5614, n5615, n5616, n5617, n5618, n5619, n5620, n5621,
+ n5622, n5623, n5624, n5625, n5626, n5627, n5628, n5629, n5630, n5631,
+ n5632, n5633, n5634, n5635, n5636, n5637, n5638, n5639, n5640, n5641,
+ n5642, n5643, n5644, n5645, n5646, n5647, n5648, n5649, n5650, n5651,
+ n5652, n5653, n5654, n5655, n5656, n5657, n5658, n5659, n5660, n5661,
+ n5662, n5663, n5664, n5665, n5666, n5667, n5668, n5669, n5670, n5671,
+ n5672, n5673, n5674, n5675, n5676, n5677, n5678, n5679, n5680, n5681,
+ n5682, n5683, n5684, n5685, n5686, n5687, n5688, n5689, n5690, n5691,
+ n5692, n5693, n5694, n5695, n5696, n5697, n5698, n5699, n5700, n5701,
+ n5702, n5703, n5704, n5705, n5706, n5707, n5708, n5709, n5710, n5711,
+ n5712, n5713, n5714, n5715, n5716, n5717, n5718, n5719, n5720, n5721,
+ n5722, n5723, n5724, n5725, n5726, n5727, n5728, n5729, n5730, n5731,
+ n5732, n5733, n5734, n5735, n5736, n5737, n5738, n5739, n5740, n5741,
+ n5742, n5743, n5744, n5745, n5746, n5747, n5748, n5749, n5750, n5751,
+ n5752, n5753, n5754, n5755, n5756, n5757, n5758, n5759, n5760, n5761,
+ n5762, n5763, n5764, n5765, n5766, n5767, n5768, n5769, n5770, n5771,
+ n5772, n5773, n5774, n5775, n5776, n5777, n5778, n5779, n5780, n5781,
+ n5782, n5783, n5784, n5785, n5786, n5787, n5788, n5789, n5790, n5791,
+ n5792, n5793, n5794, n5795, n5796, n5797, n5798, n5799, n5800, n5801,
+ n5802, n5803, n5804, n5805, n5806, n5807, n5808, n5809, n5810, n5811,
+ n5812, n5813, n5814, n5815, n5816, n5817, n5818, n5819, n5820, n5821,
+ n5822, n5823, n5824, n5825, n5826, n5827, n5828, n5829, n5830, n5831,
+ n5832, n5833, n5834, n5835, n5836, n5837, n5838, n5839, n5840, n5841,
+ n5842, n5843, n5844, n5845, n5846, n5847, n5848, n5849, n5850, n5851,
+ n5852, n5853, n5854, n5855, n5856, n5857, n5858, n5859, n5860, n5861,
+ n5862, n5863, n5864, n5865, n5866, n5867, n5868, n5869, n5870, n5871,
+ n5872, n5873, n5874, n5875, n5876, n5877, n5878, n5879, n5880, n5881,
+ n5882, n5883, n5884, n5885, n5886, n5887, n5888, n5889, n5890, n5891,
+ n5892, n5893, n5894, n5895, n5896, n5897, n5898, n5899, n5900, n5901,
+ n5902, n5903, n5904, n5905, n5906, n5907, n5908, n5909, n5910, n5911,
+ n5912, n5913, n5914, n5915, n5916, n5917, n5918, n5919, n5920, n5921,
+ n5922, n5923, n5924, n5925, n5926, n5927, n5928, n5929, n5930, n5931,
+ n5932, n5933, n5934, n5935, n5936, n5937, n5938, n5939, n5940, n5941,
+ n5942, n5943, n5944, n5945, n5946, n5947, n5948, n5949, n5950, n5951,
+ n5952, n5953, n5954, n5955, n5956, n5957, n5958, n5959, n5960, n5961,
+ n5962, n5963, n5964, n5965, n5966, n5967, n5968, n5969, n5970, n5971,
+ n5972, n5973, n5974, n5975, n5976, n5977, n5978, n5979, n5980, n5981,
+ n5982, n5983, n5984, n5985, n5986, n5987, n5988, n5989, n5990, n5991,
+ n5992, n5993, n5994, n5995, n5996, n5997, n5998, n5999, n6000, n6001,
+ n6002, n6003, n6004, n6005, n6006, n6007, n6008, n6009, n6010, n6011,
+ n6012, n6013, n6014, n6015, n6016, n6017, n6018, n6019, n6020, n6021,
+ n6022, n6023, n6024, n6025, n6026, n6027, n6028, n6029, n6030, n6031,
+ n6032, n6033, n6034, n6035, n6036, n6037, n6038, n6039, n6040, n6041,
+ n6042, n6043, n6044, n6045, n6046, n6047, n6048, n6049, n6050, n6051,
+ n6052, n6053, n6054, n6055, n6056, n6057, n6058, n6059, n6060, n6061,
+ n6062, n6063, n6064, n6065, n6066, n6067, n6068, n6069, n6070, n6071,
+ n6072, n6073, n6074, n6075, n6076, n6077, n6078, n6079, n6080, n6081,
+ n6082, n6083, n6084, n6085, n6086, n6087, n6088, n6089, n6090, n6091,
+ n6092, n6093, n6094, n6095, n6096, n6097, n6098, n6099, n6100, n6101,
+ n6102, n6103, n6104, n6105, n6106, n6107, n6108, n6109, n6110, n6111,
+ n6112, n6113, n6114, n6115, n6116, n6117, n6118, n6119, n6120, n6121,
+ n6122, n6123, n6124, n6125, n6126, n6127, n6128, n6129, n6130, n6131,
+ n6132, n6133, n6134, n6135, n6136, n6137, n6138, n6139, n6140, n6141,
+ n6142, n6143, n6144, n6145, n6146, n6147, n6148, n6149, n6150, n6151,
+ n6152, n6153, n6154, n6155, n6156, n6157, n6158, n6159, n6160, n6161,
+ n6162, n6163, n6164, n6165, n6166, n6167, n6168, n6169, n6170, n6171,
+ n6172, n6173, n6174, n6175, n6176, n6177, n6178, n6179, n6180, n6181,
+ n6182, n6183, n6184, n6185, n6186, n6187, n6188, n6189, n6190, n6191,
+ n6192, n6193, n6194, n6195, n6196, n6197, n6198, n6199, n6200, n6201,
+ n6202, n6203, n6204, n6205, n6206, n6207, n6208, n6209, n6210, n6211,
+ n6212, n6213, n6214, n6215, n6216, n6217, n6218, n6219, n6220, n6221,
+ n6222, n6223, n6224, n6225, n6226, n6227, n6228, n6229, n6230, n6231,
+ n6232, n6233, n6234, n6235, n6236, n6237, n6238, n6239, n6240, n6241,
+ n6242, n6243, n6244, n6245, n6246, n6247, n6248, n6249, n6250, n6251,
+ n6252, n6253, n6254, n6255, n6256, n6257, n6258, n6259, n6260, n6261,
+ n6262, n6263, n6264, n6265, n6266, n6267, n6268, n6269, n6270, n6271,
+ n6272, n6273, n6274, n6275, n6276, n6277, n6278, n6279, n6280, n6281,
+ n6282, n6283, n6284, n6285, n6286, n6287, n6288, n6289, n6290, n6291,
+ n6292, n6293, n6294, n6295, n6296, n6297, n6298, n6299, n6300, n6301,
+ n6302, n6303, n6304, n6305, n6306, n6307, n6308, n6309, n6310, n6311,
+ n6312, n6313, n6314, n6315, n6316, n6317, n6318, n6319, n6320, n6321,
+ n6322, n6323, n6324, n6325, n6326, n6327, n6328, n6329, n6330, n6331,
+ n6332, n6333, n6334, n6335, n6336, n6337, n6338, n6339, n6340, n6341,
+ n6342, n6343, n6344, n6345, n6346, n6347, n6348, n6349, n6350, n6351,
+ n6352, n6353, n6354, n6355, n6356, n6357, n6358, n6359, n6360, n6361,
+ n6362, n6363, n6364, n6365, n6366, n6367, n6368, n6369, n6370, n6371,
+ n6372, n6373, n6374, n6375, n6376, n6377, n6378, n6379, n6380, n6381,
+ n6382, n6383, n6384, n6385, n6386, n6387, n6388, n6389, n6390, n6391,
+ n6392, n6393, n6394, n6395, n6396, n6397, n6398, n6399, n6400, n6401,
+ n6402, n6403, n6404, n6405;
+
+assign po001 = pi187;
+
+assign po015 = po003;
+
+assign po004 = pi106;
+
+assign po009 = pi136;
+
+assign po010 = pi022;
+
+assign po011 = pi112;
+
+assign po005 = po012;
+
+assign po013 = pi062;
+
+assign po014 = pi123;
+
+assign po101 = po023;
+
+assign po067 = po023;
+
+assign po066 = po023;
+
+assign po023 = pi119;
+
+assign po024 = pi152;
+
+assign po025 = pi125;
+
+assign po027 = pi102;
+
+assign po028 = pi031;
+
+assign po031 = pi155;
+
+assign po065 = po034;
+
+assign po035 = pi182;
+
+assign po036 = pi023;
+
+assign po038 = pi071;
+
+assign po039 = pi015;
+
+assign po040 = pi132;
+
+assign po044 = pi044;
+
+assign po052 = pi048;
+
+assign po057 = pi117;
+
+assign po059 = pi091;
+
+assign po063 = pi000;
+
+assign po064 = pi194;
+
+assign po069 = pi147;
+
+assign po070 = pi002;
+
+assign po071 = pi080;
+
+assign po072 = pi188;
+
+assign po018 = po074;
+
+assign po021 = po074;
+
+assign po079 = pi084;
+
+assign po082 = pi144;
+
+assign po084 = pi199;
+
+assign po085 = pi066;
+
+assign po091 = pi008;
+
+assign po092 = pi154;
+
+assign po099 = pi042;
+
+assign po102 = pi179;
+
+assign po103 = pi145;
+
+assign po104 = pi127;
+
+assign po106 = pi105;
+
+assign po107 = pi029;
+
+assign po020 = po041;
+
+assign po032 = po007;
+
+assign po089 = po076;
+
+assign po054 = po076;
+
+ OR2 U2865 ( .A(n2822), .B(n2823), .Z(po100));
+ AN2 U2866 ( .A(n2824), .B(pi192), .Z(n2823));
+ OR2 U2867 ( .A(n2825), .B(n2826), .Z(n2824));
+ AN2 U2868 ( .A(n2827), .B(n2828), .Z(n2826));
+ IV2 U2869 ( .A(n2829), .Z(n2825));
+ OR2 U2870 ( .A(n2828), .B(n2827), .Z(n2829));
+ OR2 U2871 ( .A(n2830), .B(n2831), .Z(n2827));
+ AN2 U2872 ( .A(n2832), .B(n2833), .Z(n2831));
+ AN2 U2873 ( .A(n2834), .B(n2835), .Z(n2830));
+ AN2 U2874 ( .A(n2836), .B(n2837), .Z(n2822));
+ OR2 U2875 ( .A(n2838), .B(n2839), .Z(n2836));
+ AN2 U2876 ( .A(n2840), .B(n2828), .Z(n2839));
+ IV2 U2877 ( .A(n2841), .Z(n2838));
+ OR2 U2878 ( .A(n2828), .B(n2840), .Z(n2841));
+ OR2 U2879 ( .A(n2842), .B(n2843), .Z(n2840));
+ AN2 U2880 ( .A(n2844), .B(n2845), .Z(n2843));
+ AN2 U2881 ( .A(n2846), .B(n2847), .Z(n2842));
+ AN2 U2882 ( .A(n2848), .B(n2849), .Z(n2828));
+ IV2 U2883 ( .A(n2850), .Z(n2849));
+ AN2 U2884 ( .A(n2851), .B(n2852), .Z(n2850));
+ OR2 U2885 ( .A(n2852), .B(n2851), .Z(n2848));
+ OR2 U2886 ( .A(n2853), .B(n2854), .Z(n2851));
+ AN2 U2887 ( .A(n2855), .B(n2856), .Z(n2854));
+ IV2 U2888 ( .A(n2857), .Z(n2853));
+ OR2 U2889 ( .A(n2856), .B(n2855), .Z(n2857));
+ IV2 U2890 ( .A(n2858), .Z(n2855));
+ OR2 U2891 ( .A(n2859), .B(n2860), .Z(n2858));
+ AN2 U2892 ( .A(n2861), .B(n2862), .Z(n2859));
+ OR2 U2893 ( .A(n2863), .B(n2864), .Z(n2856));
+ OR2 U2894 ( .A(n2865), .B(n2866), .Z(n2864));
+ AN2 U2895 ( .A(pi192), .B(n2867), .Z(n2866));
+ OR2 U2896 ( .A(n2868), .B(n2869), .Z(n2867));
+ OR2 U2897 ( .A(n2870), .B(n2871), .Z(n2869));
+ AN2 U2898 ( .A(n2872), .B(n2873), .Z(n2871));
+ AN2 U2899 ( .A(n2862), .B(n2874), .Z(n2872));
+ OR2 U2900 ( .A(n2875), .B(n2876), .Z(n2874));
+ AN2 U2901 ( .A(n2877), .B(n2878), .Z(n2875));
+ AN2 U2902 ( .A(n2879), .B(n2880), .Z(n2870));
+ AN2 U2903 ( .A(n2881), .B(n2882), .Z(n2868));
+ OR2 U2904 ( .A(n2883), .B(n2884), .Z(n2881));
+ AN2 U2905 ( .A(n2885), .B(n2886), .Z(n2884));
+ AN2 U2906 ( .A(n2879), .B(n2887), .Z(n2883));
+ IV2 U2907 ( .A(n2873), .Z(n2879));
+ OR2 U2908 ( .A(n2888), .B(n2889), .Z(n2873));
+ AN2 U2909 ( .A(n2890), .B(n2891), .Z(n2889));
+ AN2 U2910 ( .A(n2892), .B(n2886), .Z(n2888));
+ AN2 U2911 ( .A(n2893), .B(n2837), .Z(n2865));
+ OR2 U2912 ( .A(n2894), .B(n2895), .Z(n2893));
+ OR2 U2913 ( .A(n2896), .B(n2897), .Z(n2895));
+ OR2 U2914 ( .A(n2898), .B(n2899), .Z(n2897));
+ AN2 U2915 ( .A(n2900), .B(n2901), .Z(n2899));
+ AN2 U2916 ( .A(n2902), .B(n2903), .Z(n2900));
+ OR2 U2917 ( .A(n2904), .B(n2905), .Z(n2903));
+ OR2 U2918 ( .A(n2906), .B(n2907), .Z(n2905));
+ AN2 U2919 ( .A(n2890), .B(n2908), .Z(n2907));
+ AN2 U2920 ( .A(n2909), .B(n2886), .Z(n2906));
+ AN2 U2921 ( .A(n2910), .B(pi082), .Z(n2909));
+ AN2 U2922 ( .A(pi200), .B(n2911), .Z(n2898));
+ OR2 U2923 ( .A(n2912), .B(n2913), .Z(n2911));
+ OR2 U2924 ( .A(n2914), .B(n2915), .Z(n2913));
+ AN2 U2925 ( .A(n2916), .B(n2890), .Z(n2915));
+ AN2 U2926 ( .A(n2910), .B(n2917), .Z(n2916));
+ OR2 U2927 ( .A(n2918), .B(n2919), .Z(n2917));
+ AN2 U2928 ( .A(n2920), .B(n2886), .Z(n2914));
+ OR2 U2929 ( .A(n2921), .B(n2922), .Z(n2920));
+ OR2 U2930 ( .A(n2923), .B(n2924), .Z(n2922));
+ AN2 U2931 ( .A(n2918), .B(n2860), .Z(n2924));
+ AN2 U2932 ( .A(n2925), .B(n2926), .Z(n2923));
+ OR2 U2933 ( .A(n2927), .B(n2928), .Z(n2926));
+ AN2 U2934 ( .A(n2844), .B(n2929), .Z(n2928));
+ AN2 U2935 ( .A(n2930), .B(n2931), .Z(n2927));
+ OR2 U2936 ( .A(n2932), .B(n2933), .Z(n2921));
+ AN2 U2937 ( .A(n2934), .B(n2935), .Z(n2933));
+ AN2 U2938 ( .A(n2936), .B(n2910), .Z(n2934));
+ AN2 U2939 ( .A(n2937), .B(n2938), .Z(n2932));
+ AN2 U2940 ( .A(n2929), .B(n2939), .Z(n2937));
+ AN2 U2941 ( .A(n2935), .B(n2940), .Z(n2912));
+ OR2 U2942 ( .A(n2904), .B(n2941), .Z(n2940));
+ AN2 U2943 ( .A(n2890), .B(n2942), .Z(n2941));
+ AN2 U2944 ( .A(n2943), .B(n2944), .Z(n2942));
+ OR2 U2945 ( .A(n2945), .B(n2946), .Z(n2944));
+ IV2 U2946 ( .A(n2910), .Z(n2945));
+ OR2 U2947 ( .A(n2936), .B(n2947), .Z(n2943));
+ IV2 U2948 ( .A(n2948), .Z(n2904));
+ OR2 U2949 ( .A(n2949), .B(n2939), .Z(n2948));
+ AN2 U2950 ( .A(n2950), .B(n2951), .Z(n2949));
+ OR2 U2951 ( .A(n2890), .B(n2947), .Z(n2951));
+ OR2 U2952 ( .A(n2929), .B(n2886), .Z(n2950));
+ AN2 U2953 ( .A(n2952), .B(n2953), .Z(n2896));
+ AN2 U2954 ( .A(n2954), .B(n2955), .Z(n2953));
+ OR2 U2955 ( .A(n2956), .B(n2957), .Z(n2955));
+ AN2 U2956 ( .A(n2890), .B(n2958), .Z(n2956));
+ OR2 U2957 ( .A(n2959), .B(n2960), .Z(n2958));
+ OR2 U2958 ( .A(pi082), .B(n2961), .Z(n2954));
+ AN2 U2959 ( .A(n2901), .B(n2886), .Z(n2961));
+ AN2 U2960 ( .A(n2910), .B(n2962), .Z(n2952));
+ AN2 U2961 ( .A(n2947), .B(n2862), .Z(n2910));
+ OR2 U2962 ( .A(n2963), .B(n2964), .Z(n2894));
+ AN2 U2963 ( .A(n2965), .B(n2890), .Z(n2964));
+ AN2 U2964 ( .A(n2929), .B(n2966), .Z(n2965));
+ OR2 U2965 ( .A(n2967), .B(n2968), .Z(n2966));
+ AN2 U2966 ( .A(n2969), .B(n2901), .Z(n2967));
+ OR2 U2967 ( .A(n2970), .B(n2971), .Z(n2969));
+ OR2 U2968 ( .A(n2972), .B(n2973), .Z(n2971));
+ AN2 U2969 ( .A(n2902), .B(n2962), .Z(n2973));
+ AN2 U2970 ( .A(n2974), .B(n2957), .Z(n2972));
+ AN2 U2971 ( .A(pi082), .B(po031), .Z(n2970));
+ AN2 U2972 ( .A(n2975), .B(n2886), .Z(n2963));
+ OR2 U2973 ( .A(n2976), .B(n2977), .Z(n2975));
+ AN2 U2974 ( .A(n2968), .B(n2947), .Z(n2977));
+ AN2 U2975 ( .A(n2978), .B(n2979), .Z(n2968));
+ OR2 U2976 ( .A(n2980), .B(n2981), .Z(n2979));
+ AN2 U2977 ( .A(n2982), .B(n2931), .Z(n2980));
+ AN2 U2978 ( .A(n2983), .B(n2929), .Z(n2976));
+ AN2 U2979 ( .A(n2984), .B(n2936), .Z(n2983));
+ AN2 U2980 ( .A(n2974), .B(n2901), .Z(n2984));
+ OR2 U2981 ( .A(n2985), .B(n2986), .Z(n2863));
+ AN2 U2982 ( .A(n2987), .B(n2890), .Z(n2986));
+ AN2 U2983 ( .A(n2988), .B(n2989), .Z(n2987));
+ AN2 U2984 ( .A(n2990), .B(n2962), .Z(n2989));
+ AN2 U2985 ( .A(n2862), .B(n2877), .Z(n2988));
+ AN2 U2986 ( .A(n2991), .B(n2886), .Z(n2985));
+ OR2 U2987 ( .A(n2992), .B(n2993), .Z(n2991));
+ AN2 U2988 ( .A(n2994), .B(n2995), .Z(n2993));
+ AN2 U2989 ( .A(n2990), .B(n2901), .Z(n2995));
+ AN2 U2990 ( .A(n2996), .B(n2974), .Z(n2994));
+ OR2 U2991 ( .A(po031), .B(n2930), .Z(n2996));
+ AN2 U2992 ( .A(n2997), .B(n2860), .Z(n2992));
+ AN2 U2993 ( .A(n2998), .B(n2930), .Z(n2860));
+ AN2 U2994 ( .A(n2877), .B(n2999), .Z(n2997));
+ IV2 U2995 ( .A(n2882), .Z(n2877));
+ AN2 U2996 ( .A(n3000), .B(n3001), .Z(n2852));
+ OR2 U2997 ( .A(n3002), .B(n2925), .Z(n3001));
+ OR2 U2998 ( .A(n3003), .B(n3004), .Z(n3000));
+ IV2 U2999 ( .A(n3002), .Z(n3004));
+ OR2 U3000 ( .A(n3005), .B(n3006), .Z(n3002));
+ AN2 U3001 ( .A(n3007), .B(n3008), .Z(n3006));
+ OR2 U3002 ( .A(n3009), .B(n3010), .Z(n3008));
+ AN2 U3003 ( .A(n3011), .B(n3012), .Z(n3009));
+ AN2 U3004 ( .A(n3013), .B(n3014), .Z(n3007));
+ OR2 U3005 ( .A(n3015), .B(n3016), .Z(n3014));
+ IV2 U3006 ( .A(n3017), .Z(n3016));
+ OR2 U3007 ( .A(n3017), .B(n3018), .Z(n3013));
+ OR2 U3008 ( .A(n3019), .B(n3020), .Z(n3017));
+ AN2 U3009 ( .A(n3021), .B(n3022), .Z(n3020));
+ OR2 U3010 ( .A(n3023), .B(n3024), .Z(n3022));
+ OR2 U3011 ( .A(n3025), .B(n3026), .Z(n3024));
+ OR2 U3012 ( .A(n3027), .B(n3028), .Z(n3026));
+ AN2 U3013 ( .A(po010), .B(n3029), .Z(n3028));
+ AN2 U3014 ( .A(n3030), .B(pi192), .Z(n3027));
+ AN2 U3015 ( .A(n3031), .B(n3032), .Z(n3030));
+ OR2 U3016 ( .A(n3033), .B(n3034), .Z(n3032));
+ AN2 U3017 ( .A(n3035), .B(n3036), .Z(n3034));
+ AN2 U3018 ( .A(n3015), .B(n3037), .Z(n3035));
+ OR2 U3019 ( .A(n3038), .B(n3039), .Z(n3031));
+ OR2 U3020 ( .A(n3040), .B(n3041), .Z(n3039));
+ AN2 U3021 ( .A(po010), .B(n3042), .Z(n3040));
+ OR2 U3022 ( .A(n3043), .B(n3044), .Z(n3025));
+ AN2 U3023 ( .A(n3015), .B(n3045), .Z(n3044));
+ OR2 U3024 ( .A(n3046), .B(n3047), .Z(n3045));
+ AN2 U3025 ( .A(n3048), .B(n3049), .Z(n3047));
+ OR2 U3026 ( .A(n3050), .B(n3051), .Z(n3048));
+ AN2 U3027 ( .A(n3052), .B(po070), .Z(n3051));
+ AN2 U3028 ( .A(n3053), .B(po099), .Z(n3050));
+ AN2 U3029 ( .A(n3054), .B(n3055), .Z(n3046));
+ AN2 U3030 ( .A(n3018), .B(n3056), .Z(n3043));
+ OR2 U3031 ( .A(n3057), .B(n3058), .Z(n3056));
+ OR2 U3032 ( .A(n3059), .B(n3060), .Z(n3058));
+ AN2 U3033 ( .A(n3061), .B(n3042), .Z(n3060));
+ AN2 U3034 ( .A(n3062), .B(n3063), .Z(n3059));
+ AN2 U3035 ( .A(n3064), .B(n3049), .Z(n3062));
+ AN2 U3036 ( .A(n3065), .B(n3066), .Z(n3057));
+ OR2 U3037 ( .A(n3067), .B(n3068), .Z(n3023));
+ OR2 U3038 ( .A(n3069), .B(n3070), .Z(n3068));
+ AN2 U3039 ( .A(n3071), .B(n3072), .Z(n3070));
+ AN2 U3040 ( .A(n3053), .B(n3073), .Z(n3069));
+ OR2 U3041 ( .A(n3074), .B(n3075), .Z(n3067));
+ AN2 U3042 ( .A(n3076), .B(n3077), .Z(n3075));
+ OR2 U3043 ( .A(n3078), .B(n3079), .Z(n3077));
+ AN2 U3044 ( .A(n3080), .B(n3066), .Z(n3078));
+ AN2 U3045 ( .A(n3081), .B(n3061), .Z(n3074));
+ AN2 U3046 ( .A(n3082), .B(n3038), .Z(n3081));
+ AN2 U3047 ( .A(n3083), .B(n3084), .Z(n3019));
+ OR2 U3048 ( .A(n3085), .B(n3086), .Z(n3084));
+ OR2 U3049 ( .A(n3087), .B(n3088), .Z(n3086));
+ OR2 U3050 ( .A(n3089), .B(n3090), .Z(n3088));
+ AN2 U3051 ( .A(n3091), .B(n3049), .Z(n3089));
+ OR2 U3052 ( .A(n3092), .B(n3093), .Z(n3087));
+ AN2 U3053 ( .A(n3015), .B(n3094), .Z(n3093));
+ OR2 U3054 ( .A(n3095), .B(n3096), .Z(n3094));
+ OR2 U3055 ( .A(n3097), .B(n3098), .Z(n3096));
+ AN2 U3056 ( .A(n3099), .B(n3100), .Z(n3098));
+ AN2 U3057 ( .A(po010), .B(po070), .Z(n3099));
+ AN2 U3058 ( .A(n3101), .B(pi192), .Z(n3097));
+ AN2 U3059 ( .A(n3041), .B(n3038), .Z(n3101));
+ OR2 U3060 ( .A(n3102), .B(n3103), .Z(n3041));
+ AN2 U3061 ( .A(n3104), .B(pi166), .Z(n3103));
+ AN2 U3062 ( .A(n3037), .B(n3049), .Z(n3104));
+ AN2 U3063 ( .A(n3105), .B(n3106), .Z(n3102));
+ OR2 U3064 ( .A(n3107), .B(n3042), .Z(n3105));
+ AN2 U3065 ( .A(po010), .B(n3108), .Z(n3107));
+ AN2 U3066 ( .A(n3079), .B(n3109), .Z(n3095));
+ OR2 U3067 ( .A(n3110), .B(n3111), .Z(n3079));
+ AN2 U3068 ( .A(n3071), .B(n3112), .Z(n3111));
+ AN2 U3069 ( .A(n3065), .B(n3113), .Z(n3110));
+ OR2 U3070 ( .A(n3114), .B(n3066), .Z(n3113));
+ AN2 U3071 ( .A(po010), .B(n3115), .Z(n3114));
+ AN2 U3072 ( .A(n3018), .B(n3116), .Z(n3092));
+ OR2 U3073 ( .A(n3117), .B(n3118), .Z(n3116));
+ AN2 U3074 ( .A(n3065), .B(n3119), .Z(n3118));
+ AN2 U3075 ( .A(n3063), .B(n3120), .Z(n3117));
+ OR2 U3076 ( .A(n3121), .B(n3122), .Z(n3085));
+ OR2 U3077 ( .A(n3123), .B(n3124), .Z(n3122));
+ AN2 U3078 ( .A(n3125), .B(n3055), .Z(n3124));
+ AN2 U3079 ( .A(n3076), .B(n3112), .Z(n3125));
+ AN2 U3080 ( .A(n3126), .B(n3127), .Z(n3123));
+ AN2 U3081 ( .A(n3033), .B(n3037), .Z(n3126));
+ AN2 U3082 ( .A(n3080), .B(n3072), .Z(n3121));
+ AN2 U3083 ( .A(n3119), .B(n3018), .Z(n3072));
+ AN2 U3084 ( .A(n3128), .B(n3129), .Z(n3005));
+ OR2 U3085 ( .A(n3130), .B(n3131), .Z(n3129));
+ OR2 U3086 ( .A(n3132), .B(n3133), .Z(n3131));
+ AN2 U3087 ( .A(n3134), .B(pi192), .Z(n3133));
+ AN2 U3088 ( .A(n3135), .B(n3136), .Z(n3134));
+ OR2 U3089 ( .A(n3137), .B(po044), .Z(n3135));
+ AN2 U3090 ( .A(n3138), .B(n2886), .Z(n3137));
+ AN2 U3091 ( .A(n3139), .B(n2837), .Z(n3132));
+ AN2 U3092 ( .A(n3140), .B(n3141), .Z(n3139));
+ OR2 U3093 ( .A(n3142), .B(po044), .Z(n3140));
+ AN2 U3094 ( .A(n3143), .B(n2886), .Z(n3142));
+ AN2 U3095 ( .A(n3144), .B(n3145), .Z(n3130));
+ OR2 U3096 ( .A(n3146), .B(n3147), .Z(n3145));
+ IV2 U3097 ( .A(n3012), .Z(n3144));
+ AN2 U3098 ( .A(n3148), .B(n3149), .Z(n3128));
+ OR2 U3099 ( .A(n3150), .B(n3018), .Z(n3149));
+ OR2 U3100 ( .A(n3015), .B(n3151), .Z(n3148));
+ IV2 U3101 ( .A(n3150), .Z(n3151));
+ OR2 U3102 ( .A(n3152), .B(n3153), .Z(n3150));
+ AN2 U3103 ( .A(n3021), .B(n3154), .Z(n3153));
+ AN2 U3104 ( .A(n3155), .B(n3083), .Z(n3152));
+ IV2 U3105 ( .A(n3154), .Z(n3155));
+ OR2 U3106 ( .A(n3156), .B(n3157), .Z(n3154));
+ OR2 U3107 ( .A(n3091), .B(n3158), .Z(n3157));
+ OR2 U3108 ( .A(n3159), .B(n3160), .Z(n3158));
+ AN2 U3109 ( .A(n3161), .B(n3049), .Z(n3160));
+ OR2 U3110 ( .A(n3162), .B(n3029), .Z(n3161));
+ OR2 U3111 ( .A(n3163), .B(n3164), .Z(n3029));
+ AN2 U3112 ( .A(po099), .B(n3165), .Z(n3164));
+ OR2 U3113 ( .A(n3166), .B(n3167), .Z(n3165));
+ OR2 U3114 ( .A(n3168), .B(n3169), .Z(n3167));
+ AN2 U3115 ( .A(n3170), .B(pi192), .Z(n3169));
+ AN2 U3116 ( .A(n3038), .B(n3171), .Z(n3170));
+ AN2 U3117 ( .A(n3054), .B(n2837), .Z(n3168));
+ AN2 U3118 ( .A(n3172), .B(n3173), .Z(n3166));
+ AN2 U3119 ( .A(n3015), .B(n3109), .Z(n3172));
+ AN2 U3120 ( .A(n3100), .B(n3018), .Z(n3163));
+ AN2 U3121 ( .A(n3015), .B(n3174), .Z(n3162));
+ OR2 U3122 ( .A(n3175), .B(n3176), .Z(n3174));
+ AN2 U3123 ( .A(n3054), .B(n3173), .Z(n3176));
+ AN2 U3124 ( .A(n3177), .B(n3109), .Z(n3054));
+ AN2 U3125 ( .A(n3178), .B(n3064), .Z(n3175));
+ AN2 U3126 ( .A(n3038), .B(n3037), .Z(n3178));
+ AN2 U3127 ( .A(po010), .B(n3179), .Z(n3159));
+ OR2 U3128 ( .A(n3090), .B(n3180), .Z(n3179));
+ OR2 U3129 ( .A(n3181), .B(n3182), .Z(n3180));
+ AN2 U3130 ( .A(n3053), .B(n3183), .Z(n3182));
+ OR2 U3131 ( .A(n3184), .B(n3119), .Z(n3183));
+ AN2 U3132 ( .A(pi141), .B(n3015), .Z(n3184));
+ AN2 U3133 ( .A(n3109), .B(n3065), .Z(n3053));
+ AN2 U3134 ( .A(n3185), .B(n3061), .Z(n3181));
+ AN2 U3135 ( .A(n3186), .B(n3038), .Z(n3185));
+ OR2 U3136 ( .A(n3187), .B(n3063), .Z(n3186));
+ AN2 U3137 ( .A(pi033), .B(n3015), .Z(n3187));
+ OR2 U3138 ( .A(n3188), .B(n3189), .Z(n3090));
+ AN2 U3139 ( .A(n3190), .B(n3065), .Z(n3189));
+ AN2 U3140 ( .A(n3073), .B(n3076), .Z(n3190));
+ AN2 U3141 ( .A(n3191), .B(n3061), .Z(n3188));
+ AN2 U3142 ( .A(n3082), .B(n3033), .Z(n3191));
+ OR2 U3143 ( .A(n3192), .B(n3193), .Z(n3091));
+ OR2 U3144 ( .A(n3194), .B(n3195), .Z(n3193));
+ AN2 U3145 ( .A(n3052), .B(n3018), .Z(n3195));
+ AN2 U3146 ( .A(n3064), .B(n3196), .Z(n3194));
+ OR2 U3147 ( .A(n3197), .B(n3198), .Z(n3196));
+ AN2 U3148 ( .A(n3082), .B(n3199), .Z(n3198));
+ AN2 U3149 ( .A(n3042), .B(n3033), .Z(n3197));
+ OR2 U3150 ( .A(n3200), .B(n3201), .Z(n3192));
+ AN2 U3151 ( .A(n3173), .B(n3202), .Z(n3201));
+ OR2 U3152 ( .A(n3203), .B(n3204), .Z(n3202));
+ AN2 U3153 ( .A(n3073), .B(n3205), .Z(n3204));
+ AN2 U3154 ( .A(n3076), .B(n3066), .Z(n3203));
+ AN2 U3155 ( .A(n3206), .B(po099), .Z(n3200));
+ AN2 U3156 ( .A(po070), .B(n3207), .Z(n3206));
+ OR2 U3157 ( .A(n3208), .B(n3209), .Z(n3156));
+ AN2 U3158 ( .A(n3210), .B(n3055), .Z(n3209));
+ AN2 U3159 ( .A(n3076), .B(n3115), .Z(n3210));
+ AN2 U3160 ( .A(n3211), .B(n3127), .Z(n3208));
+ AN2 U3161 ( .A(n3033), .B(n3108), .Z(n3211));
+ OR2 U3162 ( .A(n3212), .B(n3213), .Z(po098));
+ AN2 U3163 ( .A(n3214), .B(pi192), .Z(n3213));
+ OR2 U3164 ( .A(n3215), .B(n3216), .Z(n3214));
+ AN2 U3165 ( .A(n2832), .B(n2901), .Z(n3216));
+ IV2 U3166 ( .A(n2835), .Z(n2832));
+ AN2 U3167 ( .A(pi200), .B(n2835), .Z(n3215));
+ OR2 U3168 ( .A(n2880), .B(n2876), .Z(n2835));
+ AN2 U3169 ( .A(n3217), .B(n2837), .Z(n3212));
+ OR2 U3170 ( .A(n3218), .B(n3219), .Z(n3217));
+ AN2 U3171 ( .A(n3220), .B(n2847), .Z(n3219));
+ OR2 U3172 ( .A(n3221), .B(n2902), .Z(n3220));
+ AN2 U3173 ( .A(pi200), .B(n2938), .Z(n3221));
+ AN2 U3174 ( .A(n2844), .B(n3222), .Z(n3218));
+ IV2 U3175 ( .A(n2847), .Z(n2844));
+ OR2 U3176 ( .A(n2936), .B(n2978), .Z(n2847));
+ OR2 U3177 ( .A(n3223), .B(n3224), .Z(po097));
+ AN2 U3178 ( .A(n3225), .B(n3226), .Z(n3224));
+ OR2 U3179 ( .A(n3227), .B(n3228), .Z(n3226));
+ OR2 U3180 ( .A(n3229), .B(n3230), .Z(n3228));
+ OR2 U3181 ( .A(n3231), .B(n3232), .Z(n3230));
+ AN2 U3182 ( .A(n3233), .B(n3234), .Z(n3232));
+ AN2 U3183 ( .A(n3235), .B(n3236), .Z(n3231));
+ OR2 U3184 ( .A(n3237), .B(n3238), .Z(n3227));
+ OR2 U3185 ( .A(n3239), .B(n3240), .Z(n3238));
+ AN2 U3186 ( .A(n3241), .B(n3242), .Z(n3240));
+ AN2 U3187 ( .A(n3243), .B(n3244), .Z(n3239));
+ AN2 U3188 ( .A(po082), .B(n3245), .Z(n3237));
+ AN2 U3189 ( .A(n3246), .B(n3247), .Z(n3223));
+ OR2 U3190 ( .A(n3248), .B(n3249), .Z(n3246));
+ AN2 U3191 ( .A(n3250), .B(n3251), .Z(n3249));
+ OR2 U3192 ( .A(n3252), .B(n3253), .Z(po096));
+ AN2 U3193 ( .A(n3254), .B(n3255), .Z(n3252));
+ OR2 U3194 ( .A(n3256), .B(n3257), .Z(n3254));
+ AN2 U3195 ( .A(n3258), .B(n3259), .Z(n3256));
+ AN2 U3196 ( .A(n3260), .B(n3261), .Z(n3258));
+ OR2 U3197 ( .A(n3262), .B(n3263), .Z(n3260));
+ AN2 U3198 ( .A(n3264), .B(n3265), .Z(n3262));
+ OR2 U3199 ( .A(n3266), .B(n3267), .Z(po095));
+ OR2 U3200 ( .A(n3268), .B(n3269), .Z(n3267));
+ AN2 U3201 ( .A(n3270), .B(n3119), .Z(n3269));
+ OR2 U3202 ( .A(n3271), .B(n3272), .Z(n3270));
+ AN2 U3203 ( .A(n3273), .B(n2837), .Z(n3272));
+ AN2 U3204 ( .A(n3065), .B(n3274), .Z(n3271));
+ AN2 U3205 ( .A(n3063), .B(n3275), .Z(n3268));
+ OR2 U3206 ( .A(n3276), .B(n3277), .Z(n3275));
+ AN2 U3207 ( .A(n3273), .B(pi192), .Z(n3277));
+ AN2 U3208 ( .A(n3061), .B(n3274), .Z(n3276));
+ OR2 U3209 ( .A(n3278), .B(n3279), .Z(n3266));
+ AN2 U3210 ( .A(n3280), .B(n3281), .Z(n3279));
+ OR2 U3211 ( .A(n3282), .B(n3100), .Z(n3281));
+ AN2 U3212 ( .A(n3283), .B(n3284), .Z(n3278));
+ OR2 U3213 ( .A(n3285), .B(n3052), .Z(n3283));
+ AN2 U3214 ( .A(n3286), .B(n3287), .Z(n3052));
+ AN2 U3215 ( .A(po099), .B(n3207), .Z(n3285));
+ AN2 U3216 ( .A(n3288), .B(n3289), .Z(po094));
+ OR2 U3217 ( .A(n3290), .B(n3291), .Z(n3289));
+ OR2 U3218 ( .A(n3234), .B(n3292), .Z(n3288));
+ OR2 U3219 ( .A(n3293), .B(n3294), .Z(po093));
+ AN2 U3220 ( .A(n3295), .B(n3296), .Z(n3294));
+ OR2 U3221 ( .A(n3297), .B(n3298), .Z(n3296));
+ AN2 U3222 ( .A(n3299), .B(n3300), .Z(n3297));
+ AN2 U3223 ( .A(n3301), .B(n3302), .Z(n3293));
+ IV2 U3224 ( .A(n3303), .Z(n3302));
+ AN2 U3225 ( .A(n3304), .B(n3299), .Z(n3303));
+ OR2 U3226 ( .A(n3305), .B(n3306), .Z(n3299));
+ OR2 U3227 ( .A(n3300), .B(n3298), .Z(n3304));
+ AN2 U3228 ( .A(n3305), .B(n3306), .Z(n3298));
+ OR2 U3229 ( .A(n3307), .B(n3308), .Z(po090));
+ OR2 U3230 ( .A(n3309), .B(n3310), .Z(n3308));
+ AN2 U3231 ( .A(n3311), .B(n3312), .Z(n3310));
+ AN2 U3232 ( .A(n3313), .B(n3314), .Z(n3309));
+ OR2 U3233 ( .A(n3315), .B(n3316), .Z(n3313));
+ OR2 U3234 ( .A(n3317), .B(n3318), .Z(n3316));
+ AN2 U3235 ( .A(n3319), .B(n3320), .Z(n3315));
+ OR2 U3236 ( .A(n3321), .B(n3322), .Z(n3319));
+ OR2 U3237 ( .A(n3323), .B(n3324), .Z(n3307));
+ AN2 U3238 ( .A(n3325), .B(n3326), .Z(n3324));
+ AN2 U3239 ( .A(n3327), .B(n3328), .Z(n3323));
+ OR2 U3240 ( .A(n3329), .B(n3330), .Z(n3327));
+ OR2 U3241 ( .A(n3331), .B(n3332), .Z(po088));
+ IV2 U3242 ( .A(n3333), .Z(n3332));
+ OR2 U3243 ( .A(n3334), .B(n3335), .Z(n3333));
+ AN2 U3244 ( .A(n3335), .B(n3334), .Z(n3331));
+ AN2 U3245 ( .A(n3336), .B(n3337), .Z(n3334));
+ OR2 U3246 ( .A(n3338), .B(n3339), .Z(n3337));
+ IV2 U3247 ( .A(n3340), .Z(n3338));
+ OR2 U3248 ( .A(n3341), .B(n3340), .Z(n3336));
+ OR2 U3249 ( .A(n3342), .B(n3343), .Z(n3340));
+ AN2 U3250 ( .A(n3291), .B(n3250), .Z(n3343));
+ AN2 U3251 ( .A(n3344), .B(n3292), .Z(n3342));
+ OR2 U3252 ( .A(n3345), .B(n3346), .Z(n3335));
+ IV2 U3253 ( .A(n3347), .Z(n3346));
+ OR2 U3254 ( .A(n3348), .B(n3349), .Z(n3347));
+ AN2 U3255 ( .A(n3349), .B(n3348), .Z(n3345));
+ AN2 U3256 ( .A(n3350), .B(n3351), .Z(n3348));
+ OR2 U3257 ( .A(n3352), .B(n3353), .Z(n3351));
+ IV2 U3258 ( .A(n3354), .Z(n3353));
+ OR2 U3259 ( .A(n3354), .B(n3355), .Z(n3350));
+ OR2 U3260 ( .A(n3356), .B(n3357), .Z(n3354));
+ OR2 U3261 ( .A(n3358), .B(n3359), .Z(n3357));
+ AN2 U3262 ( .A(n3360), .B(n3361), .Z(n3359));
+ AN2 U3263 ( .A(n3362), .B(n3363), .Z(n3360));
+ OR2 U3264 ( .A(n3364), .B(n3365), .Z(n3362));
+ OR2 U3265 ( .A(n3366), .B(n3367), .Z(n3365));
+ AN2 U3266 ( .A(n3368), .B(n3369), .Z(n3367));
+ AN2 U3267 ( .A(n3370), .B(n3371), .Z(n3368));
+ AN2 U3268 ( .A(n3372), .B(n3373), .Z(n3366));
+ AN2 U3269 ( .A(n3374), .B(n3375), .Z(n3372));
+ OR2 U3270 ( .A(n3376), .B(n3377), .Z(n3374));
+ OR2 U3271 ( .A(n3378), .B(n3379), .Z(n3377));
+ AN2 U3272 ( .A(n2837), .B(n3380), .Z(n3379));
+ AN2 U3273 ( .A(pi060), .B(n3381), .Z(n3378));
+ AN2 U3274 ( .A(n3382), .B(n3369), .Z(n3364));
+ AN2 U3275 ( .A(n3369), .B(n3383), .Z(n3358));
+ OR2 U3276 ( .A(n3384), .B(n3385), .Z(n3383));
+ OR2 U3277 ( .A(n3386), .B(n3387), .Z(n3385));
+ AN2 U3278 ( .A(n3370), .B(n3388), .Z(n3387));
+ OR2 U3279 ( .A(n3389), .B(n3390), .Z(n3388));
+ AN2 U3280 ( .A(n3391), .B(n3392), .Z(n3390));
+ AN2 U3281 ( .A(n3393), .B(n3394), .Z(n3386));
+ OR2 U3282 ( .A(n3395), .B(n3396), .Z(n3394));
+ OR2 U3283 ( .A(n3321), .B(n3397), .Z(n3396));
+ AN2 U3284 ( .A(n3398), .B(n3399), .Z(n3397));
+ AN2 U3285 ( .A(n3400), .B(n3401), .Z(n3395));
+ OR2 U3286 ( .A(n3402), .B(n3371), .Z(n3400));
+ AN2 U3287 ( .A(n3403), .B(n3404), .Z(n3402));
+ AN2 U3288 ( .A(pi060), .B(po071), .Z(n3403));
+ OR2 U3289 ( .A(n3405), .B(n3406), .Z(n3384));
+ AN2 U3290 ( .A(n3407), .B(n3363), .Z(n3406));
+ AN2 U3291 ( .A(n3408), .B(n3401), .Z(n3407));
+ OR2 U3292 ( .A(n3409), .B(n3410), .Z(n3408));
+ AN2 U3293 ( .A(n3411), .B(n3412), .Z(n3409));
+ OR2 U3294 ( .A(n3413), .B(n3414), .Z(n3411));
+ AN2 U3295 ( .A(n3415), .B(n3370), .Z(n3414));
+ OR2 U3296 ( .A(n3416), .B(n3417), .Z(n3415));
+ AN2 U3297 ( .A(n3418), .B(n3381), .Z(n3413));
+ AN2 U3298 ( .A(n3393), .B(n3419), .Z(n3418));
+ AN2 U3299 ( .A(n3420), .B(po027), .Z(n3405));
+ OR2 U3300 ( .A(n3421), .B(n3422), .Z(n3420));
+ OR2 U3301 ( .A(n3423), .B(n3424), .Z(n3422));
+ AN2 U3302 ( .A(n3410), .B(n3361), .Z(n3424));
+ IV2 U3303 ( .A(n3425), .Z(n3410));
+ AN2 U3304 ( .A(n3426), .B(n3401), .Z(n3423));
+ OR2 U3305 ( .A(n3427), .B(n3382), .Z(n3426));
+ IV2 U3306 ( .A(n3428), .Z(n3382));
+ OR2 U3307 ( .A(n3429), .B(n3430), .Z(n3421));
+ AN2 U3308 ( .A(n3431), .B(n3370), .Z(n3430));
+ AN2 U3309 ( .A(n3393), .B(n3432), .Z(n3429));
+ OR2 U3310 ( .A(n3433), .B(n3434), .Z(n3432));
+ AN2 U3311 ( .A(po071), .B(n3419), .Z(n3434));
+ IV2 U3312 ( .A(n3435), .Z(n3369));
+ OR2 U3313 ( .A(n3436), .B(n3375), .Z(n3435));
+ AN2 U3314 ( .A(n3437), .B(n3438), .Z(n3436));
+ AN2 U3315 ( .A(n3439), .B(n3440), .Z(n3438));
+ OR2 U3316 ( .A(n3361), .B(n3441), .Z(n3440));
+ AN2 U3317 ( .A(n3442), .B(n3443), .Z(n3441));
+ OR2 U3318 ( .A(n3444), .B(n3445), .Z(n3443));
+ OR2 U3319 ( .A(n3370), .B(n3446), .Z(n3445));
+ OR2 U3320 ( .A(n3371), .B(n3380), .Z(n3444));
+ AN2 U3321 ( .A(n3447), .B(n3448), .Z(n3442));
+ OR2 U3322 ( .A(po027), .B(n3449), .Z(n3448));
+ AN2 U3323 ( .A(n3450), .B(n3428), .Z(n3449));
+ OR2 U3324 ( .A(n3371), .B(n3451), .Z(n3428));
+ OR2 U3325 ( .A(n3370), .B(n3412), .Z(n3450));
+ OR2 U3326 ( .A(n3363), .B(n3425), .Z(n3447));
+ OR2 U3327 ( .A(n3427), .B(n3452), .Z(n3425));
+ AN2 U3328 ( .A(n3453), .B(n3412), .Z(n3452));
+ AN2 U3329 ( .A(n3371), .B(n3451), .Z(n3427));
+ OR2 U3330 ( .A(n3401), .B(n3454), .Z(n3439));
+ IV2 U3331 ( .A(n3455), .Z(n3454));
+ AN2 U3332 ( .A(n3412), .B(n3456), .Z(n3455));
+ OR2 U3333 ( .A(n3457), .B(n3458), .Z(n3456));
+ AN2 U3334 ( .A(n3392), .B(n3393), .Z(n3458));
+ AN2 U3335 ( .A(n3459), .B(n3460), .Z(n3437));
+ OR2 U3336 ( .A(n3457), .B(n3461), .Z(n3460));
+ AN2 U3337 ( .A(n3462), .B(n3463), .Z(n3459));
+ OR2 U3338 ( .A(n3464), .B(n3370), .Z(n3463));
+ IV2 U3339 ( .A(n3465), .Z(n3464));
+ OR2 U3340 ( .A(n3389), .B(n3431), .Z(n3465));
+ AN2 U3341 ( .A(n3466), .B(n3419), .Z(n3431));
+ AN2 U3342 ( .A(n3467), .B(n3468), .Z(n3389));
+ IV2 U3343 ( .A(n3469), .Z(n3468));
+ OR2 U3344 ( .A(n3417), .B(n3470), .Z(n3469));
+ AN2 U3345 ( .A(n3471), .B(n3399), .Z(n3470));
+ OR2 U3346 ( .A(n3371), .B(n3446), .Z(n3471));
+ OR2 U3347 ( .A(n3472), .B(n3393), .Z(n3462));
+ AN2 U3348 ( .A(n3473), .B(n3474), .Z(n3472));
+ AN2 U3349 ( .A(n3475), .B(n3476), .Z(n3474));
+ OR2 U3350 ( .A(n3412), .B(n3477), .Z(n3476));
+ AN2 U3351 ( .A(n3478), .B(n3261), .Z(n3475));
+ IV2 U3352 ( .A(n3479), .Z(n3478));
+ AN2 U3353 ( .A(n3361), .B(n3480), .Z(n3479));
+ AN2 U3354 ( .A(n3481), .B(n3482), .Z(n3473));
+ OR2 U3355 ( .A(n3483), .B(n3380), .Z(n3482));
+ AN2 U3356 ( .A(n3484), .B(n3461), .Z(n3483));
+ OR2 U3357 ( .A(n3371), .B(n3485), .Z(n3484));
+ IV2 U3358 ( .A(n3433), .Z(n3481));
+ OR2 U3359 ( .A(n3486), .B(n3417), .Z(n3433));
+ AN2 U3360 ( .A(n3404), .B(n3381), .Z(n3417));
+ AN2 U3361 ( .A(n3487), .B(n3380), .Z(n3486));
+ AN2 U3362 ( .A(n3488), .B(n3375), .Z(n3356));
+ OR2 U3363 ( .A(n3489), .B(n3490), .Z(n3375));
+ AN2 U3364 ( .A(n3225), .B(n3491), .Z(n3489));
+ OR2 U3365 ( .A(n3492), .B(n3493), .Z(n3491));
+ AN2 U3366 ( .A(n3494), .B(n3495), .Z(n3492));
+ OR2 U3367 ( .A(n3496), .B(n3497), .Z(n3488));
+ OR2 U3368 ( .A(n3498), .B(n3499), .Z(n3497));
+ AN2 U3369 ( .A(n3371), .B(n3500), .Z(n3499));
+ OR2 U3370 ( .A(n3501), .B(n3502), .Z(n3500));
+ OR2 U3371 ( .A(n3503), .B(n3504), .Z(n3502));
+ AN2 U3372 ( .A(n3505), .B(n3401), .Z(n3504));
+ OR2 U3373 ( .A(n3506), .B(n3507), .Z(n3505));
+ AN2 U3374 ( .A(n3508), .B(n3509), .Z(n3507));
+ OR2 U3375 ( .A(n3510), .B(n3511), .Z(n3509));
+ OR2 U3376 ( .A(n3398), .B(n3487), .Z(n3511));
+ AN2 U3377 ( .A(n3512), .B(n2837), .Z(n3487));
+ AN2 U3378 ( .A(n3404), .B(pi060), .Z(n3510));
+ AN2 U3379 ( .A(n3513), .B(po027), .Z(n3506));
+ AN2 U3380 ( .A(n3514), .B(n3515), .Z(n3513));
+ OR2 U3381 ( .A(n3516), .B(n3517), .Z(n3515));
+ OR2 U3382 ( .A(n3321), .B(n3373), .Z(n3514));
+ AN2 U3383 ( .A(n3518), .B(n3467), .Z(n3503));
+ AN2 U3384 ( .A(n3404), .B(n3519), .Z(n3518));
+ OR2 U3385 ( .A(n3520), .B(n3521), .Z(n3501));
+ AN2 U3386 ( .A(n3522), .B(n3517), .Z(n3521));
+ AN2 U3387 ( .A(n3516), .B(n3363), .Z(n3522));
+ AN2 U3388 ( .A(n3373), .B(n3523), .Z(n3520));
+ OR2 U3389 ( .A(n3524), .B(n3525), .Z(n3523));
+ AN2 U3390 ( .A(n3361), .B(n3526), .Z(n3524));
+ OR2 U3391 ( .A(n3527), .B(n3321), .Z(n3526));
+ AN2 U3392 ( .A(n3519), .B(n3528), .Z(n3498));
+ OR2 U3393 ( .A(n3529), .B(n3530), .Z(n3528));
+ OR2 U3394 ( .A(n3392), .B(n3531), .Z(n3530));
+ AN2 U3395 ( .A(n3376), .B(n3412), .Z(n3531));
+ OR2 U3396 ( .A(n3532), .B(n3321), .Z(n3376));
+ AN2 U3397 ( .A(n3533), .B(n3399), .Z(n3532));
+ AN2 U3398 ( .A(n3534), .B(n3381), .Z(n3529));
+ OR2 U3399 ( .A(n3535), .B(n3536), .Z(n3519));
+ AN2 U3400 ( .A(n3537), .B(po027), .Z(n3536));
+ AN2 U3401 ( .A(n3538), .B(n3363), .Z(n3535));
+ AN2 U3402 ( .A(n3517), .B(n3401), .Z(n3538));
+ OR2 U3403 ( .A(n3539), .B(n3540), .Z(n3496));
+ AN2 U3404 ( .A(n3541), .B(n3542), .Z(n3540));
+ OR2 U3405 ( .A(n3543), .B(n3544), .Z(n3542));
+ AN2 U3406 ( .A(n3453), .B(po071), .Z(n3544));
+ AN2 U3407 ( .A(n3480), .B(n3534), .Z(n3543));
+ AN2 U3408 ( .A(n3545), .B(n3546), .Z(n3541));
+ OR2 U3409 ( .A(n3361), .B(n3547), .Z(n3546));
+ AN2 U3410 ( .A(n3508), .B(n3412), .Z(n3547));
+ OR2 U3411 ( .A(n3401), .B(n3548), .Z(n3545));
+ IV2 U3412 ( .A(n3508), .Z(n3548));
+ OR2 U3413 ( .A(n3549), .B(n3550), .Z(n3508));
+ AN2 U3414 ( .A(n3373), .B(n3363), .Z(n3550));
+ AN2 U3415 ( .A(n3517), .B(po027), .Z(n3549));
+ AN2 U3416 ( .A(n3551), .B(n3467), .Z(n3539));
+ AN2 U3417 ( .A(n3552), .B(n3381), .Z(n3551));
+ OR2 U3418 ( .A(n3553), .B(n3554), .Z(n3552));
+ AN2 U3419 ( .A(n3537), .B(n3363), .Z(n3554));
+ AN2 U3420 ( .A(n3555), .B(po027), .Z(n3553));
+ IV2 U3421 ( .A(n3537), .Z(n3555));
+ OR2 U3422 ( .A(n3556), .B(n3557), .Z(n3537));
+ AN2 U3423 ( .A(n3373), .B(n3401), .Z(n3557));
+ AN2 U3424 ( .A(n3517), .B(n3361), .Z(n3556));
+ IV2 U3425 ( .A(n3373), .Z(n3517));
+ OR2 U3426 ( .A(n3558), .B(n3559), .Z(n3373));
+ AN2 U3427 ( .A(n3370), .B(n3560), .Z(n3559));
+ OR2 U3428 ( .A(n3561), .B(n3562), .Z(n3560));
+ OR2 U3429 ( .A(n3361), .B(n3563), .Z(n3562));
+ AN2 U3430 ( .A(n3321), .B(po027), .Z(n3563));
+ OR2 U3431 ( .A(n3564), .B(n3565), .Z(n3561));
+ OR2 U3432 ( .A(n3527), .B(n3566), .Z(n3565));
+ AN2 U3433 ( .A(po027), .B(n3398), .Z(n3527));
+ AN2 U3434 ( .A(n3404), .B(n3567), .Z(n3564));
+ AN2 U3435 ( .A(n3393), .B(n3568), .Z(n3558));
+ OR2 U3436 ( .A(n3569), .B(n3570), .Z(n3568));
+ AN2 U3437 ( .A(n3571), .B(n3401), .Z(n3570));
+ OR2 U3438 ( .A(n3516), .B(n3572), .Z(n3571));
+ AN2 U3439 ( .A(n3419), .B(n3363), .Z(n3572));
+ AN2 U3440 ( .A(po104), .B(n3453), .Z(n3516));
+ AN2 U3441 ( .A(n3573), .B(n3467), .Z(n3569));
+ AN2 U3442 ( .A(n3261), .B(n3533), .Z(n3467));
+ AN2 U3443 ( .A(n3404), .B(po027), .Z(n3573));
+ OR2 U3444 ( .A(n3574), .B(n3575), .Z(n3349));
+ AN2 U3445 ( .A(n3576), .B(n3247), .Z(n3575));
+ IV2 U3446 ( .A(n3577), .Z(n3576));
+ AN2 U3447 ( .A(n3225), .B(n3577), .Z(n3574));
+ OR2 U3448 ( .A(n3578), .B(n3579), .Z(n3577));
+ OR2 U3449 ( .A(n3580), .B(n3581), .Z(n3579));
+ OR2 U3450 ( .A(n3582), .B(n3583), .Z(n3581));
+ AN2 U3451 ( .A(n3584), .B(n2837), .Z(n3583));
+ OR2 U3452 ( .A(n3585), .B(n3586), .Z(n3584));
+ OR2 U3453 ( .A(n3587), .B(n3588), .Z(n3586));
+ AN2 U3454 ( .A(n3589), .B(n3590), .Z(n3588));
+ AN2 U3455 ( .A(n3591), .B(n3592), .Z(n3589));
+ OR2 U3456 ( .A(n3593), .B(n3355), .Z(n3592));
+ AN2 U3457 ( .A(n3594), .B(n3595), .Z(n3591));
+ OR2 U3458 ( .A(n3596), .B(n3597), .Z(n3595));
+ OR2 U3459 ( .A(pi003), .B(n3598), .Z(n3594));
+ AN2 U3460 ( .A(n3599), .B(n3600), .Z(n3587));
+ OR2 U3461 ( .A(n3601), .B(n3602), .Z(n3600));
+ OR2 U3462 ( .A(n3603), .B(n3604), .Z(n3602));
+ AN2 U3463 ( .A(n3605), .B(n3593), .Z(n3604));
+ AN2 U3464 ( .A(n3606), .B(n3607), .Z(n3603));
+ OR2 U3465 ( .A(n3608), .B(n3609), .Z(n3601));
+ AN2 U3466 ( .A(n3610), .B(pi003), .Z(n3609));
+ AN2 U3467 ( .A(n3611), .B(n3612), .Z(n3610));
+ AN2 U3468 ( .A(n3613), .B(n3597), .Z(n3608));
+ OR2 U3469 ( .A(n3614), .B(n3615), .Z(n3613));
+ AN2 U3470 ( .A(n3598), .B(n3616), .Z(n3615));
+ AN2 U3471 ( .A(n3617), .B(n3593), .Z(n3614));
+ AN2 U3472 ( .A(n3618), .B(n3619), .Z(n3585));
+ AN2 U3473 ( .A(n3620), .B(n3590), .Z(n3618));
+ OR2 U3474 ( .A(n3621), .B(n3622), .Z(n3620));
+ OR2 U3475 ( .A(n3494), .B(n3606), .Z(n3622));
+ AN2 U3476 ( .A(pi003), .B(n3623), .Z(n3606));
+ AN2 U3477 ( .A(n3616), .B(po011), .Z(n3623));
+ AN2 U3478 ( .A(n3624), .B(n3625), .Z(n3621));
+ AN2 U3479 ( .A(n3616), .B(n3597), .Z(n3624));
+ AN2 U3480 ( .A(pi192), .B(n3626), .Z(n3582));
+ OR2 U3481 ( .A(n3627), .B(n3628), .Z(n3626));
+ OR2 U3482 ( .A(n3629), .B(n3630), .Z(n3628));
+ AN2 U3483 ( .A(n3631), .B(n3632), .Z(n3630));
+ AN2 U3484 ( .A(n3633), .B(n3634), .Z(n3631));
+ OR2 U3485 ( .A(n3635), .B(n3355), .Z(n3634));
+ AN2 U3486 ( .A(n3636), .B(n3637), .Z(n3633));
+ OR2 U3487 ( .A(n3596), .B(n3638), .Z(n3637));
+ AN2 U3488 ( .A(n3639), .B(n3339), .Z(n3596));
+ OR2 U3489 ( .A(pi098), .B(n3598), .Z(n3636));
+ AN2 U3490 ( .A(n3640), .B(n3641), .Z(n3629));
+ OR2 U3491 ( .A(n3642), .B(n3643), .Z(n3641));
+ OR2 U3492 ( .A(n3644), .B(n3645), .Z(n3643));
+ AN2 U3493 ( .A(n3605), .B(n3635), .Z(n3645));
+ OR2 U3494 ( .A(n3646), .B(n3647), .Z(n3605));
+ AN2 U3495 ( .A(n3648), .B(n3493), .Z(n3647));
+ AN2 U3496 ( .A(n3341), .B(n3639), .Z(n3646));
+ AN2 U3497 ( .A(n3649), .B(n3607), .Z(n3644));
+ OR2 U3498 ( .A(n3650), .B(n3651), .Z(n3642));
+ AN2 U3499 ( .A(n3652), .B(pi098), .Z(n3651));
+ AN2 U3500 ( .A(n3653), .B(n3612), .Z(n3652));
+ AN2 U3501 ( .A(n3654), .B(n3638), .Z(n3650));
+ OR2 U3502 ( .A(n3655), .B(n3656), .Z(n3654));
+ AN2 U3503 ( .A(n3598), .B(n3657), .Z(n3656));
+ OR2 U3504 ( .A(n3658), .B(n3659), .Z(n3598));
+ AN2 U3505 ( .A(n3660), .B(n3493), .Z(n3659));
+ AN2 U3506 ( .A(po011), .B(n3612), .Z(n3660));
+ AN2 U3507 ( .A(n3625), .B(n3661), .Z(n3658));
+ AN2 U3508 ( .A(n3617), .B(n3635), .Z(n3655));
+ AN2 U3509 ( .A(n3625), .B(n3493), .Z(n3617));
+ AN2 U3510 ( .A(n3662), .B(n3619), .Z(n3627));
+ AN2 U3511 ( .A(n3663), .B(n3632), .Z(n3662));
+ OR2 U3512 ( .A(n3664), .B(n3665), .Z(n3663));
+ OR2 U3513 ( .A(n3494), .B(n3649), .Z(n3665));
+ AN2 U3514 ( .A(pi098), .B(n3666), .Z(n3649));
+ AN2 U3515 ( .A(n3657), .B(po011), .Z(n3666));
+ AN2 U3516 ( .A(n3612), .B(n3667), .Z(n3494));
+ AN2 U3517 ( .A(n3668), .B(n3625), .Z(n3664));
+ AN2 U3518 ( .A(n3657), .B(n3638), .Z(n3668));
+ OR2 U3519 ( .A(n3669), .B(n3670), .Z(n3580));
+ AN2 U3520 ( .A(n3671), .B(po011), .Z(n3670));
+ AN2 U3521 ( .A(n3672), .B(n3612), .Z(n3671));
+ AN2 U3522 ( .A(n3673), .B(n3674), .Z(n3672));
+ OR2 U3523 ( .A(pi192), .B(n3675), .Z(n3674));
+ AN2 U3524 ( .A(n3676), .B(n3597), .Z(n3675));
+ OR2 U3525 ( .A(n3677), .B(n3678), .Z(n3676));
+ AN2 U3526 ( .A(n3679), .B(n3680), .Z(n3677));
+ AN2 U3527 ( .A(n3599), .B(n3661), .Z(n3679));
+ OR2 U3528 ( .A(n2837), .B(n3681), .Z(n3673));
+ AN2 U3529 ( .A(n3682), .B(n3638), .Z(n3681));
+ OR2 U3530 ( .A(n3683), .B(n3684), .Z(n3682));
+ AN2 U3531 ( .A(n3685), .B(n3686), .Z(n3683));
+ AN2 U3532 ( .A(n3640), .B(n3661), .Z(n3685));
+ AN2 U3533 ( .A(n3687), .B(n3688), .Z(n3669));
+ OR2 U3534 ( .A(n3689), .B(n3690), .Z(n3687));
+ OR2 U3535 ( .A(n3691), .B(n3692), .Z(n3690));
+ AN2 U3536 ( .A(n3693), .B(n3612), .Z(n3692));
+ AN2 U3537 ( .A(n3619), .B(n3694), .Z(n3693));
+ OR2 U3538 ( .A(n3695), .B(n3696), .Z(n3694));
+ OR2 U3539 ( .A(n3697), .B(n3698), .Z(n3696));
+ AN2 U3540 ( .A(n3699), .B(n3616), .Z(n3698));
+ AN2 U3541 ( .A(n3700), .B(n3657), .Z(n3697));
+ AN2 U3542 ( .A(n3341), .B(n3701), .Z(n3695));
+ AN2 U3543 ( .A(n3493), .B(n3352), .Z(n3619));
+ AN2 U3544 ( .A(n3625), .B(n3702), .Z(n3691));
+ OR2 U3545 ( .A(n3703), .B(n3704), .Z(n3702));
+ AN2 U3546 ( .A(n3705), .B(n3706), .Z(n3704));
+ OR2 U3547 ( .A(n3684), .B(n3707), .Z(n3706));
+ OR2 U3548 ( .A(n3708), .B(n3709), .Z(n3707));
+ AN2 U3549 ( .A(n3710), .B(n3640), .Z(n3709));
+ OR2 U3550 ( .A(n3711), .B(n3712), .Z(n3710));
+ AN2 U3551 ( .A(n3607), .B(n3686), .Z(n3712));
+ AN2 U3552 ( .A(n3493), .B(n3713), .Z(n3711));
+ IV2 U3553 ( .A(n3686), .Z(n3713));
+ AN2 U3554 ( .A(n3653), .B(n3632), .Z(n3708));
+ OR2 U3555 ( .A(n3714), .B(n3715), .Z(n3653));
+ AN2 U3556 ( .A(n3686), .B(n3493), .Z(n3714));
+ AN2 U3557 ( .A(n3635), .B(n3339), .Z(n3686));
+ AN2 U3558 ( .A(n3607), .B(n3716), .Z(n3684));
+ AN2 U3559 ( .A(n3632), .B(n3657), .Z(n3716));
+ AN2 U3560 ( .A(n3717), .B(n3718), .Z(n3703));
+ OR2 U3561 ( .A(n3678), .B(n3719), .Z(n3718));
+ OR2 U3562 ( .A(n3720), .B(n3721), .Z(n3719));
+ AN2 U3563 ( .A(n3722), .B(n3599), .Z(n3721));
+ OR2 U3564 ( .A(n3723), .B(n3724), .Z(n3722));
+ AN2 U3565 ( .A(n3680), .B(n3607), .Z(n3724));
+ AN2 U3566 ( .A(n3493), .B(n3725), .Z(n3723));
+ IV2 U3567 ( .A(n3680), .Z(n3725));
+ AN2 U3568 ( .A(n3611), .B(n3590), .Z(n3720));
+ OR2 U3569 ( .A(n3726), .B(n3715), .Z(n3611));
+ AN2 U3570 ( .A(n3341), .B(n3607), .Z(n3715));
+ AN2 U3571 ( .A(n3680), .B(n3493), .Z(n3726));
+ AN2 U3572 ( .A(n3593), .B(n3339), .Z(n3680));
+ AN2 U3573 ( .A(n3607), .B(n3727), .Z(n3678));
+ AN2 U3574 ( .A(n3590), .B(n3616), .Z(n3727));
+ AN2 U3575 ( .A(n3661), .B(n3352), .Z(n3607));
+ AN2 U3576 ( .A(n3639), .B(n3728), .Z(n3689));
+ OR2 U3577 ( .A(n3729), .B(n3730), .Z(n3728));
+ OR2 U3578 ( .A(n3731), .B(n3732), .Z(n3730));
+ AN2 U3579 ( .A(n3733), .B(pi192), .Z(n3732));
+ AN2 U3580 ( .A(n3640), .B(n3657), .Z(n3733));
+ AN2 U3581 ( .A(n3734), .B(n2837), .Z(n3731));
+ AN2 U3582 ( .A(n3599), .B(n3616), .Z(n3734));
+ IV2 U3583 ( .A(n3590), .Z(n3599));
+ AN2 U3584 ( .A(n3735), .B(n3355), .Z(n3729));
+ OR2 U3585 ( .A(n3339), .B(n3736), .Z(n3735));
+ OR2 U3586 ( .A(n3737), .B(n3738), .Z(n3578));
+ AN2 U3587 ( .A(n3355), .B(n3739), .Z(n3738));
+ OR2 U3588 ( .A(n3740), .B(n3741), .Z(n3739));
+ AN2 U3589 ( .A(n3742), .B(n3625), .Z(n3741));
+ AN2 U3590 ( .A(n3743), .B(n3744), .Z(n3742));
+ OR2 U3591 ( .A(n3661), .B(n3688), .Z(n3744));
+ OR2 U3592 ( .A(po011), .B(n3745), .Z(n3743));
+ AN2 U3593 ( .A(n3493), .B(n3746), .Z(n3745));
+ AN2 U3594 ( .A(n3747), .B(n3639), .Z(n3740));
+ AN2 U3595 ( .A(n3661), .B(n3612), .Z(n3639));
+ AN2 U3596 ( .A(n3736), .B(n3746), .Z(n3747));
+ OR2 U3597 ( .A(n3292), .B(n3344), .Z(n3736));
+ IV2 U3598 ( .A(n3291), .Z(n3292));
+ AN2 U3599 ( .A(n3748), .B(n3648), .Z(n3737));
+ OR2 U3600 ( .A(n3749), .B(n3750), .Z(n3648));
+ AN2 U3601 ( .A(n3625), .B(po011), .Z(n3750));
+ IV2 U3602 ( .A(n3612), .Z(n3625));
+ AN2 U3603 ( .A(n3751), .B(n3688), .Z(n3749));
+ AN2 U3604 ( .A(n3339), .B(n3612), .Z(n3751));
+ OR2 U3605 ( .A(n3752), .B(n3753), .Z(n3612));
+ OR2 U3606 ( .A(n3754), .B(n3755), .Z(n3753));
+ AN2 U3607 ( .A(n3756), .B(n3757), .Z(n3755));
+ OR2 U3608 ( .A(n3758), .B(n3759), .Z(n3752));
+ AN2 U3609 ( .A(n3760), .B(n3761), .Z(n3759));
+ AN2 U3610 ( .A(n3661), .B(n3762), .Z(n3748));
+ OR2 U3611 ( .A(n3763), .B(n3764), .Z(po087));
+ OR2 U3612 ( .A(po042), .B(n3765), .Z(n3764));
+ OR2 U3613 ( .A(po029), .B(po022), .Z(n3765));
+ OR2 U3614 ( .A(n3766), .B(n3767), .Z(n3763));
+ OR2 U3615 ( .A(po080), .B(po056), .Z(n3767));
+ OR2 U3616 ( .A(po105), .B(po083), .Z(n3766));
+ IV2 U3617 ( .A(n3768), .Z(po105));
+ AN2 U3618 ( .A(n3769), .B(n3770), .Z(n3768));
+ AN2 U3619 ( .A(pi034), .B(pi007), .Z(n3770));
+ AN2 U3620 ( .A(pi139), .B(pi120), .Z(n3769));
+ OR2 U3621 ( .A(n3771), .B(n3772), .Z(po086));
+ AN2 U3622 ( .A(n3773), .B(n3774), .Z(n3772));
+ OR2 U3623 ( .A(n3775), .B(n3776), .Z(n3774));
+ AN2 U3624 ( .A(n3777), .B(n3778), .Z(n3771));
+ AN2 U3625 ( .A(n3779), .B(n3780), .Z(n3777));
+ OR2 U3626 ( .A(po025), .B(n3781), .Z(n3779));
+ IV2 U3627 ( .A(n3782), .Z(po083));
+ AN2 U3628 ( .A(n3783), .B(n3784), .Z(n3782));
+ AN2 U3629 ( .A(pi067), .B(pi041), .Z(n3784));
+ AN2 U3630 ( .A(pi104), .B(pi070), .Z(n3783));
+ OR2 U3631 ( .A(n3785), .B(n3786), .Z(po081));
+ AN2 U3632 ( .A(n2862), .B(n3787), .Z(n3786));
+ AN2 U3633 ( .A(n2930), .B(n3788), .Z(n3785));
+ OR2 U3634 ( .A(n3146), .B(n3789), .Z(n3788));
+ OR2 U3635 ( .A(n3790), .B(n3791), .Z(n3789));
+ AN2 U3636 ( .A(n3792), .B(n2901), .Z(n3791));
+ OR2 U3637 ( .A(n3793), .B(n3794), .Z(n3792));
+ AN2 U3638 ( .A(pi192), .B(n2887), .Z(n3794));
+ AN2 U3639 ( .A(n3795), .B(n2974), .Z(n3793));
+ OR2 U3640 ( .A(n3796), .B(po031), .Z(n3795));
+ AN2 U3641 ( .A(n2957), .B(n2837), .Z(n3796));
+ AN2 U3642 ( .A(n3797), .B(n2935), .Z(n3790));
+ AN2 U3643 ( .A(n2946), .B(n2837), .Z(n3797));
+ OR2 U3644 ( .A(n3798), .B(n3799), .Z(po080));
+ OR2 U3645 ( .A(n3800), .B(n3801), .Z(n3799));
+ OR2 U3646 ( .A(n3802), .B(n3803), .Z(n3801));
+ AN2 U3647 ( .A(n3804), .B(n2837), .Z(n3803));
+ OR2 U3648 ( .A(n3805), .B(n3806), .Z(n3804));
+ OR2 U3649 ( .A(n3807), .B(n3808), .Z(n3806));
+ AN2 U3650 ( .A(n3809), .B(n3810), .Z(n3808));
+ AN2 U3651 ( .A(n3811), .B(n3812), .Z(n3807));
+ AN2 U3652 ( .A(n3813), .B(n3814), .Z(n3805));
+ OR2 U3653 ( .A(n3815), .B(n3816), .Z(n3814));
+ OR2 U3654 ( .A(n3817), .B(n3818), .Z(n3813));
+ AN2 U3655 ( .A(pi192), .B(n3819), .Z(n3802));
+ OR2 U3656 ( .A(n3820), .B(n3821), .Z(n3819));
+ OR2 U3657 ( .A(n3822), .B(n3823), .Z(n3821));
+ AN2 U3658 ( .A(n3824), .B(n3825), .Z(n3823));
+ OR2 U3659 ( .A(n3826), .B(n3827), .Z(n3825));
+ IV2 U3660 ( .A(n3828), .Z(n3824));
+ AN2 U3661 ( .A(n3827), .B(n3826), .Z(n3828));
+ OR2 U3662 ( .A(n3829), .B(n3830), .Z(n3826));
+ AN2 U3663 ( .A(n3817), .B(n3171), .Z(n3830));
+ AN2 U3664 ( .A(n3816), .B(pi033), .Z(n3829));
+ IV2 U3665 ( .A(n3817), .Z(n3816));
+ OR2 U3666 ( .A(n3831), .B(n3832), .Z(n3817));
+ AN2 U3667 ( .A(n3833), .B(pi192), .Z(n3832));
+ OR2 U3668 ( .A(n3834), .B(n3835), .Z(n3833));
+ IV2 U3669 ( .A(n3836), .Z(n3835));
+ OR2 U3670 ( .A(n3837), .B(n3838), .Z(n3836));
+ AN2 U3671 ( .A(n3838), .B(n3837), .Z(n3834));
+ AN2 U3672 ( .A(n3839), .B(n3840), .Z(n3837));
+ OR2 U3673 ( .A(n3841), .B(pi013), .Z(n3840));
+ IV2 U3674 ( .A(n3842), .Z(n3841));
+ OR2 U3675 ( .A(n3843), .B(n3842), .Z(n3839));
+ OR2 U3676 ( .A(n3844), .B(n3845), .Z(n3842));
+ AN2 U3677 ( .A(pi026), .B(n3846), .Z(n3845));
+ AN2 U3678 ( .A(pi077), .B(n3847), .Z(n3844));
+ IV2 U3679 ( .A(pi013), .Z(n3843));
+ OR2 U3680 ( .A(n3848), .B(n3849), .Z(n3838));
+ AN2 U3681 ( .A(n3850), .B(n3136), .Z(n3849));
+ AN2 U3682 ( .A(n3851), .B(pi088), .Z(n3848));
+ IV2 U3683 ( .A(n3850), .Z(n3851));
+ OR2 U3684 ( .A(n3852), .B(n3853), .Z(n3850));
+ IV2 U3685 ( .A(n3854), .Z(n3853));
+ OR2 U3686 ( .A(n3855), .B(pi157), .Z(n3854));
+ AN2 U3687 ( .A(pi157), .B(n3855), .Z(n3852));
+ IV2 U3688 ( .A(pi137), .Z(n3855));
+ AN2 U3689 ( .A(n3856), .B(n3857), .Z(n3827));
+ OR2 U3690 ( .A(n3858), .B(pi096), .Z(n3857));
+ IV2 U3691 ( .A(n3859), .Z(n3858));
+ OR2 U3692 ( .A(n3859), .B(n3199), .Z(n3856));
+ OR2 U3693 ( .A(n3860), .B(n3861), .Z(n3859));
+ AN2 U3694 ( .A(pi166), .B(n3862), .Z(n3861));
+ IV2 U3695 ( .A(pi175), .Z(n3862));
+ AN2 U3696 ( .A(pi175), .B(n3106), .Z(n3860));
+ OR2 U3697 ( .A(n3863), .B(n3864), .Z(n3822));
+ AN2 U3698 ( .A(n3865), .B(n3866), .Z(n3864));
+ IV2 U3699 ( .A(n3867), .Z(n3863));
+ OR2 U3700 ( .A(n3866), .B(n3865), .Z(n3867));
+ OR2 U3701 ( .A(n3868), .B(n3869), .Z(n3865));
+ AN2 U3702 ( .A(n3811), .B(n3870), .Z(n3869));
+ IV2 U3703 ( .A(n3810), .Z(n3811));
+ AN2 U3704 ( .A(pi016), .B(n3810), .Z(n3868));
+ OR2 U3705 ( .A(n3871), .B(n3872), .Z(n3810));
+ OR2 U3706 ( .A(n3873), .B(n3874), .Z(n3872));
+ AN2 U3707 ( .A(n3875), .B(pi148), .Z(n3874));
+ OR2 U3708 ( .A(n3876), .B(n3877), .Z(n3875));
+ AN2 U3709 ( .A(n3878), .B(pi135), .Z(n3877));
+ AN2 U3710 ( .A(n3879), .B(n3880), .Z(n3876));
+ AN2 U3711 ( .A(n3881), .B(n3882), .Z(n3873));
+ IV2 U3712 ( .A(pi148), .Z(n3882));
+ OR2 U3713 ( .A(n3883), .B(n3884), .Z(n3881));
+ AN2 U3714 ( .A(n3879), .B(pi135), .Z(n3884));
+ OR2 U3715 ( .A(n3885), .B(n3886), .Z(n3879));
+ AN2 U3716 ( .A(n3887), .B(n3888), .Z(n3886));
+ AN2 U3717 ( .A(n3889), .B(n3890), .Z(n3885));
+ AN2 U3718 ( .A(n3878), .B(n3880), .Z(n3883));
+ OR2 U3719 ( .A(n3891), .B(n3892), .Z(n3878));
+ AN2 U3720 ( .A(n3887), .B(n3890), .Z(n3892));
+ AN2 U3721 ( .A(n3889), .B(n3888), .Z(n3891));
+ IV2 U3722 ( .A(n3887), .Z(n3889));
+ OR2 U3723 ( .A(n3893), .B(n3894), .Z(n3887));
+ AN2 U3724 ( .A(n3895), .B(n3896), .Z(n3894));
+ AN2 U3725 ( .A(n3897), .B(pi005), .Z(n3893));
+ IV2 U3726 ( .A(n3895), .Z(n3897));
+ OR2 U3727 ( .A(n3898), .B(n3899), .Z(n3895));
+ AN2 U3728 ( .A(pi069), .B(n3900), .Z(n3899));
+ IV2 U3729 ( .A(pi072), .Z(n3900));
+ AN2 U3730 ( .A(pi072), .B(n3901), .Z(n3898));
+ AN2 U3731 ( .A(n3902), .B(n3903), .Z(n3866));
+ OR2 U3732 ( .A(n3904), .B(pi045), .Z(n3903));
+ IV2 U3733 ( .A(n3905), .Z(n3902));
+ AN2 U3734 ( .A(n3904), .B(pi045), .Z(n3905));
+ AN2 U3735 ( .A(n3906), .B(n3907), .Z(n3904));
+ OR2 U3736 ( .A(n3908), .B(pi158), .Z(n3907));
+ OR2 U3737 ( .A(n3909), .B(pi079), .Z(n3906));
+ OR2 U3738 ( .A(n3910), .B(n3911), .Z(n3820));
+ AN2 U3739 ( .A(n3912), .B(n3913), .Z(n3911));
+ AN2 U3740 ( .A(n3534), .B(n3914), .Z(n3912));
+ AN2 U3741 ( .A(pi118), .B(n3915), .Z(n3910));
+ OR2 U3742 ( .A(n3916), .B(n3917), .Z(n3915));
+ AN2 U3743 ( .A(n3918), .B(pi060), .Z(n3917));
+ AN2 U3744 ( .A(n3919), .B(n3534), .Z(n3916));
+ AN2 U3745 ( .A(n3920), .B(n3921), .Z(n3919));
+ AN2 U3746 ( .A(n3922), .B(n3923), .Z(n3800));
+ OR2 U3747 ( .A(n3924), .B(n3925), .Z(n3923));
+ OR2 U3748 ( .A(n3321), .B(n3926), .Z(n3925));
+ AN2 U3749 ( .A(n3927), .B(n3928), .Z(n3924));
+ AN2 U3750 ( .A(pi050), .B(pi118), .Z(n3928));
+ AN2 U3751 ( .A(pi196), .B(n3534), .Z(n3927));
+ OR2 U3752 ( .A(n3929), .B(n3930), .Z(n3798));
+ OR2 U3753 ( .A(n3931), .B(n3932), .Z(n3930));
+ AN2 U3754 ( .A(n3933), .B(n3533), .Z(n3932));
+ AN2 U3755 ( .A(n3934), .B(n3913), .Z(n3933));
+ OR2 U3756 ( .A(n3918), .B(n3935), .Z(n3934));
+ OR2 U3757 ( .A(n3936), .B(n3937), .Z(n3935));
+ AN2 U3758 ( .A(n3938), .B(n3921), .Z(n3937));
+ AN2 U3759 ( .A(n3920), .B(n3261), .Z(n3938));
+ AN2 U3760 ( .A(n3939), .B(n3922), .Z(n3936));
+ AN2 U3761 ( .A(pi196), .B(n3940), .Z(n3939));
+ AN2 U3762 ( .A(n3922), .B(n3941), .Z(n3918));
+ AN2 U3763 ( .A(n3942), .B(n3943), .Z(n3941));
+ AN2 U3764 ( .A(n3944), .B(n3945), .Z(n3931));
+ AN2 U3765 ( .A(pi204), .B(n3946), .Z(n3944));
+ IV2 U3766 ( .A(n3947), .Z(n3946));
+ AN2 U3767 ( .A(n3948), .B(n3261), .Z(n3929));
+ OR2 U3768 ( .A(n3949), .B(n3950), .Z(n3948));
+ AN2 U3769 ( .A(n3947), .B(n3951), .Z(n3950));
+ AN2 U3770 ( .A(n3952), .B(n3953), .Z(n3947));
+ IV2 U3771 ( .A(n3954), .Z(n3953));
+ AN2 U3772 ( .A(n3955), .B(n3956), .Z(n3954));
+ OR2 U3773 ( .A(n3956), .B(n3955), .Z(n3952));
+ OR2 U3774 ( .A(n3957), .B(n3958), .Z(n3955));
+ AN2 U3775 ( .A(n3959), .B(n3960), .Z(n3958));
+ IV2 U3776 ( .A(pi009), .Z(n3960));
+ AN2 U3777 ( .A(pi009), .B(n3961), .Z(n3957));
+ AN2 U3778 ( .A(n3962), .B(n3963), .Z(n3956));
+ OR2 U3779 ( .A(n3964), .B(pi129), .Z(n3963));
+ IV2 U3780 ( .A(n3965), .Z(n3964));
+ OR2 U3781 ( .A(n3965), .B(n3966), .Z(n3962));
+ OR2 U3782 ( .A(n3967), .B(n3968), .Z(n3965));
+ AN2 U3783 ( .A(pi138), .B(n3969), .Z(n3968));
+ AN2 U3784 ( .A(pi169), .B(n3970), .Z(n3967));
+ IV2 U3785 ( .A(pi138), .Z(n3970));
+ AN2 U3786 ( .A(n3971), .B(n3533), .Z(n3949));
+ AN2 U3787 ( .A(n3914), .B(pi118), .Z(n3971));
+ OR2 U3788 ( .A(n3972), .B(n3973), .Z(n3914));
+ AN2 U3789 ( .A(n3920), .B(n3922), .Z(n3973));
+ IV2 U3790 ( .A(n3921), .Z(n3922));
+ AN2 U3791 ( .A(n3921), .B(n3974), .Z(n3972));
+ IV2 U3792 ( .A(n3920), .Z(n3974));
+ OR2 U3793 ( .A(n3975), .B(n3976), .Z(n3920));
+ AN2 U3794 ( .A(pi050), .B(n3942), .Z(n3976));
+ AN2 U3795 ( .A(pi196), .B(n3943), .Z(n3975));
+ OR2 U3796 ( .A(n3977), .B(n3978), .Z(n3921));
+ AN2 U3797 ( .A(n3979), .B(pi192), .Z(n3978));
+ OR2 U3798 ( .A(n3980), .B(n3981), .Z(n3979));
+ AN2 U3799 ( .A(n3982), .B(n3983), .Z(n3981));
+ IV2 U3800 ( .A(n3984), .Z(n3980));
+ OR2 U3801 ( .A(n3983), .B(n3982), .Z(n3984));
+ OR2 U3802 ( .A(n3985), .B(n3986), .Z(n3982));
+ IV2 U3803 ( .A(n3987), .Z(n3986));
+ OR2 U3804 ( .A(n3988), .B(n3989), .Z(n3987));
+ AN2 U3805 ( .A(n3988), .B(n3989), .Z(n3985));
+ AN2 U3806 ( .A(n3990), .B(n3991), .Z(n3988));
+ OR2 U3807 ( .A(n3992), .B(pi039), .Z(n3991));
+ OR2 U3808 ( .A(n3993), .B(pi004), .Z(n3990));
+ IV2 U3809 ( .A(pi039), .Z(n3993));
+ AN2 U3810 ( .A(n3994), .B(n3995), .Z(n3983));
+ OR2 U3811 ( .A(n3996), .B(pi068), .Z(n3995));
+ IV2 U3812 ( .A(n3997), .Z(n3996));
+ OR2 U3813 ( .A(n3997), .B(n3998), .Z(n3994));
+ OR2 U3814 ( .A(n3999), .B(n4000), .Z(n3997));
+ AN2 U3815 ( .A(pi098), .B(n4001), .Z(n4000));
+ AN2 U3816 ( .A(pi171), .B(n3638), .Z(n3999));
+ OR2 U3817 ( .A(pi037), .B(pi043), .Z(po078));
+ OR2 U3818 ( .A(n4002), .B(n4003), .Z(po077));
+ AN2 U3819 ( .A(n4004), .B(n4005), .Z(n4003));
+ AN2 U3820 ( .A(n4006), .B(n4007), .Z(n4002));
+ OR2 U3821 ( .A(n4008), .B(n4009), .Z(n4007));
+ IV2 U3822 ( .A(pi090), .Z(po076));
+ OR2 U3823 ( .A(n4010), .B(n4011), .Z(po075));
+ AN2 U3824 ( .A(n4012), .B(n4013), .Z(n4011));
+ OR2 U3825 ( .A(n4014), .B(n4015), .Z(n4012));
+ OR2 U3826 ( .A(n4016), .B(n4017), .Z(n4015));
+ OR2 U3827 ( .A(n4018), .B(n4019), .Z(n4014));
+ AN2 U3828 ( .A(n4020), .B(n3314), .Z(n4019));
+ OR2 U3829 ( .A(n4021), .B(n4022), .Z(n4020));
+ AN2 U3830 ( .A(n3926), .B(n3328), .Z(n4022));
+ OR2 U3831 ( .A(n3265), .B(n3326), .Z(n3328));
+ AN2 U3832 ( .A(n4023), .B(pi204), .Z(n4021));
+ AN2 U3833 ( .A(n3312), .B(n3261), .Z(n4023));
+ OR2 U3834 ( .A(n4024), .B(n4025), .Z(n3312));
+ AN2 U3835 ( .A(n3326), .B(n4026), .Z(n4024));
+ AN2 U3836 ( .A(n4027), .B(n3320), .Z(n4018));
+ OR2 U3837 ( .A(n4028), .B(n3321), .Z(n4027));
+ AN2 U3838 ( .A(po040), .B(n4029), .Z(n4010));
+ OR2 U3839 ( .A(n4030), .B(n4031), .Z(n4029));
+ OR2 U3840 ( .A(n4032), .B(n4033), .Z(n4031));
+ AN2 U3841 ( .A(n4034), .B(n3261), .Z(n4032));
+ OR2 U3842 ( .A(n4035), .B(n4036), .Z(n4034));
+ OR2 U3843 ( .A(n4037), .B(n4038), .Z(n4036));
+ AN2 U3844 ( .A(n4039), .B(n3951), .Z(n4038));
+ AN2 U3845 ( .A(n4025), .B(n3314), .Z(n4039));
+ AN2 U3846 ( .A(n4040), .B(n4041), .Z(n4037));
+ AN2 U3847 ( .A(n4042), .B(n3320), .Z(n4035));
+ OR2 U3848 ( .A(n4043), .B(n4044), .Z(n4042));
+ AN2 U3849 ( .A(pi204), .B(n4045), .Z(n4044));
+ AN2 U3850 ( .A(n4046), .B(n4041), .Z(n4043));
+ OR2 U3851 ( .A(n4047), .B(n4048), .Z(n4030));
+ AN2 U3852 ( .A(n4049), .B(n4050), .Z(n4048));
+ OR2 U3853 ( .A(n4051), .B(n4052), .Z(n4050));
+ AN2 U3854 ( .A(n3321), .B(n3265), .Z(n4052));
+ AN2 U3855 ( .A(n3951), .B(n4053), .Z(n4051));
+ AN2 U3856 ( .A(n3326), .B(n3314), .Z(n4049));
+ AN2 U3857 ( .A(n4054), .B(n4055), .Z(n4047));
+ AN2 U3858 ( .A(n4056), .B(n4057), .Z(n4055));
+ AN2 U3859 ( .A(n3945), .B(pi204), .Z(n4054));
+ OR2 U3860 ( .A(n4058), .B(n4059), .Z(po073));
+ AN2 U3861 ( .A(n4060), .B(n4061), .Z(n4059));
+ AN2 U3862 ( .A(n3457), .B(n4062), .Z(n4058));
+ OR2 U3863 ( .A(n4063), .B(n4064), .Z(po068));
+ AN2 U3864 ( .A(n4065), .B(n4066), .Z(n4064));
+ OR2 U3865 ( .A(n4067), .B(n4068), .Z(n4065));
+ OR2 U3866 ( .A(n4069), .B(n4070), .Z(n4068));
+ AN2 U3867 ( .A(n4071), .B(n4072), .Z(n4070));
+ OR2 U3868 ( .A(n4073), .B(po059), .Z(n4071));
+ AN2 U3869 ( .A(n4074), .B(n2837), .Z(n4073));
+ AN2 U3870 ( .A(n4075), .B(n4076), .Z(n4069));
+ AN2 U3871 ( .A(n3780), .B(n4077), .Z(n4075));
+ AN2 U3872 ( .A(n4078), .B(n4079), .Z(n4063));
+ OR2 U3873 ( .A(n4080), .B(n4081), .Z(n4079));
+ OR2 U3874 ( .A(n4082), .B(n4083), .Z(n4081));
+ AN2 U3875 ( .A(n4084), .B(n2837), .Z(n4083));
+ AN2 U3876 ( .A(n4085), .B(pi192), .Z(n4082));
+ AN2 U3877 ( .A(n3778), .B(n3776), .Z(n4080));
+ OR2 U3878 ( .A(n4086), .B(n4087), .Z(n3776));
+ OR2 U3879 ( .A(n4088), .B(n4089), .Z(po061));
+ AN2 U3880 ( .A(n2861), .B(n4090), .Z(n4089));
+ OR2 U3881 ( .A(n4091), .B(n4092), .Z(n4090));
+ OR2 U3882 ( .A(n4093), .B(n4094), .Z(n4092));
+ AN2 U3883 ( .A(n4095), .B(n2901), .Z(n4094));
+ AN2 U3884 ( .A(n2862), .B(n2990), .Z(n4093));
+ OR2 U3885 ( .A(n4096), .B(n4097), .Z(n4091));
+ AN2 U3886 ( .A(n2880), .B(n4098), .Z(n4097));
+ AN2 U3887 ( .A(n4099), .B(n4100), .Z(n4096));
+ OR2 U3888 ( .A(n4101), .B(n4102), .Z(n4100));
+ OR2 U3889 ( .A(n2978), .B(n4103), .Z(n4102));
+ AN2 U3890 ( .A(n3222), .B(n2957), .Z(n4103));
+ AN2 U3891 ( .A(n2935), .B(po031), .Z(n4101));
+ IV2 U3892 ( .A(n2938), .Z(n2935));
+ AN2 U3893 ( .A(n4104), .B(n2998), .Z(n4088));
+ OR2 U3894 ( .A(n4105), .B(n4106), .Z(n4104));
+ OR2 U3895 ( .A(n4107), .B(n4108), .Z(n4106));
+ AN2 U3896 ( .A(n2892), .B(pi192), .Z(n4108));
+ AN2 U3897 ( .A(n2929), .B(n2837), .Z(n4107));
+ AN2 U3898 ( .A(n2930), .B(n3787), .Z(n4105));
+ OR2 U3899 ( .A(n4109), .B(n4110), .Z(n3787));
+ OR2 U3900 ( .A(n4111), .B(n4112), .Z(n4110));
+ AN2 U3901 ( .A(n4113), .B(n2837), .Z(n4112));
+ AN2 U3902 ( .A(n2876), .B(pi192), .Z(n4111));
+ AN2 U3903 ( .A(pi200), .B(n4114), .Z(n4109));
+ OR2 U3904 ( .A(n4115), .B(n2999), .Z(n4114));
+ OR2 U3905 ( .A(n4116), .B(n4117), .Z(n2999));
+ AN2 U3906 ( .A(n2938), .B(n2962), .Z(n4117));
+ AN2 U3907 ( .A(pi192), .B(n2878), .Z(n4116));
+ AN2 U3908 ( .A(n2918), .B(n2837), .Z(n4115));
+ AN2 U3909 ( .A(n2938), .B(pi082), .Z(n2918));
+ OR2 U3910 ( .A(n4118), .B(n4119), .Z(po060));
+ OR2 U3911 ( .A(n4120), .B(n4121), .Z(n4119));
+ AN2 U3912 ( .A(n4122), .B(n4123), .Z(n4121));
+ OR2 U3913 ( .A(n4124), .B(n4125), .Z(n4123));
+ AN2 U3914 ( .A(n4126), .B(n4127), .Z(n4124));
+ OR2 U3915 ( .A(n4128), .B(n4129), .Z(n4126));
+ AN2 U3916 ( .A(n4130), .B(n4131), .Z(n4122));
+ OR2 U3917 ( .A(n4132), .B(n4133), .Z(n4131));
+ AN2 U3918 ( .A(pi052), .B(n4134), .Z(n4132));
+ OR2 U3919 ( .A(po064), .B(n4135), .Z(n4130));
+ AN2 U3920 ( .A(n4136), .B(n4137), .Z(n4120));
+ OR2 U3921 ( .A(n4138), .B(n4139), .Z(n4137));
+ AN2 U3922 ( .A(n4140), .B(n4141), .Z(n4139));
+ OR2 U3923 ( .A(n4142), .B(n4143), .Z(n4140));
+ OR2 U3924 ( .A(n4144), .B(n4145), .Z(n4143));
+ AN2 U3925 ( .A(po040), .B(n3321), .Z(n4145));
+ AN2 U3926 ( .A(po103), .B(n4146), .Z(n4144));
+ OR2 U3927 ( .A(n4147), .B(n3321), .Z(n4146));
+ AN2 U3928 ( .A(n4148), .B(n4149), .Z(n4147));
+ OR2 U3929 ( .A(po004), .B(n4150), .Z(n4149));
+ OR2 U3930 ( .A(n4151), .B(n4152), .Z(n4142));
+ OR2 U3931 ( .A(n4153), .B(n4154), .Z(n4152));
+ IV2 U3932 ( .A(n4155), .Z(n4154));
+ OR2 U3933 ( .A(n4156), .B(n4157), .Z(n4155));
+ AN2 U3934 ( .A(n4158), .B(n4159), .Z(n4153));
+ AN2 U3935 ( .A(n4160), .B(po004), .Z(n4151));
+ AN2 U3936 ( .A(n3951), .B(po040), .Z(n4160));
+ AN2 U3937 ( .A(po004), .B(n4161), .Z(n4138));
+ AN2 U3938 ( .A(n4162), .B(n4163), .Z(n4136));
+ OR2 U3939 ( .A(n4164), .B(n4134), .Z(n4163));
+ AN2 U3940 ( .A(n4165), .B(po064), .Z(n4164));
+ IV2 U3941 ( .A(n4166), .Z(n4165));
+ OR2 U3942 ( .A(n4167), .B(n4125), .Z(n4166));
+ OR2 U3943 ( .A(n4135), .B(n4168), .Z(n4162));
+ OR2 U3944 ( .A(n4169), .B(n4170), .Z(n4168));
+ AN2 U3945 ( .A(pi054), .B(n4167), .Z(n4170));
+ AN2 U3946 ( .A(n4171), .B(n4133), .Z(n4169));
+ IV2 U3947 ( .A(n4172), .Z(n4171));
+ OR2 U3948 ( .A(n4173), .B(n4174), .Z(n4118));
+ AN2 U3949 ( .A(n4175), .B(pi054), .Z(n4174));
+ AN2 U3950 ( .A(n4176), .B(n4177), .Z(n4175));
+ OR2 U3951 ( .A(n4178), .B(n4179), .Z(n4176));
+ AN2 U3952 ( .A(n4134), .B(n4133), .Z(n4179));
+ AN2 U3953 ( .A(n4135), .B(po064), .Z(n4178));
+ AN2 U3954 ( .A(n4180), .B(n4135), .Z(n4173));
+ IV2 U3955 ( .A(n4134), .Z(n4135));
+ OR2 U3956 ( .A(n4181), .B(n4182), .Z(n4134));
+ AN2 U3957 ( .A(n4183), .B(n4184), .Z(n4182));
+ OR2 U3958 ( .A(n4185), .B(n4186), .Z(n4183));
+ AN2 U3959 ( .A(n4187), .B(n4188), .Z(n4186));
+ IV2 U3960 ( .A(n4189), .Z(n4188));
+ OR2 U3961 ( .A(n4190), .B(n4191), .Z(n4187));
+ AN2 U3962 ( .A(n4192), .B(n4193), .Z(n4191));
+ OR2 U3963 ( .A(n4194), .B(n4195), .Z(n4193));
+ AN2 U3964 ( .A(n4196), .B(n3261), .Z(n4195));
+ OR2 U3965 ( .A(n4197), .B(n4198), .Z(n4196));
+ AN2 U3966 ( .A(n4199), .B(po103), .Z(n4198));
+ AN2 U3967 ( .A(n4200), .B(n4201), .Z(n4199));
+ AN2 U3968 ( .A(n4202), .B(n4025), .Z(n4197));
+ AN2 U3969 ( .A(n4203), .B(po091), .Z(n4202));
+ AN2 U3970 ( .A(n4204), .B(n4205), .Z(n4190));
+ OR2 U3971 ( .A(n3317), .B(n4206), .Z(n4204));
+ OR2 U3972 ( .A(n4207), .B(n4208), .Z(n4206));
+ AN2 U3973 ( .A(n4209), .B(n3314), .Z(n4208));
+ IV2 U3974 ( .A(n4210), .Z(n4209));
+ AN2 U3975 ( .A(n4210), .B(n4057), .Z(n4207));
+ AN2 U3976 ( .A(po103), .B(n4148), .Z(n4210));
+ AN2 U3977 ( .A(n4189), .B(n4211), .Z(n4185));
+ OR2 U3978 ( .A(n4212), .B(n4213), .Z(n4211));
+ AN2 U3979 ( .A(n4214), .B(n4205), .Z(n4213));
+ OR2 U3980 ( .A(n3325), .B(n4215), .Z(n4214));
+ OR2 U3981 ( .A(n4216), .B(n3329), .Z(n4215));
+ AN2 U3982 ( .A(n4040), .B(n4217), .Z(n3329));
+ AN2 U3983 ( .A(n4192), .B(n4218), .Z(n4212));
+ OR2 U3984 ( .A(n4219), .B(n4220), .Z(n4218));
+ OR2 U3985 ( .A(n4221), .B(n4222), .Z(n4220));
+ AN2 U3986 ( .A(n4025), .B(n4201), .Z(n4222));
+ IV2 U3987 ( .A(n4223), .Z(n4025));
+ AN2 U3988 ( .A(po091), .B(n4200), .Z(n4221));
+ OR2 U3989 ( .A(n4224), .B(n4225), .Z(n4189));
+ AN2 U3990 ( .A(n4226), .B(n4227), .Z(n4225));
+ IV2 U3991 ( .A(n4228), .Z(n4224));
+ OR2 U3992 ( .A(n4227), .B(n4226), .Z(n4228));
+ AN2 U3993 ( .A(n4229), .B(n4230), .Z(n4181));
+ OR2 U3994 ( .A(n4231), .B(n4232), .Z(n4230));
+ OR2 U3995 ( .A(n4233), .B(n4234), .Z(n4232));
+ AN2 U3996 ( .A(n4235), .B(n4236), .Z(n4234));
+ OR2 U3997 ( .A(n4237), .B(n4238), .Z(n4235));
+ AN2 U3998 ( .A(n4239), .B(n4240), .Z(n4238));
+ OR2 U3999 ( .A(n3325), .B(n4216), .Z(n4240));
+ AN2 U4000 ( .A(po103), .B(n4194), .Z(n4216));
+ AN2 U4001 ( .A(n3265), .B(n4040), .Z(n3325));
+ AN2 U4002 ( .A(n4241), .B(n4242), .Z(n4237));
+ OR2 U4003 ( .A(n4243), .B(n4219), .Z(n4241));
+ OR2 U4004 ( .A(n4244), .B(n3321), .Z(n4219));
+ AN2 U4005 ( .A(n4203), .B(n4223), .Z(n4244));
+ AN2 U4006 ( .A(n4245), .B(n3314), .Z(n4243));
+ OR2 U4007 ( .A(n4246), .B(po091), .Z(n4245));
+ AN2 U4008 ( .A(n4247), .B(n3265), .Z(n4246));
+ AN2 U4009 ( .A(n4248), .B(n4249), .Z(n4233));
+ OR2 U4010 ( .A(n4250), .B(n4251), .Z(n4249));
+ OR2 U4011 ( .A(n4252), .B(n4253), .Z(n4251));
+ AN2 U4012 ( .A(po103), .B(n4254), .Z(n4253));
+ OR2 U4013 ( .A(n4255), .B(n3330), .Z(n4254));
+ AN2 U4014 ( .A(n3311), .B(n4242), .Z(n4255));
+ AN2 U4015 ( .A(n4194), .B(n3265), .Z(n4252));
+ AN2 U4016 ( .A(n4148), .B(n3311), .Z(n4194));
+ AN2 U4017 ( .A(n4239), .B(n4256), .Z(n4250));
+ OR2 U4018 ( .A(n4257), .B(n4258), .Z(n4256));
+ OR2 U4019 ( .A(n3926), .B(n4259), .Z(n4258));
+ AN2 U4020 ( .A(n4260), .B(n3314), .Z(n4259));
+ OR2 U4021 ( .A(n4261), .B(n4262), .Z(n4257));
+ AN2 U4022 ( .A(pi058), .B(pi129), .Z(n4262));
+ AN2 U4023 ( .A(n4056), .B(n3966), .Z(n4261));
+ AN2 U4024 ( .A(n4263), .B(n4264), .Z(n4231));
+ AN2 U4025 ( .A(n4265), .B(n4266), .Z(n4264));
+ OR2 U4026 ( .A(n4267), .B(n4236), .Z(n4266));
+ AN2 U4027 ( .A(n4268), .B(pi058), .Z(n4267));
+ AN2 U4028 ( .A(n4242), .B(n3265), .Z(n4268));
+ OR2 U4029 ( .A(n4269), .B(n4248), .Z(n4265));
+ IV2 U4030 ( .A(n4236), .Z(n4248));
+ AN2 U4031 ( .A(n4270), .B(n4271), .Z(n4236));
+ IV2 U4032 ( .A(n4272), .Z(n4271));
+ AN2 U4033 ( .A(n4226), .B(n4141), .Z(n4272));
+ OR2 U4034 ( .A(n4226), .B(n4141), .Z(n4270));
+ OR2 U4035 ( .A(n4273), .B(n4274), .Z(n4226));
+ IV2 U4036 ( .A(n4275), .Z(n4274));
+ OR2 U4037 ( .A(n4276), .B(n4277), .Z(n4275));
+ AN2 U4038 ( .A(n4277), .B(n4276), .Z(n4273));
+ AN2 U4039 ( .A(n4278), .B(n4279), .Z(n4276));
+ OR2 U4040 ( .A(n4280), .B(n4281), .Z(n4279));
+ IV2 U4041 ( .A(n4282), .Z(n4280));
+ OR2 U4042 ( .A(n4283), .B(n4282), .Z(n4278));
+ OR2 U4043 ( .A(n4284), .B(n4285), .Z(n4282));
+ AN2 U4044 ( .A(po040), .B(n4286), .Z(n4285));
+ OR2 U4045 ( .A(n4017), .B(n4287), .Z(n4286));
+ OR2 U4046 ( .A(n4288), .B(n4289), .Z(n4287));
+ AN2 U4047 ( .A(n4290), .B(n3314), .Z(n4289));
+ OR2 U4048 ( .A(n4291), .B(n3321), .Z(n4290));
+ IV2 U4049 ( .A(n4292), .Z(n4288));
+ OR2 U4050 ( .A(n4293), .B(n3314), .Z(n4292));
+ OR2 U4051 ( .A(n4294), .B(n3330), .Z(n4017));
+ AN2 U4052 ( .A(n4201), .B(n3926), .Z(n3330));
+ AN2 U4053 ( .A(n3311), .B(pi204), .Z(n4294));
+ AN2 U4054 ( .A(n4295), .B(n4013), .Z(n4284));
+ OR2 U4055 ( .A(n4033), .B(n4296), .Z(n4295));
+ OR2 U4056 ( .A(n4297), .B(n4298), .Z(n4296));
+ AN2 U4057 ( .A(n4299), .B(n3314), .Z(n4298));
+ AN2 U4058 ( .A(n4300), .B(n3261), .Z(n4299));
+ OR2 U4059 ( .A(n4301), .B(n4302), .Z(n4300));
+ AN2 U4060 ( .A(pi204), .B(n4203), .Z(n4302));
+ AN2 U4061 ( .A(po091), .B(n4041), .Z(n4301));
+ AN2 U4062 ( .A(n4040), .B(n4293), .Z(n4297));
+ AN2 U4063 ( .A(n3311), .B(n3951), .Z(n4033));
+ IV2 U4064 ( .A(n4260), .Z(n3311));
+ OR2 U4065 ( .A(n3321), .B(n4057), .Z(n4260));
+ IV2 U4066 ( .A(n4281), .Z(n4283));
+ OR2 U4067 ( .A(n4303), .B(n4304), .Z(n4281));
+ AN2 U4068 ( .A(n4305), .B(n4306), .Z(n4304));
+ AN2 U4069 ( .A(n4307), .B(n3261), .Z(n4305));
+ OR2 U4070 ( .A(n4308), .B(n4309), .Z(n4307));
+ AN2 U4071 ( .A(pi065), .B(n4148), .Z(n4309));
+ AN2 U4072 ( .A(n4310), .B(pi058), .Z(n4308));
+ AN2 U4073 ( .A(n4311), .B(n4312), .Z(n4303));
+ OR2 U4074 ( .A(n3961), .B(n4313), .Z(n4311));
+ IV2 U4075 ( .A(n3959), .Z(n3961));
+ OR2 U4076 ( .A(n4314), .B(n4315), .Z(n3959));
+ AN2 U4077 ( .A(pi058), .B(n4150), .Z(n4315));
+ AN2 U4078 ( .A(pi065), .B(n4316), .Z(n4314));
+ OR2 U4079 ( .A(n4317), .B(n4318), .Z(n4277));
+ AN2 U4080 ( .A(po004), .B(n3265), .Z(n4318));
+ AN2 U4081 ( .A(po103), .B(n4319), .Z(n4317));
+ AN2 U4082 ( .A(n4239), .B(pi058), .Z(n4269));
+ AN2 U4083 ( .A(n4040), .B(n3261), .Z(n4263));
+ AN2 U4084 ( .A(n4320), .B(n4167), .Z(n4180));
+ OR2 U4085 ( .A(n4129), .B(n4127), .Z(n4320));
+ AN2 U4086 ( .A(po023), .B(pi183), .Z(po058));
+ IV2 U4087 ( .A(n4321), .Z(po056));
+ AN2 U4088 ( .A(n4322), .B(n4323), .Z(n4321));
+ AN2 U4089 ( .A(pi063), .B(pi010), .Z(n4323));
+ AN2 U4090 ( .A(pi203), .B(pi073), .Z(n4322));
+ OR2 U4091 ( .A(n4324), .B(n4325), .Z(po055));
+ AN2 U4092 ( .A(n3015), .B(n4326), .Z(n4325));
+ AN2 U4093 ( .A(n3018), .B(n4327), .Z(n4324));
+ AN2 U4094 ( .A(n4328), .B(n4329), .Z(po053));
+ OR2 U4095 ( .A(n4306), .B(n4330), .Z(n4329));
+ IV2 U4096 ( .A(n4312), .Z(n4306));
+ OR2 U4097 ( .A(n4331), .B(n4312), .Z(n4328));
+ AN2 U4098 ( .A(n4332), .B(n3780), .Z(po051));
+ OR2 U4099 ( .A(n4333), .B(n4334), .Z(n4332));
+ OR2 U4100 ( .A(n4335), .B(n4336), .Z(po050));
+ AN2 U4101 ( .A(n4337), .B(n4338), .Z(n4336));
+ OR2 U4102 ( .A(n4339), .B(n4340), .Z(n4338));
+ AN2 U4103 ( .A(n4087), .B(n4341), .Z(n4339));
+ AN2 U4104 ( .A(n4342), .B(n4343), .Z(n4335));
+ OR2 U4105 ( .A(n4344), .B(n4345), .Z(n4343));
+ OR2 U4106 ( .A(n4346), .B(n4347), .Z(n4345));
+ AN2 U4107 ( .A(n4067), .B(n4348), .Z(n4346));
+ OR2 U4108 ( .A(n4349), .B(n4350), .Z(n4067));
+ AN2 U4109 ( .A(n4351), .B(pi192), .Z(n4350));
+ AN2 U4110 ( .A(n4072), .B(n3880), .Z(n4351));
+ AN2 U4111 ( .A(n4352), .B(n3890), .Z(n4349));
+ AN2 U4112 ( .A(n4353), .B(n3780), .Z(n4352));
+ OR2 U4113 ( .A(n4354), .B(n4355), .Z(n4344));
+ AN2 U4114 ( .A(n4356), .B(n3780), .Z(n4355));
+ AN2 U4115 ( .A(n4357), .B(n4076), .Z(n4354));
+ AN2 U4116 ( .A(n4072), .B(n4358), .Z(n4357));
+ OR2 U4117 ( .A(n4359), .B(n4360), .Z(po049));
+ AN2 U4118 ( .A(n3361), .B(n4361), .Z(n4360));
+ OR2 U4119 ( .A(n4362), .B(n4363), .Z(n4361));
+ AN2 U4120 ( .A(n4364), .B(n3451), .Z(n4362));
+ IV2 U4121 ( .A(n3401), .Z(n3361));
+ AN2 U4122 ( .A(n4365), .B(n3401), .Z(n4359));
+ OR2 U4123 ( .A(n4366), .B(n4367), .Z(n4365));
+ AN2 U4124 ( .A(n3453), .B(n4368), .Z(n4366));
+ OR2 U4125 ( .A(n4369), .B(n3253), .Z(po048));
+ AN2 U4126 ( .A(n4370), .B(n3255), .Z(n4369));
+ OR2 U4127 ( .A(n4371), .B(n4372), .Z(n4370));
+ AN2 U4128 ( .A(n4373), .B(n3259), .Z(n4371));
+ AN2 U4129 ( .A(n4374), .B(n4242), .Z(n4373));
+ OR2 U4130 ( .A(n4375), .B(n4376), .Z(po047));
+ OR2 U4131 ( .A(n4377), .B(n4378), .Z(n4376));
+ AN2 U4132 ( .A(n4379), .B(n4380), .Z(n4378));
+ AN2 U4133 ( .A(n4381), .B(n3259), .Z(n4377));
+ AN2 U4134 ( .A(n4382), .B(n4383), .Z(n4381));
+ OR2 U4135 ( .A(po004), .B(n4384), .Z(n4383));
+ OR2 U4136 ( .A(n3926), .B(n4385), .Z(n4384));
+ AN2 U4137 ( .A(n4386), .B(pi065), .Z(n4385));
+ AN2 U4138 ( .A(n4387), .B(n4157), .Z(n4386));
+ OR2 U4139 ( .A(n4319), .B(n4388), .Z(n4382));
+ OR2 U4140 ( .A(n4389), .B(n4390), .Z(n4388));
+ AN2 U4141 ( .A(n4391), .B(n3321), .Z(n4390));
+ AN2 U4142 ( .A(n4392), .B(n4310), .Z(n4389));
+ AN2 U4143 ( .A(pi204), .B(n4387), .Z(n4392));
+ OR2 U4144 ( .A(n4393), .B(n4394), .Z(n4375));
+ AN2 U4145 ( .A(n4395), .B(n4319), .Z(n4394));
+ OR2 U4146 ( .A(n4396), .B(n4397), .Z(n4395));
+ AN2 U4147 ( .A(n4227), .B(n4161), .Z(n4397));
+ AN2 U4148 ( .A(po004), .B(n4398), .Z(n4393));
+ OR2 U4149 ( .A(n4399), .B(n4400), .Z(n4398));
+ OR2 U4150 ( .A(n4401), .B(n4402), .Z(n4400));
+ AN2 U4151 ( .A(n4310), .B(n4403), .Z(n4402));
+ AN2 U4152 ( .A(n4404), .B(n4227), .Z(n4401));
+ AN2 U4153 ( .A(n4405), .B(n4406), .Z(n4399));
+ AN2 U4154 ( .A(n4407), .B(n3261), .Z(n4405));
+ OR2 U4155 ( .A(n4408), .B(n4409), .Z(n4407));
+ AN2 U4156 ( .A(n4028), .B(pi065), .Z(n4409));
+ AN2 U4157 ( .A(po040), .B(n4410), .Z(n4408));
+ OR2 U4158 ( .A(n4411), .B(n4412), .Z(n4410));
+ AN2 U4159 ( .A(pi065), .B(n4045), .Z(n4412));
+ AN2 U4160 ( .A(n4046), .B(n4156), .Z(n4411));
+ OR2 U4161 ( .A(n4413), .B(n4414), .Z(po046));
+ OR2 U4162 ( .A(n4415), .B(n4416), .Z(n4414));
+ AN2 U4163 ( .A(n3339), .B(n4417), .Z(n4416));
+ AN2 U4164 ( .A(n3341), .B(n4418), .Z(n4415));
+ OR2 U4165 ( .A(n4419), .B(n4420), .Z(n4413));
+ AN2 U4166 ( .A(n4421), .B(pi192), .Z(n4420));
+ OR2 U4167 ( .A(n4422), .B(n4423), .Z(n4421));
+ AN2 U4168 ( .A(n4424), .B(pi098), .Z(n4423));
+ AN2 U4169 ( .A(n4425), .B(n4426), .Z(n4424));
+ OR2 U4170 ( .A(n3242), .B(n3657), .Z(n4425));
+ IV2 U4171 ( .A(n3635), .Z(n3657));
+ AN2 U4172 ( .A(n4427), .B(n3638), .Z(n4422));
+ OR2 U4173 ( .A(n4428), .B(n4429), .Z(n4427));
+ AN2 U4174 ( .A(n4430), .B(pi171), .Z(n4429));
+ AN2 U4175 ( .A(n4431), .B(n4001), .Z(n4428));
+ AN2 U4176 ( .A(n4432), .B(n2837), .Z(n4419));
+ OR2 U4177 ( .A(n4433), .B(n4434), .Z(n4432));
+ AN2 U4178 ( .A(n4435), .B(pi003), .Z(n4434));
+ AN2 U4179 ( .A(n4436), .B(n4426), .Z(n4435));
+ OR2 U4180 ( .A(n3244), .B(n3616), .Z(n4436));
+ IV2 U4181 ( .A(n3593), .Z(n3616));
+ AN2 U4182 ( .A(n4437), .B(n3597), .Z(n4433));
+ OR2 U4183 ( .A(n4438), .B(n4439), .Z(n4437));
+ AN2 U4184 ( .A(n4430), .B(pi142), .Z(n4439));
+ AN2 U4185 ( .A(n4431), .B(n4440), .Z(n4438));
+ AN2 U4186 ( .A(n3236), .B(n4441), .Z(n4431));
+ OR2 U4187 ( .A(n4442), .B(n4443), .Z(po045));
+ AN2 U4188 ( .A(n4444), .B(n4445), .Z(n4443));
+ OR2 U4189 ( .A(n4446), .B(n3756), .Z(n4445));
+ AN2 U4190 ( .A(n4006), .B(n4005), .Z(n4446));
+ OR2 U4191 ( .A(n4447), .B(n4448), .Z(n4005));
+ AN2 U4192 ( .A(n4449), .B(n3301), .Z(n4447));
+ AN2 U4193 ( .A(n4450), .B(n3306), .Z(n4449));
+ AN2 U4194 ( .A(n3757), .B(n4451), .Z(n4442));
+ OR2 U4195 ( .A(n4452), .B(n4453), .Z(n4451));
+ OR2 U4196 ( .A(n4454), .B(n4455), .Z(n4453));
+ AN2 U4197 ( .A(po092), .B(n4456), .Z(n4455));
+ OR2 U4198 ( .A(n4008), .B(n4004), .Z(n4456));
+ AN2 U4199 ( .A(n4457), .B(n4458), .Z(n4008));
+ AN2 U4200 ( .A(n4458), .B(n4459), .Z(n4454));
+ OR2 U4201 ( .A(n4460), .B(n4461), .Z(n4459));
+ AN2 U4202 ( .A(n4462), .B(n4463), .Z(n4461));
+ AN2 U4203 ( .A(n4464), .B(n4465), .Z(n4462));
+ AN2 U4204 ( .A(n4466), .B(n4467), .Z(n4460));
+ AN2 U4205 ( .A(n4468), .B(n4469), .Z(n4466));
+ OR2 U4206 ( .A(n4470), .B(n4471), .Z(po043));
+ OR2 U4207 ( .A(n4472), .B(n4473), .Z(n4471));
+ AN2 U4208 ( .A(n4474), .B(n4475), .Z(n4473));
+ AN2 U4209 ( .A(n4476), .B(n4337), .Z(n4474));
+ AN2 U4210 ( .A(n4477), .B(n4478), .Z(n4472));
+ OR2 U4211 ( .A(n4479), .B(n4480), .Z(n4477));
+ AN2 U4212 ( .A(n4337), .B(n4481), .Z(n4480));
+ IV2 U4213 ( .A(n4342), .Z(n4337));
+ AN2 U4214 ( .A(n4342), .B(n4476), .Z(n4479));
+ IV2 U4215 ( .A(n4481), .Z(n4476));
+ AN2 U4216 ( .A(n4482), .B(n4481), .Z(n4470));
+ OR2 U4217 ( .A(n4483), .B(n4484), .Z(n4481));
+ OR2 U4218 ( .A(n4485), .B(n4486), .Z(n4484));
+ AN2 U4219 ( .A(n4487), .B(n4078), .Z(n4486));
+ OR2 U4220 ( .A(n4488), .B(n4489), .Z(n4487));
+ AN2 U4221 ( .A(n4490), .B(n3778), .Z(n4489));
+ AN2 U4222 ( .A(n3773), .B(n4491), .Z(n4488));
+ AN2 U4223 ( .A(n4492), .B(n4066), .Z(n4485));
+ AN2 U4224 ( .A(n4490), .B(n3773), .Z(n4492));
+ AN2 U4225 ( .A(n4491), .B(n4341), .Z(n4483));
+ IV2 U4226 ( .A(n4490), .Z(n4491));
+ OR2 U4227 ( .A(n4493), .B(n4494), .Z(n4490));
+ IV2 U4228 ( .A(n4495), .Z(n4494));
+ OR2 U4229 ( .A(n4496), .B(n4497), .Z(n4495));
+ AN2 U4230 ( .A(n4497), .B(n4496), .Z(n4493));
+ AN2 U4231 ( .A(n4498), .B(n4499), .Z(n4496));
+ IV2 U4232 ( .A(n4500), .Z(n4499));
+ AN2 U4233 ( .A(n4333), .B(n4501), .Z(n4500));
+ OR2 U4234 ( .A(n4501), .B(n4333), .Z(n4498));
+ OR2 U4235 ( .A(n4502), .B(n4503), .Z(n4501));
+ OR2 U4236 ( .A(n4504), .B(n4505), .Z(n4503));
+ OR2 U4237 ( .A(n4506), .B(n4507), .Z(n4505));
+ AN2 U4238 ( .A(n4508), .B(n4509), .Z(n4507));
+ AN2 U4239 ( .A(n4510), .B(n4511), .Z(n4506));
+ AN2 U4240 ( .A(n4512), .B(n4513), .Z(n4504));
+ OR2 U4241 ( .A(n4514), .B(n4515), .Z(n4502));
+ AN2 U4242 ( .A(n4516), .B(n4517), .Z(n4515));
+ AN2 U4243 ( .A(po102), .B(n4518), .Z(n4514));
+ OR2 U4244 ( .A(n4519), .B(n4520), .Z(n4518));
+ AN2 U4245 ( .A(n4513), .B(n4521), .Z(n4520));
+ OR2 U4246 ( .A(n4522), .B(n4523), .Z(n4513));
+ AN2 U4247 ( .A(n4508), .B(n3773), .Z(n4523));
+ AN2 U4248 ( .A(po025), .B(n4516), .Z(n4522));
+ AN2 U4249 ( .A(n4508), .B(n4524), .Z(n4519));
+ IV2 U4250 ( .A(n4510), .Z(n4508));
+ OR2 U4251 ( .A(n4525), .B(n4526), .Z(n4510));
+ AN2 U4252 ( .A(n4527), .B(n4528), .Z(n4526));
+ OR2 U4253 ( .A(n4529), .B(n4530), .Z(n4527));
+ OR2 U4254 ( .A(n4531), .B(n4532), .Z(n4530));
+ AN2 U4255 ( .A(po025), .B(n4533), .Z(n4532));
+ OR2 U4256 ( .A(n4534), .B(n4535), .Z(n4533));
+ OR2 U4257 ( .A(n4356), .B(n4536), .Z(n4535));
+ AN2 U4258 ( .A(n4537), .B(n4538), .Z(n4536));
+ AN2 U4259 ( .A(n4539), .B(n4540), .Z(n4537));
+ AN2 U4260 ( .A(n3890), .B(n4541), .Z(n4534));
+ OR2 U4261 ( .A(n4542), .B(n4543), .Z(n4541));
+ AN2 U4262 ( .A(n4085), .B(n4544), .Z(n4542));
+ AN2 U4263 ( .A(n3778), .B(n4545), .Z(n4531));
+ OR2 U4264 ( .A(n4546), .B(n4547), .Z(n4545));
+ OR2 U4265 ( .A(n4548), .B(n4549), .Z(n4547));
+ AN2 U4266 ( .A(n3775), .B(n4550), .Z(n4549));
+ AN2 U4267 ( .A(n4524), .B(n4333), .Z(n4548));
+ AN2 U4268 ( .A(n4086), .B(n4551), .Z(n4546));
+ OR2 U4269 ( .A(n4552), .B(n4553), .Z(n4529));
+ AN2 U4270 ( .A(n4554), .B(n4555), .Z(n4553));
+ OR2 U4271 ( .A(n4556), .B(n3888), .Z(n4555));
+ AN2 U4272 ( .A(pi192), .B(n4557), .Z(n4556));
+ AN2 U4273 ( .A(n4558), .B(n4559), .Z(n4554));
+ OR2 U4274 ( .A(n4085), .B(n4560), .Z(n4558));
+ AN2 U4275 ( .A(n4561), .B(n3773), .Z(n4560));
+ AN2 U4276 ( .A(n4562), .B(n4563), .Z(n4552));
+ OR2 U4277 ( .A(n4564), .B(n4565), .Z(n4563));
+ AN2 U4278 ( .A(n4566), .B(n4567), .Z(n4564));
+ AN2 U4279 ( .A(n3773), .B(n4076), .Z(n4566));
+ OR2 U4280 ( .A(pi076), .B(n4557), .Z(n4562));
+ AN2 U4281 ( .A(n4516), .B(n4568), .Z(n4525));
+ OR2 U4282 ( .A(n4569), .B(n4570), .Z(n4568));
+ OR2 U4283 ( .A(n4571), .B(n4572), .Z(n4570));
+ OR2 U4284 ( .A(n4573), .B(n4574), .Z(n4572));
+ AN2 U4285 ( .A(n4575), .B(n4576), .Z(n4574));
+ AN2 U4286 ( .A(n4577), .B(n4076), .Z(n4575));
+ AN2 U4287 ( .A(n3773), .B(n4578), .Z(n4577));
+ AN2 U4288 ( .A(n4579), .B(n4580), .Z(n4573));
+ OR2 U4289 ( .A(n4581), .B(n4565), .Z(n4579));
+ AN2 U4290 ( .A(n4539), .B(n4582), .Z(n4565));
+ AN2 U4291 ( .A(n2837), .B(n4550), .Z(n4582));
+ IV2 U4292 ( .A(n4540), .Z(n4550));
+ AN2 U4293 ( .A(n4567), .B(n4076), .Z(n4581));
+ AN2 U4294 ( .A(n4086), .B(n4583), .Z(n4571));
+ OR2 U4295 ( .A(n4584), .B(n4585), .Z(n4583));
+ AN2 U4296 ( .A(n4543), .B(n3773), .Z(n4585));
+ AN2 U4297 ( .A(n4586), .B(n4544), .Z(n4584));
+ OR2 U4298 ( .A(n4085), .B(n3778), .Z(n4586));
+ AN2 U4299 ( .A(n4557), .B(n3888), .Z(n4086));
+ OR2 U4300 ( .A(n4587), .B(n4588), .Z(n4569));
+ AN2 U4301 ( .A(n4589), .B(n4590), .Z(n4588));
+ OR2 U4302 ( .A(n4591), .B(n3890), .Z(n4590));
+ AN2 U4303 ( .A(po025), .B(pi192), .Z(n4591));
+ AN2 U4304 ( .A(n4559), .B(n4592), .Z(n4589));
+ OR2 U4305 ( .A(n4561), .B(n4085), .Z(n4592));
+ OR2 U4306 ( .A(n4551), .B(n4353), .Z(n4559));
+ AN2 U4307 ( .A(n4593), .B(n3775), .Z(n4587));
+ AN2 U4308 ( .A(n2837), .B(n4576), .Z(n3775));
+ AN2 U4309 ( .A(n4594), .B(n4540), .Z(n4593));
+ OR2 U4310 ( .A(n4567), .B(n4066), .Z(n4540));
+ OR2 U4311 ( .A(n4539), .B(n3778), .Z(n4594));
+ IV2 U4312 ( .A(n4528), .Z(n4516));
+ OR2 U4313 ( .A(n4595), .B(n4596), .Z(n4497));
+ AN2 U4314 ( .A(n4597), .B(n4598), .Z(n4596));
+ OR2 U4315 ( .A(n4599), .B(n4600), .Z(n4598));
+ AN2 U4316 ( .A(n4601), .B(n4602), .Z(n4600));
+ IV2 U4317 ( .A(n4603), .Z(n4599));
+ OR2 U4318 ( .A(n4602), .B(n4601), .Z(n4603));
+ OR2 U4319 ( .A(n4604), .B(n4605), .Z(n4601));
+ AN2 U4320 ( .A(n3295), .B(n4606), .Z(n4605));
+ AN2 U4321 ( .A(n4450), .B(n3301), .Z(n4604));
+ AN2 U4322 ( .A(n4607), .B(n4608), .Z(n4602));
+ OR2 U4323 ( .A(n4609), .B(n4610), .Z(n4608));
+ IV2 U4324 ( .A(n4611), .Z(n4610));
+ OR2 U4325 ( .A(n4611), .B(n4612), .Z(n4607));
+ IV2 U4326 ( .A(n4609), .Z(n4612));
+ OR2 U4327 ( .A(n4613), .B(n4614), .Z(n4609));
+ OR2 U4328 ( .A(n4615), .B(n4616), .Z(n4614));
+ AN2 U4329 ( .A(n4004), .B(n4617), .Z(n4616));
+ OR2 U4330 ( .A(n4618), .B(n4619), .Z(n4617));
+ AN2 U4331 ( .A(n4620), .B(n4463), .Z(n4619));
+ AN2 U4332 ( .A(n4621), .B(n4464), .Z(n4620));
+ AN2 U4333 ( .A(n4622), .B(n4467), .Z(n4618));
+ AN2 U4334 ( .A(n4623), .B(n4468), .Z(n4622));
+ AN2 U4335 ( .A(n4006), .B(n4624), .Z(n4615));
+ OR2 U4336 ( .A(n4625), .B(n4626), .Z(n4613));
+ AN2 U4337 ( .A(n4627), .B(n4628), .Z(n4626));
+ OR2 U4338 ( .A(n4629), .B(n4630), .Z(n4627));
+ AN2 U4339 ( .A(n4631), .B(pi192), .Z(n4630));
+ AN2 U4340 ( .A(n4632), .B(pi158), .Z(n4631));
+ AN2 U4341 ( .A(n4633), .B(n4634), .Z(n4632));
+ OR2 U4342 ( .A(n4635), .B(n4465), .Z(n4634));
+ OR2 U4343 ( .A(n4464), .B(n4636), .Z(n4633));
+ OR2 U4344 ( .A(n4621), .B(n3301), .Z(n4636));
+ AN2 U4345 ( .A(n4637), .B(n2837), .Z(n4629));
+ AN2 U4346 ( .A(n4638), .B(pi151), .Z(n4637));
+ AN2 U4347 ( .A(n4639), .B(n4640), .Z(n4638));
+ OR2 U4348 ( .A(n4641), .B(n4469), .Z(n4640));
+ OR2 U4349 ( .A(n4468), .B(n4642), .Z(n4639));
+ OR2 U4350 ( .A(n4623), .B(n3301), .Z(n4642));
+ AN2 U4351 ( .A(n4643), .B(po092), .Z(n4625));
+ AN2 U4352 ( .A(n4644), .B(n3295), .Z(n4643));
+ AN2 U4353 ( .A(n4645), .B(n4646), .Z(n4644));
+ OR2 U4354 ( .A(pi192), .B(n4647), .Z(n4646));
+ AN2 U4355 ( .A(n4641), .B(n4648), .Z(n4647));
+ OR2 U4356 ( .A(n2837), .B(n4649), .Z(n4645));
+ AN2 U4357 ( .A(n4635), .B(n3908), .Z(n4649));
+ IV2 U4358 ( .A(n3761), .Z(n4597));
+ AN2 U4359 ( .A(n4650), .B(n3761), .Z(n4595));
+ OR2 U4360 ( .A(n4651), .B(n4652), .Z(n3761));
+ AN2 U4361 ( .A(n4653), .B(n4654), .Z(n4651));
+ AN2 U4362 ( .A(n4333), .B(n4528), .Z(n4654));
+ OR2 U4363 ( .A(n4655), .B(n4656), .Z(n4528));
+ AN2 U4364 ( .A(n4657), .B(n3083), .Z(n4655));
+ AN2 U4365 ( .A(n3018), .B(n4658), .Z(n4657));
+ OR2 U4366 ( .A(n4659), .B(n4660), .Z(n4658));
+ OR2 U4367 ( .A(n4661), .B(n4662), .Z(n4660));
+ AN2 U4368 ( .A(n4663), .B(n3010), .Z(n4662));
+ AN2 U4369 ( .A(n4664), .B(n3049), .Z(n4661));
+ OR2 U4370 ( .A(n4665), .B(n4663), .Z(n4664));
+ AN2 U4371 ( .A(n4666), .B(n3010), .Z(n4665));
+ OR2 U4372 ( .A(n3100), .B(n4667), .Z(n4659));
+ AN2 U4373 ( .A(n4668), .B(n3012), .Z(n4667));
+ OR2 U4374 ( .A(n4669), .B(n4670), .Z(n4668));
+ AN2 U4375 ( .A(n4671), .B(pi201), .Z(n4670));
+ AN2 U4376 ( .A(n4672), .B(n3115), .Z(n4671));
+ OR2 U4377 ( .A(n4673), .B(n3173), .Z(n4672));
+ AN2 U4378 ( .A(n2837), .B(n3049), .Z(n4673));
+ AN2 U4379 ( .A(n4674), .B(pi088), .Z(n4669));
+ AN2 U4380 ( .A(n4675), .B(n3108), .Z(n4674));
+ OR2 U4381 ( .A(n4676), .B(n3064), .Z(n4675));
+ AN2 U4382 ( .A(pi192), .B(n3049), .Z(n4676));
+ AN2 U4383 ( .A(n4341), .B(n4482), .Z(n4653));
+ OR2 U4384 ( .A(n4677), .B(n4678), .Z(n4650));
+ OR2 U4385 ( .A(n4679), .B(n4680), .Z(n4678));
+ OR2 U4386 ( .A(n4681), .B(n4682), .Z(n4680));
+ AN2 U4387 ( .A(n4683), .B(n4684), .Z(n4682));
+ AN2 U4388 ( .A(n4685), .B(n4648), .Z(n4683));
+ AN2 U4389 ( .A(n4686), .B(n4687), .Z(n4681));
+ OR2 U4390 ( .A(n4688), .B(n4689), .Z(n4687));
+ OR2 U4391 ( .A(n4690), .B(n4691), .Z(n4689));
+ AN2 U4392 ( .A(n4692), .B(n4621), .Z(n4691));
+ AN2 U4393 ( .A(n4685), .B(n4623), .Z(n4690));
+ AN2 U4394 ( .A(n4693), .B(n3300), .Z(n4688));
+ IV2 U4395 ( .A(n4684), .Z(n4686));
+ OR2 U4396 ( .A(n4694), .B(n4695), .Z(n4679));
+ AN2 U4397 ( .A(n4696), .B(n3300), .Z(n4695));
+ AN2 U4398 ( .A(po014), .B(n4684), .Z(n4696));
+ OR2 U4399 ( .A(n4697), .B(n4698), .Z(n4684));
+ AN2 U4400 ( .A(n4699), .B(n4450), .Z(n4697));
+ AN2 U4401 ( .A(po039), .B(n4700), .Z(n4694));
+ OR2 U4402 ( .A(n4701), .B(n4702), .Z(n4700));
+ AN2 U4403 ( .A(n4698), .B(n4703), .Z(n4702));
+ AN2 U4404 ( .A(n4704), .B(n4606), .Z(n4698));
+ AN2 U4405 ( .A(n4705), .B(n4706), .Z(n4701));
+ AN2 U4406 ( .A(n4707), .B(n4708), .Z(n4705));
+ OR2 U4407 ( .A(n4704), .B(n3295), .Z(n4708));
+ OR2 U4408 ( .A(n4699), .B(n3301), .Z(n4707));
+ OR2 U4409 ( .A(n4709), .B(n4710), .Z(n4677));
+ AN2 U4410 ( .A(n4711), .B(n4699), .Z(n4710));
+ IV2 U4411 ( .A(n4704), .Z(n4699));
+ AN2 U4412 ( .A(n4450), .B(n4712), .Z(n4711));
+ OR2 U4413 ( .A(po014), .B(n3301), .Z(n4712));
+ AN2 U4414 ( .A(n4713), .B(n4704), .Z(n4709));
+ OR2 U4415 ( .A(n4714), .B(n4715), .Z(n4704));
+ OR2 U4416 ( .A(n4716), .B(n4717), .Z(n4715));
+ OR2 U4417 ( .A(n4718), .B(n4719), .Z(n4717));
+ IV2 U4418 ( .A(n4720), .Z(n4719));
+ OR2 U4419 ( .A(n4721), .B(n4006), .Z(n4720));
+ OR2 U4420 ( .A(n4444), .B(n3756), .Z(n4721));
+ AN2 U4421 ( .A(n4722), .B(n4006), .Z(n4718));
+ AN2 U4422 ( .A(n4444), .B(n4452), .Z(n4722));
+ OR2 U4423 ( .A(n4723), .B(n4724), .Z(n4452));
+ OR2 U4424 ( .A(n4725), .B(n4726), .Z(n4724));
+ AN2 U4425 ( .A(po092), .B(n4009), .Z(n4726));
+ OR2 U4426 ( .A(n4727), .B(n4728), .Z(n4009));
+ AN2 U4427 ( .A(n3295), .B(n4729), .Z(n4728));
+ AN2 U4428 ( .A(n4606), .B(n4457), .Z(n4727));
+ OR2 U4429 ( .A(n4730), .B(n4706), .Z(n4457));
+ OR2 U4430 ( .A(n4731), .B(n4732), .Z(n4706));
+ AN2 U4431 ( .A(n4733), .B(pi192), .Z(n4732));
+ AN2 U4432 ( .A(n4465), .B(n3870), .Z(n4733));
+ AN2 U4433 ( .A(n4734), .B(n2837), .Z(n4731));
+ AN2 U4434 ( .A(n4469), .B(n4735), .Z(n4734));
+ AN2 U4435 ( .A(po039), .B(n4729), .Z(n4730));
+ OR2 U4436 ( .A(po014), .B(n4736), .Z(n4729));
+ AN2 U4437 ( .A(n4737), .B(n4606), .Z(n4725));
+ AN2 U4438 ( .A(po014), .B(n4738), .Z(n4737));
+ OR2 U4439 ( .A(n4739), .B(n4740), .Z(n4738));
+ AN2 U4440 ( .A(n4463), .B(n4464), .Z(n4740));
+ AN2 U4441 ( .A(n4467), .B(n4468), .Z(n4739));
+ OR2 U4442 ( .A(n4741), .B(n4742), .Z(n4723));
+ AN2 U4443 ( .A(n4743), .B(n4463), .Z(n4742));
+ AN2 U4444 ( .A(n3909), .B(pi192), .Z(n4463));
+ IV2 U4445 ( .A(pi158), .Z(n3909));
+ AN2 U4446 ( .A(n4744), .B(n3908), .Z(n4743));
+ OR2 U4447 ( .A(n4745), .B(n3295), .Z(n4744));
+ AN2 U4448 ( .A(n4606), .B(n4464), .Z(n4745));
+ AN2 U4449 ( .A(n4746), .B(n4467), .Z(n4741));
+ AN2 U4450 ( .A(n2837), .B(n4747), .Z(n4467));
+ AN2 U4451 ( .A(n4748), .B(n4648), .Z(n4746));
+ OR2 U4452 ( .A(n4749), .B(n3295), .Z(n4748));
+ AN2 U4453 ( .A(n4606), .B(n4468), .Z(n4749));
+ AN2 U4454 ( .A(n3756), .B(n4611), .Z(n4716));
+ OR2 U4455 ( .A(n4750), .B(n4751), .Z(n4611));
+ AN2 U4456 ( .A(n4004), .B(n4444), .Z(n4750));
+ IV2 U4457 ( .A(n4006), .Z(n4004));
+ AN2 U4458 ( .A(n4628), .B(n4752), .Z(n3756));
+ OR2 U4459 ( .A(n3758), .B(n3760), .Z(n4714));
+ AN2 U4460 ( .A(n4448), .B(n4751), .Z(n3758));
+ OR2 U4461 ( .A(n4713), .B(n4693), .Z(n4448));
+ OR2 U4462 ( .A(n4753), .B(n4754), .Z(n4693));
+ AN2 U4463 ( .A(n4621), .B(pi192), .Z(n4754));
+ AN2 U4464 ( .A(n4623), .B(n2837), .Z(n4753));
+ AN2 U4465 ( .A(n3301), .B(n4624), .Z(n4713));
+ OR2 U4466 ( .A(n4755), .B(n4756), .Z(po042));
+ AN2 U4467 ( .A(n4757), .B(n2837), .Z(n4756));
+ OR2 U4468 ( .A(n4758), .B(n4759), .Z(n4757));
+ OR2 U4469 ( .A(n4760), .B(n4761), .Z(n4759));
+ AN2 U4470 ( .A(n4762), .B(n4763), .Z(n4761));
+ OR2 U4471 ( .A(n4764), .B(n4765), .Z(n4763));
+ IV2 U4472 ( .A(n4766), .Z(n4762));
+ AN2 U4473 ( .A(n4765), .B(n4764), .Z(n4766));
+ OR2 U4474 ( .A(n4767), .B(n4768), .Z(n4764));
+ AN2 U4475 ( .A(n4769), .B(n4770), .Z(n4768));
+ AN2 U4476 ( .A(n4771), .B(pi028), .Z(n4767));
+ AN2 U4477 ( .A(n4772), .B(n4773), .Z(n4765));
+ OR2 U4478 ( .A(n4774), .B(pi094), .Z(n4773));
+ IV2 U4479 ( .A(n4775), .Z(n4772));
+ AN2 U4480 ( .A(n4774), .B(pi094), .Z(n4775));
+ AN2 U4481 ( .A(n4776), .B(n4777), .Z(n4774));
+ OR2 U4482 ( .A(n4778), .B(pi173), .Z(n4777));
+ OR2 U4483 ( .A(n4779), .B(pi163), .Z(n4776));
+ IV2 U4484 ( .A(pi173), .Z(n4779));
+ AN2 U4485 ( .A(n4780), .B(n4781), .Z(n4760));
+ IV2 U4486 ( .A(n4782), .Z(n4781));
+ AN2 U4487 ( .A(n4783), .B(n4784), .Z(n4782));
+ OR2 U4488 ( .A(n4784), .B(n4783), .Z(n4780));
+ AN2 U4489 ( .A(n4785), .B(n4786), .Z(n4783));
+ IV2 U4490 ( .A(n4787), .Z(n4786));
+ AN2 U4491 ( .A(n4788), .B(n4789), .Z(n4787));
+ OR2 U4492 ( .A(n4789), .B(n4788), .Z(n4785));
+ OR2 U4493 ( .A(n4790), .B(n4791), .Z(n4788));
+ AN2 U4494 ( .A(pi025), .B(n4792), .Z(n4791));
+ IV2 U4495 ( .A(n4793), .Z(n4790));
+ OR2 U4496 ( .A(n4792), .B(pi025), .Z(n4793));
+ IV2 U4497 ( .A(pi035), .Z(n4792));
+ AN2 U4498 ( .A(n4794), .B(n4795), .Z(n4789));
+ IV2 U4499 ( .A(n4796), .Z(n4795));
+ AN2 U4500 ( .A(pi056), .B(n4797), .Z(n4796));
+ OR2 U4501 ( .A(n4797), .B(pi056), .Z(n4794));
+ IV2 U4502 ( .A(pi100), .Z(n4797));
+ OR2 U4503 ( .A(n4798), .B(n4799), .Z(n4784));
+ IV2 U4504 ( .A(n4800), .Z(n4799));
+ OR2 U4505 ( .A(n4801), .B(n4802), .Z(n4800));
+ AN2 U4506 ( .A(n4802), .B(n4801), .Z(n4798));
+ AN2 U4507 ( .A(n4803), .B(n4804), .Z(n4801));
+ IV2 U4508 ( .A(n4805), .Z(n4804));
+ AN2 U4509 ( .A(pi126), .B(n4806), .Z(n4805));
+ OR2 U4510 ( .A(n4806), .B(pi126), .Z(n4803));
+ IV2 U4511 ( .A(pi146), .Z(n4806));
+ OR2 U4512 ( .A(n4807), .B(n4808), .Z(n4802));
+ AN2 U4513 ( .A(pi190), .B(n4809), .Z(n4808));
+ IV2 U4514 ( .A(pi202), .Z(n4809));
+ AN2 U4515 ( .A(pi202), .B(n4810), .Z(n4807));
+ IV2 U4516 ( .A(pi190), .Z(n4810));
+ OR2 U4517 ( .A(n4811), .B(n4812), .Z(n4758));
+ AN2 U4518 ( .A(n4813), .B(n4814), .Z(n4812));
+ IV2 U4519 ( .A(n4815), .Z(n4814));
+ AN2 U4520 ( .A(n4816), .B(n4817), .Z(n4815));
+ OR2 U4521 ( .A(n4817), .B(n4816), .Z(n4813));
+ AN2 U4522 ( .A(n4818), .B(n4819), .Z(n4816));
+ OR2 U4523 ( .A(n4820), .B(pi019), .Z(n4819));
+ OR2 U4524 ( .A(n4821), .B(n4822), .Z(n4818));
+ IV2 U4525 ( .A(pi019), .Z(n4822));
+ OR2 U4526 ( .A(n4823), .B(n4824), .Z(n4817));
+ IV2 U4527 ( .A(n4825), .Z(n4824));
+ OR2 U4528 ( .A(n4826), .B(pi085), .Z(n4825));
+ AN2 U4529 ( .A(n4826), .B(pi085), .Z(n4823));
+ AN2 U4530 ( .A(n4827), .B(n4828), .Z(n4826));
+ OR2 U4531 ( .A(n4829), .B(pi167), .Z(n4828));
+ IV2 U4532 ( .A(pi110), .Z(n4829));
+ OR2 U4533 ( .A(n4830), .B(pi110), .Z(n4827));
+ IV2 U4534 ( .A(pi167), .Z(n4830));
+ AN2 U4535 ( .A(n4831), .B(n4832), .Z(n4811));
+ IV2 U4536 ( .A(n4833), .Z(n4832));
+ AN2 U4537 ( .A(n4834), .B(n4835), .Z(n4833));
+ OR2 U4538 ( .A(n4835), .B(n4834), .Z(n4831));
+ AN2 U4539 ( .A(n4836), .B(n4837), .Z(n4834));
+ OR2 U4540 ( .A(n4838), .B(pi020), .Z(n4837));
+ OR2 U4541 ( .A(n4839), .B(n4840), .Z(n4836));
+ IV2 U4542 ( .A(pi020), .Z(n4840));
+ OR2 U4543 ( .A(n4841), .B(n4842), .Z(n4835));
+ IV2 U4544 ( .A(n4843), .Z(n4842));
+ OR2 U4545 ( .A(n4844), .B(pi047), .Z(n4843));
+ AN2 U4546 ( .A(n4844), .B(pi047), .Z(n4841));
+ AN2 U4547 ( .A(n4845), .B(n4846), .Z(n4844));
+ OR2 U4548 ( .A(n4847), .B(pi153), .Z(n4846));
+ IV2 U4549 ( .A(pi075), .Z(n4847));
+ OR2 U4550 ( .A(n4848), .B(pi075), .Z(n4845));
+ IV2 U4551 ( .A(pi153), .Z(n4848));
+ AN2 U4552 ( .A(pi192), .B(n4849), .Z(n4755));
+ OR2 U4553 ( .A(n4850), .B(n4851), .Z(n4849));
+ OR2 U4554 ( .A(n4852), .B(n4853), .Z(n4851));
+ AN2 U4555 ( .A(n4854), .B(n4855), .Z(n4853));
+ OR2 U4556 ( .A(n4856), .B(n4857), .Z(n4855));
+ IV2 U4557 ( .A(n4858), .Z(n4854));
+ AN2 U4558 ( .A(n4857), .B(n4856), .Z(n4858));
+ OR2 U4559 ( .A(n4859), .B(n4860), .Z(n4856));
+ AN2 U4560 ( .A(n4839), .B(n4861), .Z(n4860));
+ AN2 U4561 ( .A(n4838), .B(po014), .Z(n4859));
+ IV2 U4562 ( .A(n4839), .Z(n4838));
+ OR2 U4563 ( .A(n4862), .B(n4863), .Z(n4839));
+ AN2 U4564 ( .A(n4864), .B(pi192), .Z(n4863));
+ OR2 U4565 ( .A(n4865), .B(n4866), .Z(n4864));
+ IV2 U4566 ( .A(n4867), .Z(n4866));
+ OR2 U4567 ( .A(n4868), .B(n4869), .Z(n4867));
+ AN2 U4568 ( .A(n4869), .B(n4868), .Z(n4865));
+ AN2 U4569 ( .A(n4870), .B(n4871), .Z(n4868));
+ OR2 U4570 ( .A(n4872), .B(po024), .Z(n4871));
+ IV2 U4571 ( .A(n4873), .Z(n4872));
+ OR2 U4572 ( .A(n4873), .B(n4874), .Z(n4870));
+ OR2 U4573 ( .A(n4875), .B(n4876), .Z(n4873));
+ AN2 U4574 ( .A(po025), .B(n4877), .Z(n4876));
+ AN2 U4575 ( .A(po059), .B(n4557), .Z(n4875));
+ OR2 U4576 ( .A(n4878), .B(n4879), .Z(n4869));
+ AN2 U4577 ( .A(n4880), .B(n4881), .Z(n4879));
+ AN2 U4578 ( .A(n4882), .B(po072), .Z(n4878));
+ IV2 U4579 ( .A(n4880), .Z(n4882));
+ OR2 U4580 ( .A(n4883), .B(n4884), .Z(n4880));
+ AN2 U4581 ( .A(po084), .B(n4885), .Z(n4884));
+ AN2 U4582 ( .A(po102), .B(n4886), .Z(n4883));
+ IV2 U4583 ( .A(po084), .Z(n4886));
+ AN2 U4584 ( .A(n4887), .B(n2837), .Z(n4862));
+ OR2 U4585 ( .A(n4888), .B(n4889), .Z(n4887));
+ AN2 U4586 ( .A(n4890), .B(n4891), .Z(n4889));
+ IV2 U4587 ( .A(n4892), .Z(n4888));
+ OR2 U4588 ( .A(n4891), .B(n4890), .Z(n4892));
+ OR2 U4589 ( .A(n4893), .B(n4894), .Z(n4890));
+ IV2 U4590 ( .A(n4895), .Z(n4894));
+ OR2 U4591 ( .A(n4896), .B(pi014), .Z(n4895));
+ AN2 U4592 ( .A(n4896), .B(pi014), .Z(n4893));
+ AN2 U4593 ( .A(n4897), .B(n4898), .Z(n4896));
+ OR2 U4594 ( .A(n4899), .B(pi111), .Z(n4898));
+ OR2 U4595 ( .A(n4900), .B(pi097), .Z(n4897));
+ IV2 U4596 ( .A(pi111), .Z(n4900));
+ AN2 U4597 ( .A(n4901), .B(n4902), .Z(n4891));
+ OR2 U4598 ( .A(n4903), .B(pi143), .Z(n4902));
+ IV2 U4599 ( .A(n4904), .Z(n4901));
+ AN2 U4600 ( .A(n4903), .B(pi143), .Z(n4904));
+ AN2 U4601 ( .A(n4905), .B(n4906), .Z(n4903));
+ OR2 U4602 ( .A(n4907), .B(pi189), .Z(n4906));
+ IV2 U4603 ( .A(n4908), .Z(n4905));
+ AN2 U4604 ( .A(pi189), .B(n4907), .Z(n4908));
+ IV2 U4605 ( .A(pi176), .Z(n4907));
+ AN2 U4606 ( .A(n4909), .B(n4910), .Z(n4857));
+ OR2 U4607 ( .A(n4911), .B(po039), .Z(n4910));
+ IV2 U4608 ( .A(n4912), .Z(n4911));
+ OR2 U4609 ( .A(n4912), .B(n3300), .Z(n4909));
+ OR2 U4610 ( .A(n4913), .B(n4914), .Z(n4912));
+ AN2 U4611 ( .A(po063), .B(n4628), .Z(n4914));
+ AN2 U4612 ( .A(po092), .B(n4915), .Z(n4913));
+ AN2 U4613 ( .A(n4916), .B(n4917), .Z(n4852));
+ IV2 U4614 ( .A(n4918), .Z(n4917));
+ AN2 U4615 ( .A(n4919), .B(n4920), .Z(n4918));
+ OR2 U4616 ( .A(n4920), .B(n4919), .Z(n4916));
+ IV2 U4617 ( .A(n4921), .Z(n4919));
+ OR2 U4618 ( .A(n4922), .B(n4923), .Z(n4921));
+ AN2 U4619 ( .A(n4821), .B(n3391), .Z(n4923));
+ IV2 U4620 ( .A(n4924), .Z(n3391));
+ AN2 U4621 ( .A(n4924), .B(n4820), .Z(n4922));
+ IV2 U4622 ( .A(n4821), .Z(n4820));
+ OR2 U4623 ( .A(n4925), .B(n4926), .Z(n4821));
+ AN2 U4624 ( .A(n4927), .B(pi192), .Z(n4926));
+ OR2 U4625 ( .A(n4928), .B(n4929), .Z(n4927));
+ IV2 U4626 ( .A(n4930), .Z(n4929));
+ OR2 U4627 ( .A(n4931), .B(n4932), .Z(n4930));
+ AN2 U4628 ( .A(n4932), .B(n4931), .Z(n4928));
+ AN2 U4629 ( .A(n4933), .B(n4934), .Z(n4931));
+ OR2 U4630 ( .A(n4935), .B(po001), .Z(n4934));
+ IV2 U4631 ( .A(n4936), .Z(n4935));
+ OR2 U4632 ( .A(n4936), .B(n4937), .Z(n4933));
+ OR2 U4633 ( .A(n4938), .B(n4939), .Z(n4936));
+ AN2 U4634 ( .A(po011), .B(n4441), .Z(n4939));
+ AN2 U4635 ( .A(po036), .B(n3688), .Z(n4938));
+ OR2 U4636 ( .A(n4940), .B(n4941), .Z(n4932));
+ AN2 U4637 ( .A(n4942), .B(n4943), .Z(n4941));
+ AN2 U4638 ( .A(n4944), .B(po057), .Z(n4940));
+ IV2 U4639 ( .A(n4942), .Z(n4944));
+ OR2 U4640 ( .A(n4945), .B(n4946), .Z(n4942));
+ AN2 U4641 ( .A(po069), .B(n4947), .Z(n4946));
+ AN2 U4642 ( .A(po082), .B(n4948), .Z(n4945));
+ IV2 U4643 ( .A(po069), .Z(n4948));
+ AN2 U4644 ( .A(n4949), .B(n2837), .Z(n4925));
+ OR2 U4645 ( .A(n4950), .B(n4951), .Z(n4949));
+ AN2 U4646 ( .A(n4952), .B(n4953), .Z(n4951));
+ IV2 U4647 ( .A(n4954), .Z(n4950));
+ OR2 U4648 ( .A(n4953), .B(n4952), .Z(n4954));
+ OR2 U4649 ( .A(n4955), .B(n4956), .Z(n4952));
+ IV2 U4650 ( .A(n4957), .Z(n4956));
+ OR2 U4651 ( .A(n4958), .B(pi024), .Z(n4957));
+ AN2 U4652 ( .A(n4958), .B(pi024), .Z(n4955));
+ AN2 U4653 ( .A(n4959), .B(n4960), .Z(n4958));
+ OR2 U4654 ( .A(n4961), .B(pi078), .Z(n4960));
+ OR2 U4655 ( .A(n4962), .B(pi030), .Z(n4959));
+ IV2 U4656 ( .A(pi078), .Z(n4962));
+ AN2 U4657 ( .A(n4963), .B(n4964), .Z(n4953));
+ OR2 U4658 ( .A(n4965), .B(pi087), .Z(n4964));
+ IV2 U4659 ( .A(n4966), .Z(n4963));
+ AN2 U4660 ( .A(n4965), .B(pi087), .Z(n4966));
+ AN2 U4661 ( .A(n4967), .B(n4968), .Z(n4965));
+ OR2 U4662 ( .A(n4969), .B(pi164), .Z(n4968));
+ OR2 U4663 ( .A(n4970), .B(pi159), .Z(n4967));
+ IV2 U4664 ( .A(pi164), .Z(n4970));
+ OR2 U4665 ( .A(n4971), .B(n4972), .Z(n4924));
+ AN2 U4666 ( .A(po027), .B(n3512), .Z(n4972));
+ AN2 U4667 ( .A(po104), .B(n3363), .Z(n4971));
+ OR2 U4668 ( .A(n4973), .B(n4974), .Z(n4920));
+ AN2 U4669 ( .A(po038), .B(n3380), .Z(n4974));
+ AN2 U4670 ( .A(po071), .B(n4975), .Z(n4973));
+ OR2 U4671 ( .A(n4976), .B(n4977), .Z(n4850));
+ AN2 U4672 ( .A(n4978), .B(n4979), .Z(n4977));
+ OR2 U4673 ( .A(n4980), .B(n4981), .Z(n4979));
+ IV2 U4674 ( .A(n4982), .Z(n4978));
+ AN2 U4675 ( .A(n4981), .B(n4980), .Z(n4982));
+ OR2 U4676 ( .A(n4983), .B(n4984), .Z(n4980));
+ AN2 U4677 ( .A(n4769), .B(n3049), .Z(n4984));
+ AN2 U4678 ( .A(n4771), .B(po010), .Z(n4983));
+ IV2 U4679 ( .A(n4769), .Z(n4771));
+ OR2 U4680 ( .A(n4985), .B(n4986), .Z(n4769));
+ AN2 U4681 ( .A(n4987), .B(pi192), .Z(n4986));
+ OR2 U4682 ( .A(n4988), .B(n4989), .Z(n4987));
+ IV2 U4683 ( .A(n4990), .Z(n4989));
+ OR2 U4684 ( .A(n4991), .B(n4992), .Z(n4990));
+ AN2 U4685 ( .A(n4992), .B(n4991), .Z(n4988));
+ AN2 U4686 ( .A(n4993), .B(n4994), .Z(n4991));
+ OR2 U4687 ( .A(n4995), .B(po031), .Z(n4994));
+ IV2 U4688 ( .A(n4996), .Z(n4995));
+ OR2 U4689 ( .A(n4996), .B(n2962), .Z(n4993));
+ OR2 U4690 ( .A(n4997), .B(n4998), .Z(n4996));
+ AN2 U4691 ( .A(po044), .B(n4999), .Z(n4998));
+ IV2 U4692 ( .A(po052), .Z(n4999));
+ AN2 U4693 ( .A(po052), .B(n5000), .Z(n4997));
+ OR2 U4694 ( .A(n5001), .B(n5002), .Z(n4992));
+ AN2 U4695 ( .A(n5003), .B(n5004), .Z(n5002));
+ AN2 U4696 ( .A(n5005), .B(po079), .Z(n5001));
+ IV2 U4697 ( .A(n5003), .Z(n5005));
+ OR2 U4698 ( .A(n5006), .B(n5007), .Z(n5003));
+ AN2 U4699 ( .A(po106), .B(n2931), .Z(n5007));
+ AN2 U4700 ( .A(po107), .B(n5008), .Z(n5006));
+ AN2 U4701 ( .A(n5009), .B(n2837), .Z(n4985));
+ OR2 U4702 ( .A(n5010), .B(n5011), .Z(n5009));
+ IV2 U4703 ( .A(n5012), .Z(n5011));
+ OR2 U4704 ( .A(n5013), .B(n5014), .Z(n5012));
+ AN2 U4705 ( .A(n5014), .B(n5013), .Z(n5010));
+ AN2 U4706 ( .A(n5015), .B(n5016), .Z(n5013));
+ OR2 U4707 ( .A(n5017), .B(pi011), .Z(n5016));
+ IV2 U4708 ( .A(n5018), .Z(n5017));
+ OR2 U4709 ( .A(n5018), .B(n5019), .Z(n5015));
+ OR2 U4710 ( .A(n5020), .B(n5021), .Z(n5018));
+ AN2 U4711 ( .A(pi021), .B(n5022), .Z(n5021));
+ AN2 U4712 ( .A(pi032), .B(n5023), .Z(n5020));
+ IV2 U4713 ( .A(pi021), .Z(n5023));
+ OR2 U4714 ( .A(n5024), .B(n5025), .Z(n5014));
+ AN2 U4715 ( .A(n5026), .B(n5027), .Z(n5025));
+ AN2 U4716 ( .A(n5028), .B(pi086), .Z(n5024));
+ IV2 U4717 ( .A(n5026), .Z(n5028));
+ OR2 U4718 ( .A(n5029), .B(n5030), .Z(n5026));
+ AN2 U4719 ( .A(pi115), .B(n5031), .Z(n5030));
+ AN2 U4720 ( .A(pi165), .B(n5032), .Z(n5029));
+ IV2 U4721 ( .A(pi115), .Z(n5032));
+ AN2 U4722 ( .A(n5033), .B(n5034), .Z(n4981));
+ OR2 U4723 ( .A(n5035), .B(po035), .Z(n5034));
+ IV2 U4724 ( .A(n5036), .Z(n5035));
+ OR2 U4725 ( .A(n5036), .B(n5037), .Z(n5033));
+ OR2 U4726 ( .A(n5038), .B(n5039), .Z(n5036));
+ AN2 U4727 ( .A(po070), .B(n3286), .Z(n5039));
+ AN2 U4728 ( .A(po099), .B(n5040), .Z(n5038));
+ AN2 U4729 ( .A(n5041), .B(n5042), .Z(n4976));
+ OR2 U4730 ( .A(n5043), .B(n5044), .Z(n5042));
+ IV2 U4731 ( .A(n5045), .Z(n5041));
+ AN2 U4732 ( .A(n5044), .B(n5043), .Z(n5045));
+ OR2 U4733 ( .A(n5046), .B(n5047), .Z(n5043));
+ IV2 U4734 ( .A(n5048), .Z(n5047));
+ OR2 U4735 ( .A(n5049), .B(n5050), .Z(n5048));
+ AN2 U4736 ( .A(n5050), .B(n5049), .Z(n5046));
+ AN2 U4737 ( .A(n5051), .B(n5052), .Z(n5049));
+ OR2 U4738 ( .A(n4319), .B(po013), .Z(n5052));
+ OR2 U4739 ( .A(n5053), .B(po004), .Z(n5051));
+ IV2 U4740 ( .A(po013), .Z(n5053));
+ OR2 U4741 ( .A(n5054), .B(n5055), .Z(n5050));
+ AN2 U4742 ( .A(po028), .B(n4013), .Z(n5055));
+ AN2 U4743 ( .A(po040), .B(n5056), .Z(n5054));
+ AN2 U4744 ( .A(n5057), .B(n5058), .Z(n5044));
+ OR2 U4745 ( .A(n5059), .B(n5060), .Z(n5058));
+ IV2 U4746 ( .A(n5061), .Z(n5059));
+ OR2 U4747 ( .A(n5062), .B(n5061), .Z(n5057));
+ OR2 U4748 ( .A(n5063), .B(n5064), .Z(n5061));
+ AN2 U4749 ( .A(po064), .B(n4128), .Z(n5064));
+ AN2 U4750 ( .A(po085), .B(n4133), .Z(n5063));
+ IV2 U4751 ( .A(n5060), .Z(n5062));
+ OR2 U4752 ( .A(n5065), .B(n5066), .Z(n5060));
+ AN2 U4753 ( .A(po091), .B(n3265), .Z(n5066));
+ AN2 U4754 ( .A(po103), .B(n4201), .Z(n5065));
+ IV2 U4755 ( .A(n5067), .Z(po041));
+ AN2 U4756 ( .A(n5068), .B(pi193), .Z(n5067));
+ AN2 U4757 ( .A(pi057), .B(n5069), .Z(n5068));
+ IV2 U4758 ( .A(pi037), .Z(n5069));
+ OR2 U4759 ( .A(n5070), .B(n5071), .Z(po037));
+ AN2 U4760 ( .A(n3021), .B(n5072), .Z(n5071));
+ OR2 U4761 ( .A(n5073), .B(n5074), .Z(n5072));
+ AN2 U4762 ( .A(n3018), .B(n5075), .Z(n5073));
+ OR2 U4763 ( .A(n5076), .B(n5077), .Z(n5075));
+ AN2 U4764 ( .A(n4663), .B(n3284), .Z(n5076));
+ OR2 U4765 ( .A(n5078), .B(n5079), .Z(n4663));
+ AN2 U4766 ( .A(n3064), .B(n3108), .Z(n5079));
+ AN2 U4767 ( .A(n3173), .B(n3115), .Z(n5078));
+ AN2 U4768 ( .A(n3083), .B(n5080), .Z(n5070));
+ OR2 U4769 ( .A(n5081), .B(n5082), .Z(n5080));
+ OR2 U4770 ( .A(n5083), .B(n5084), .Z(n5082));
+ AN2 U4771 ( .A(po070), .B(n4327), .Z(n5084));
+ OR2 U4772 ( .A(n5085), .B(n5086), .Z(n4327));
+ OR2 U4773 ( .A(n5087), .B(n5088), .Z(n5086));
+ AN2 U4774 ( .A(n3273), .B(n5089), .Z(n5088));
+ IV2 U4775 ( .A(n3284), .Z(n3273));
+ AN2 U4776 ( .A(n5090), .B(n3274), .Z(n5087));
+ OR2 U4777 ( .A(n5091), .B(n3282), .Z(n5085));
+ IV2 U4778 ( .A(n4666), .Z(n3282));
+ AN2 U4779 ( .A(n5092), .B(n3199), .Z(n5083));
+ OR2 U4780 ( .A(n5093), .B(n5094), .Z(n5092));
+ OR2 U4781 ( .A(n5095), .B(n5096), .Z(n5094));
+ AN2 U4782 ( .A(n5090), .B(po010), .Z(n5096));
+ AN2 U4783 ( .A(n3037), .B(n3061), .Z(n5090));
+ AN2 U4784 ( .A(n5097), .B(n5098), .Z(n5095));
+ AN2 U4785 ( .A(n3037), .B(n5099), .Z(n5098));
+ AN2 U4786 ( .A(n5100), .B(n3120), .Z(n5097));
+ OR2 U4787 ( .A(n5101), .B(n3061), .Z(n3120));
+ AN2 U4788 ( .A(n3106), .B(pi192), .Z(n3061));
+ AN2 U4789 ( .A(po010), .B(pi192), .Z(n5101));
+ AN2 U4790 ( .A(n3082), .B(pi192), .Z(n5093));
+ IV2 U4791 ( .A(n3108), .Z(n3082));
+ OR2 U4792 ( .A(pi033), .B(n3286), .Z(n3108));
+ OR2 U4793 ( .A(n5102), .B(n5103), .Z(n5081));
+ AN2 U4794 ( .A(n3015), .B(n5104), .Z(n5103));
+ IV2 U4795 ( .A(n3018), .Z(n3015));
+ AN2 U4796 ( .A(n5105), .B(n3205), .Z(n5102));
+ OR2 U4797 ( .A(n5106), .B(n5107), .Z(n5105));
+ OR2 U4798 ( .A(n5091), .B(n5108), .Z(n5107));
+ AN2 U4799 ( .A(n5100), .B(n5109), .Z(n5108));
+ OR2 U4800 ( .A(n5110), .B(n5111), .Z(n5109));
+ AN2 U4801 ( .A(n5112), .B(n2925), .Z(n5111));
+ AN2 U4802 ( .A(po010), .B(n5089), .Z(n5112));
+ IV2 U4803 ( .A(n3100), .Z(n5089));
+ AN2 U4804 ( .A(n5113), .B(n3080), .Z(n5110));
+ AN2 U4805 ( .A(n2837), .B(po010), .Z(n3080));
+ AN2 U4806 ( .A(n3112), .B(n5099), .Z(n5113));
+ AN2 U4807 ( .A(n3065), .B(n5114), .Z(n5091));
+ AN2 U4808 ( .A(n3112), .B(n3274), .Z(n5114));
+ IV2 U4809 ( .A(n3280), .Z(n3274));
+ AN2 U4810 ( .A(n2837), .B(n5115), .Z(n3065));
+ AN2 U4811 ( .A(n3073), .B(n2837), .Z(n5106));
+ IV2 U4812 ( .A(n3115), .Z(n3073));
+ OR2 U4813 ( .A(pi141), .B(n3286), .Z(n3115));
+ OR2 U4814 ( .A(n5116), .B(n5117), .Z(po034));
+ OR2 U4815 ( .A(n5118), .B(n5119), .Z(n5117));
+ AN2 U4816 ( .A(pi054), .B(n5120), .Z(n5119));
+ AN2 U4817 ( .A(n5121), .B(n5122), .Z(n5118));
+ AN2 U4818 ( .A(n5123), .B(n5124), .Z(n5122));
+ OR2 U4819 ( .A(po085), .B(po064), .Z(n5124));
+ OR2 U4820 ( .A(n4125), .B(n4133), .Z(n5123));
+ AN2 U4821 ( .A(n4129), .B(n4128), .Z(n4125));
+ AN2 U4822 ( .A(pi052), .B(n5125), .Z(n5121));
+ AN2 U4823 ( .A(n5126), .B(n5127), .Z(n5116));
+ OR2 U4824 ( .A(n4167), .B(n5128), .Z(n5127));
+ OR2 U4825 ( .A(n5129), .B(n5130), .Z(n5128));
+ AN2 U4826 ( .A(n5131), .B(po064), .Z(n5130));
+ AN2 U4827 ( .A(pi054), .B(po085), .Z(n5131));
+ AN2 U4828 ( .A(n4129), .B(n4133), .Z(n5129));
+ OR2 U4829 ( .A(n5132), .B(n5133), .Z(po033));
+ AN2 U4830 ( .A(n3371), .B(n5134), .Z(n5133));
+ OR2 U4831 ( .A(n5135), .B(n5136), .Z(n5134));
+ AN2 U4832 ( .A(n5137), .B(n3412), .Z(n5132));
+ OR2 U4833 ( .A(n5138), .B(n5139), .Z(n5137));
+ OR2 U4834 ( .A(n5140), .B(n5141), .Z(po030));
+ AN2 U4835 ( .A(n5142), .B(pi192), .Z(n5141));
+ OR2 U4836 ( .A(n5143), .B(n5144), .Z(n5142));
+ AN2 U4837 ( .A(n2834), .B(n5145), .Z(n5144));
+ OR2 U4838 ( .A(n5146), .B(n5147), .Z(n5145));
+ AN2 U4839 ( .A(n2998), .B(n3847), .Z(n5147));
+ AN2 U4840 ( .A(n5148), .B(n5149), .Z(n5146));
+ OR2 U4841 ( .A(n2862), .B(n5150), .Z(n5149));
+ OR2 U4842 ( .A(n2880), .B(n5151), .Z(n5150));
+ AN2 U4843 ( .A(n2887), .B(n2901), .Z(n5151));
+ AN2 U4844 ( .A(n2891), .B(n5152), .Z(n5148));
+ IV2 U4845 ( .A(n5153), .Z(n5152));
+ AN2 U4846 ( .A(n5154), .B(n2833), .Z(n5143));
+ OR2 U4847 ( .A(n5155), .B(n5156), .Z(n5154));
+ AN2 U4848 ( .A(n5157), .B(n5158), .Z(n5155));
+ AN2 U4849 ( .A(n2930), .B(n2878), .Z(n5158));
+ AN2 U4850 ( .A(n5159), .B(n2837), .Z(n5140));
+ OR2 U4851 ( .A(n5160), .B(n5161), .Z(n5159));
+ AN2 U4852 ( .A(n2846), .B(n5162), .Z(n5161));
+ OR2 U4853 ( .A(n5163), .B(n5164), .Z(n5162));
+ AN2 U4854 ( .A(n2998), .B(n5165), .Z(n5164));
+ AN2 U4855 ( .A(n5166), .B(n5167), .Z(n5163));
+ OR2 U4856 ( .A(n5168), .B(n5169), .Z(n5167));
+ AN2 U4857 ( .A(n3222), .B(n2946), .Z(n5168));
+ OR2 U4858 ( .A(n5170), .B(n2959), .Z(n3222));
+ AN2 U4859 ( .A(n2982), .B(n2901), .Z(n2959));
+ AN2 U4860 ( .A(po107), .B(n5171), .Z(n5170));
+ IV2 U4861 ( .A(n2981), .Z(n5171));
+ AN2 U4862 ( .A(pi081), .B(pi200), .Z(n2981));
+ AN2 U4863 ( .A(n2947), .B(n5172), .Z(n5166));
+ AN2 U4864 ( .A(n5173), .B(n2845), .Z(n5160));
+ OR2 U4865 ( .A(n5174), .B(n5175), .Z(n5173));
+ AN2 U4866 ( .A(n5157), .B(n5176), .Z(n5174));
+ AN2 U4867 ( .A(n2908), .B(n2938), .Z(n5176));
+ OR2 U4868 ( .A(pi081), .B(n2931), .Z(n2938));
+ IV2 U4869 ( .A(n5169), .Z(n2908));
+ AN2 U4870 ( .A(n2861), .B(pi200), .Z(n5157));
+ OR2 U4871 ( .A(n5177), .B(n5178), .Z(po029));
+ OR2 U4872 ( .A(n5179), .B(n5180), .Z(n5178));
+ AN2 U4873 ( .A(n5181), .B(n4313), .Z(n5180));
+ AN2 U4874 ( .A(n3945), .B(n5182), .Z(n5179));
+ OR2 U4875 ( .A(n5183), .B(n5184), .Z(n5182));
+ OR2 U4876 ( .A(n5185), .B(n5186), .Z(n5184));
+ AN2 U4877 ( .A(n5187), .B(pi186), .Z(n5186));
+ OR2 U4878 ( .A(n5188), .B(n5189), .Z(n5187));
+ AN2 U4879 ( .A(n5190), .B(n5191), .Z(n5189));
+ AN2 U4880 ( .A(n5192), .B(pi124), .Z(n5188));
+ IV2 U4881 ( .A(n5190), .Z(n5192));
+ AN2 U4882 ( .A(n5193), .B(n5194), .Z(n5185));
+ OR2 U4883 ( .A(n5195), .B(n5196), .Z(n5193));
+ AN2 U4884 ( .A(n5190), .B(pi124), .Z(n5196));
+ OR2 U4885 ( .A(n5197), .B(n5198), .Z(n5190));
+ AN2 U4886 ( .A(n5199), .B(n5200), .Z(n5198));
+ AN2 U4887 ( .A(n5201), .B(pi109), .Z(n5197));
+ IV2 U4888 ( .A(n5199), .Z(n5201));
+ AN2 U4889 ( .A(n5202), .B(n5191), .Z(n5195));
+ OR2 U4890 ( .A(n5203), .B(n5204), .Z(n5202));
+ AN2 U4891 ( .A(n5199), .B(pi109), .Z(n5204));
+ OR2 U4892 ( .A(n5205), .B(n5206), .Z(n5199));
+ AN2 U4893 ( .A(n5207), .B(n5208), .Z(n5206));
+ AN2 U4894 ( .A(n5181), .B(pi055), .Z(n5205));
+ AN2 U4895 ( .A(n5209), .B(n5200), .Z(n5203));
+ AN2 U4896 ( .A(pi055), .B(n5207), .Z(n5209));
+ AN2 U4897 ( .A(n5210), .B(n5211), .Z(n5183));
+ OR2 U4898 ( .A(n5212), .B(n5213), .Z(n5211));
+ IV2 U4899 ( .A(n5214), .Z(n5210));
+ AN2 U4900 ( .A(n5213), .B(n5212), .Z(n5214));
+ OR2 U4901 ( .A(n5215), .B(n5216), .Z(n5212));
+ IV2 U4902 ( .A(n5217), .Z(n5216));
+ OR2 U4903 ( .A(n5218), .B(pi006), .Z(n5217));
+ AN2 U4904 ( .A(n5218), .B(pi006), .Z(n5215));
+ AN2 U4905 ( .A(n5219), .B(n5220), .Z(n5218));
+ OR2 U4906 ( .A(n5221), .B(pi061), .Z(n5220));
+ IV2 U4907 ( .A(pi051), .Z(n5221));
+ OR2 U4908 ( .A(n5222), .B(pi051), .Z(n5219));
+ IV2 U4909 ( .A(pi061), .Z(n5222));
+ AN2 U4910 ( .A(n5223), .B(n5224), .Z(n5213));
+ IV2 U4911 ( .A(n5225), .Z(n5224));
+ AN2 U4912 ( .A(n5226), .B(n5227), .Z(n5225));
+ OR2 U4913 ( .A(n5227), .B(n5226), .Z(n5223));
+ OR2 U4914 ( .A(n5228), .B(n5229), .Z(n5226));
+ AN2 U4915 ( .A(pi093), .B(n5230), .Z(n5229));
+ IV2 U4916 ( .A(n5231), .Z(n5228));
+ OR2 U4917 ( .A(n5230), .B(pi093), .Z(n5231));
+ IV2 U4918 ( .A(pi122), .Z(n5230));
+ AN2 U4919 ( .A(n5232), .B(n5233), .Z(n5227));
+ IV2 U4920 ( .A(n5234), .Z(n5233));
+ AN2 U4921 ( .A(pi134), .B(n5235), .Z(n5234));
+ OR2 U4922 ( .A(n5235), .B(pi134), .Z(n5232));
+ IV2 U4923 ( .A(pi198), .Z(n5235));
+ OR2 U4924 ( .A(n5236), .B(n5237), .Z(n5177));
+ AN2 U4925 ( .A(n5238), .B(n2837), .Z(n5237));
+ OR2 U4926 ( .A(n5239), .B(n5240), .Z(n5238));
+ AN2 U4927 ( .A(n5241), .B(n5242), .Z(n5240));
+ OR2 U4928 ( .A(n3809), .B(n5243), .Z(n5242));
+ IV2 U4929 ( .A(n3812), .Z(n3809));
+ OR2 U4930 ( .A(n5244), .B(n3812), .Z(n5241));
+ AN2 U4931 ( .A(n5245), .B(n5246), .Z(n3812));
+ IV2 U4932 ( .A(n5247), .Z(n5246));
+ AN2 U4933 ( .A(n5248), .B(n5249), .Z(n5247));
+ OR2 U4934 ( .A(n5249), .B(n5248), .Z(n5245));
+ OR2 U4935 ( .A(n5250), .B(n5251), .Z(n5248));
+ AN2 U4936 ( .A(pi040), .B(n5252), .Z(n5251));
+ IV2 U4937 ( .A(pi095), .Z(n5252));
+ AN2 U4938 ( .A(pi095), .B(n4735), .Z(n5250));
+ AN2 U4939 ( .A(n5253), .B(n5254), .Z(n5249));
+ OR2 U4940 ( .A(n4747), .B(pi156), .Z(n5254));
+ IV2 U4941 ( .A(pi151), .Z(n4747));
+ OR2 U4942 ( .A(n4648), .B(pi151), .Z(n5253));
+ AN2 U4943 ( .A(n5255), .B(n5256), .Z(n5239));
+ OR2 U4944 ( .A(n3815), .B(n5257), .Z(n5256));
+ OR2 U4945 ( .A(n5258), .B(n3818), .Z(n5255));
+ IV2 U4946 ( .A(n3815), .Z(n3818));
+ OR2 U4947 ( .A(n5259), .B(n5260), .Z(n3815));
+ AN2 U4948 ( .A(n5261), .B(n5262), .Z(n5260));
+ IV2 U4949 ( .A(n5263), .Z(n5259));
+ OR2 U4950 ( .A(n5262), .B(n5261), .Z(n5263));
+ OR2 U4951 ( .A(n5264), .B(n5265), .Z(n5261));
+ AN2 U4952 ( .A(pi128), .B(n3177), .Z(n5265));
+ AN2 U4953 ( .A(pi141), .B(n3205), .Z(n5264));
+ AN2 U4954 ( .A(n5266), .B(n5267), .Z(n5262));
+ OR2 U4955 ( .A(n5115), .B(pi185), .Z(n5267));
+ OR2 U4956 ( .A(n5268), .B(pi174), .Z(n5266));
+ IV2 U4957 ( .A(pi185), .Z(n5268));
+ AN2 U4958 ( .A(pi192), .B(n5269), .Z(n5236));
+ OR2 U4959 ( .A(n5270), .B(n5271), .Z(n5269));
+ OR2 U4960 ( .A(n5272), .B(n5273), .Z(n5271));
+ AN2 U4961 ( .A(n5274), .B(n5275), .Z(n5273));
+ IV2 U4962 ( .A(n5276), .Z(n5275));
+ AN2 U4963 ( .A(n5277), .B(n5278), .Z(n5276));
+ OR2 U4964 ( .A(n5278), .B(n5277), .Z(n5274));
+ AN2 U4965 ( .A(n5279), .B(n5280), .Z(n5277));
+ OR2 U4966 ( .A(n5243), .B(pi036), .Z(n5280));
+ IV2 U4967 ( .A(n5244), .Z(n5243));
+ OR2 U4968 ( .A(n5244), .B(n5281), .Z(n5279));
+ IV2 U4969 ( .A(pi036), .Z(n5281));
+ OR2 U4970 ( .A(n3871), .B(n5282), .Z(n5244));
+ AN2 U4971 ( .A(n5283), .B(pi192), .Z(n5282));
+ OR2 U4972 ( .A(n5284), .B(n5285), .Z(n5283));
+ AN2 U4973 ( .A(n5286), .B(n5287), .Z(n5285));
+ IV2 U4974 ( .A(n5288), .Z(n5284));
+ OR2 U4975 ( .A(n5287), .B(n5286), .Z(n5288));
+ OR2 U4976 ( .A(n5289), .B(n5290), .Z(n5286));
+ IV2 U4977 ( .A(n5291), .Z(n5290));
+ OR2 U4978 ( .A(n5292), .B(pi017), .Z(n5291));
+ AN2 U4979 ( .A(pi017), .B(n5292), .Z(n5289));
+ AN2 U4980 ( .A(n5293), .B(n5294), .Z(n5292));
+ OR2 U4981 ( .A(n5295), .B(pi083), .Z(n5294));
+ IV2 U4982 ( .A(pi027), .Z(n5295));
+ OR2 U4983 ( .A(n5296), .B(pi027), .Z(n5293));
+ IV2 U4984 ( .A(pi083), .Z(n5296));
+ AN2 U4985 ( .A(n5297), .B(n5298), .Z(n5287));
+ OR2 U4986 ( .A(n5299), .B(pi089), .Z(n5298));
+ IV2 U4987 ( .A(n5300), .Z(n5297));
+ AN2 U4988 ( .A(n5299), .B(pi089), .Z(n5300));
+ AN2 U4989 ( .A(n5301), .B(n5302), .Z(n5299));
+ OR2 U4990 ( .A(n5303), .B(pi162), .Z(n5302));
+ OR2 U4991 ( .A(n5304), .B(pi140), .Z(n5301));
+ IV2 U4992 ( .A(pi162), .Z(n5304));
+ AN2 U4993 ( .A(n5305), .B(n2837), .Z(n3871));
+ OR2 U4994 ( .A(n5306), .B(n5307), .Z(n5305));
+ AN2 U4995 ( .A(n5308), .B(n5309), .Z(n5307));
+ IV2 U4996 ( .A(n5310), .Z(n5306));
+ OR2 U4997 ( .A(n5309), .B(n5308), .Z(n5310));
+ OR2 U4998 ( .A(n5311), .B(n5312), .Z(n5308));
+ IV2 U4999 ( .A(n5313), .Z(n5312));
+ OR2 U5000 ( .A(n5314), .B(pi064), .Z(n5313));
+ AN2 U5001 ( .A(pi064), .B(n5314), .Z(n5311));
+ AN2 U5002 ( .A(n5315), .B(n5316), .Z(n5314));
+ OR2 U5003 ( .A(n4077), .B(pi108), .Z(n5316));
+ OR2 U5004 ( .A(n5317), .B(pi076), .Z(n5315));
+ IV2 U5005 ( .A(pi108), .Z(n5317));
+ AN2 U5006 ( .A(n5318), .B(n5319), .Z(n5309));
+ OR2 U5007 ( .A(n5320), .B(pi114), .Z(n5319));
+ IV2 U5008 ( .A(n5321), .Z(n5320));
+ OR2 U5009 ( .A(n5321), .B(n5322), .Z(n5318));
+ OR2 U5010 ( .A(n5323), .B(n5324), .Z(n5321));
+ AN2 U5011 ( .A(pi160), .B(n4074), .Z(n5324));
+ AN2 U5012 ( .A(pi170), .B(n4358), .Z(n5323));
+ OR2 U5013 ( .A(n5325), .B(n5326), .Z(n5278));
+ IV2 U5014 ( .A(n5327), .Z(n5326));
+ OR2 U5015 ( .A(n5328), .B(pi101), .Z(n5327));
+ AN2 U5016 ( .A(n5328), .B(pi101), .Z(n5325));
+ AN2 U5017 ( .A(n5329), .B(n5330), .Z(n5328));
+ OR2 U5018 ( .A(n5331), .B(pi205), .Z(n5330));
+ OR2 U5019 ( .A(n5332), .B(pi168), .Z(n5329));
+ IV2 U5020 ( .A(pi205), .Z(n5332));
+ AN2 U5021 ( .A(n5333), .B(n5334), .Z(n5272));
+ AN2 U5022 ( .A(n5335), .B(n5200), .Z(n5334));
+ IV2 U5023 ( .A(pi109), .Z(n5200));
+ AN2 U5024 ( .A(n5191), .B(n5194), .Z(n5335));
+ IV2 U5025 ( .A(pi186), .Z(n5194));
+ IV2 U5026 ( .A(pi124), .Z(n5191));
+ AN2 U5027 ( .A(n5181), .B(n5208), .Z(n5333));
+ IV2 U5028 ( .A(pi055), .Z(n5208));
+ IV2 U5029 ( .A(n5207), .Z(n5181));
+ OR2 U5030 ( .A(n3977), .B(n5336), .Z(n5207));
+ AN2 U5031 ( .A(n5337), .B(pi192), .Z(n5336));
+ OR2 U5032 ( .A(n5338), .B(n5339), .Z(n5337));
+ AN2 U5033 ( .A(n5340), .B(n5341), .Z(n5339));
+ IV2 U5034 ( .A(n5342), .Z(n5338));
+ OR2 U5035 ( .A(n5341), .B(n5340), .Z(n5342));
+ OR2 U5036 ( .A(n5343), .B(n5344), .Z(n5340));
+ IV2 U5037 ( .A(n5345), .Z(n5344));
+ OR2 U5038 ( .A(n5346), .B(n5347), .Z(n5345));
+ AN2 U5039 ( .A(n5346), .B(n5347), .Z(n5343));
+ AN2 U5040 ( .A(n5348), .B(n5349), .Z(n5346));
+ OR2 U5041 ( .A(n5350), .B(pi099), .Z(n5349));
+ OR2 U5042 ( .A(n5351), .B(pi018), .Z(n5348));
+ IV2 U5043 ( .A(pi099), .Z(n5351));
+ AN2 U5044 ( .A(n5352), .B(n5353), .Z(n5341));
+ OR2 U5045 ( .A(n5354), .B(pi150), .Z(n5353));
+ IV2 U5046 ( .A(n5355), .Z(n5352));
+ AN2 U5047 ( .A(pi150), .B(n5354), .Z(n5355));
+ AN2 U5048 ( .A(n5356), .B(n5357), .Z(n5354));
+ OR2 U5049 ( .A(n5358), .B(pi180), .Z(n5357));
+ OR2 U5050 ( .A(n5359), .B(pi172), .Z(n5356));
+ IV2 U5051 ( .A(pi180), .Z(n5359));
+ AN2 U5052 ( .A(n5360), .B(n2837), .Z(n3977));
+ AN2 U5053 ( .A(n5361), .B(n5362), .Z(n5360));
+ IV2 U5054 ( .A(n5363), .Z(n5362));
+ AN2 U5055 ( .A(n5364), .B(n5365), .Z(n5363));
+ OR2 U5056 ( .A(n5365), .B(n5364), .Z(n5361));
+ OR2 U5057 ( .A(n5366), .B(n5367), .Z(n5364));
+ AN2 U5058 ( .A(n5368), .B(n3261), .Z(n5367));
+ AN2 U5059 ( .A(n5369), .B(n3321), .Z(n5366));
+ IV2 U5060 ( .A(n5368), .Z(n5369));
+ OR2 U5061 ( .A(n5370), .B(n5371), .Z(n5368));
+ AN2 U5062 ( .A(pi003), .B(n5372), .Z(n5371));
+ AN2 U5063 ( .A(pi130), .B(n3597), .Z(n5370));
+ AN2 U5064 ( .A(n5373), .B(n5374), .Z(n5365));
+ OR2 U5065 ( .A(n5375), .B(pi142), .Z(n5374));
+ IV2 U5066 ( .A(n5376), .Z(n5375));
+ OR2 U5067 ( .A(n5376), .B(n4440), .Z(n5373));
+ OR2 U5068 ( .A(n5377), .B(n5378), .Z(n5376));
+ AN2 U5069 ( .A(pi177), .B(n5379), .Z(n5378));
+ AN2 U5070 ( .A(pi195), .B(n5380), .Z(n5377));
+ IV2 U5071 ( .A(pi177), .Z(n5380));
+ AN2 U5072 ( .A(n5381), .B(n5382), .Z(n5270));
+ IV2 U5073 ( .A(n5383), .Z(n5382));
+ AN2 U5074 ( .A(n5384), .B(n5385), .Z(n5383));
+ OR2 U5075 ( .A(n5385), .B(n5384), .Z(n5381));
+ AN2 U5076 ( .A(n5386), .B(n5387), .Z(n5384));
+ OR2 U5077 ( .A(n5257), .B(pi001), .Z(n5387));
+ IV2 U5078 ( .A(n5258), .Z(n5257));
+ OR2 U5079 ( .A(n5258), .B(n5388), .Z(n5386));
+ IV2 U5080 ( .A(pi001), .Z(n5388));
+ OR2 U5081 ( .A(n3831), .B(n5389), .Z(n5258));
+ AN2 U5082 ( .A(n5390), .B(pi192), .Z(n5389));
+ OR2 U5083 ( .A(n5391), .B(n5392), .Z(n5390));
+ AN2 U5084 ( .A(n5393), .B(n5394), .Z(n5392));
+ IV2 U5085 ( .A(n5395), .Z(n5391));
+ OR2 U5086 ( .A(n5394), .B(n5393), .Z(n5395));
+ OR2 U5087 ( .A(n5396), .B(n5397), .Z(n5393));
+ IV2 U5088 ( .A(n5398), .Z(n5397));
+ OR2 U5089 ( .A(n5399), .B(pi038), .Z(n5398));
+ AN2 U5090 ( .A(pi038), .B(n5399), .Z(n5396));
+ AN2 U5091 ( .A(n5400), .B(n5401), .Z(n5399));
+ OR2 U5092 ( .A(n5402), .B(pi103), .Z(n5401));
+ IV2 U5093 ( .A(pi053), .Z(n5402));
+ OR2 U5094 ( .A(n5403), .B(pi053), .Z(n5400));
+ IV2 U5095 ( .A(pi103), .Z(n5403));
+ AN2 U5096 ( .A(n5404), .B(n5405), .Z(n5394));
+ OR2 U5097 ( .A(n5406), .B(pi121), .Z(n5405));
+ IV2 U5098 ( .A(n5407), .Z(n5404));
+ AN2 U5099 ( .A(n5406), .B(pi121), .Z(n5407));
+ AN2 U5100 ( .A(n5408), .B(n5409), .Z(n5406));
+ OR2 U5101 ( .A(n5410), .B(pi184), .Z(n5409));
+ IV2 U5102 ( .A(pi149), .Z(n5410));
+ OR2 U5103 ( .A(n5411), .B(pi149), .Z(n5408));
+ IV2 U5104 ( .A(pi184), .Z(n5411));
+ AN2 U5105 ( .A(n5412), .B(n2837), .Z(n3831));
+ OR2 U5106 ( .A(n5413), .B(n5414), .Z(n5412));
+ IV2 U5107 ( .A(n5415), .Z(n5414));
+ OR2 U5108 ( .A(n5416), .B(n5417), .Z(n5415));
+ AN2 U5109 ( .A(n5417), .B(n5416), .Z(n5413));
+ AN2 U5110 ( .A(n5418), .B(n5419), .Z(n5416));
+ OR2 U5111 ( .A(n5420), .B(pi081), .Z(n5419));
+ IV2 U5112 ( .A(n5421), .Z(n5420));
+ OR2 U5113 ( .A(n5421), .B(n2982), .Z(n5418));
+ OR2 U5114 ( .A(n5422), .B(n5423), .Z(n5421));
+ AN2 U5115 ( .A(pi082), .B(n5424), .Z(n5423));
+ IV2 U5116 ( .A(pi092), .Z(n5424));
+ AN2 U5117 ( .A(pi092), .B(n2957), .Z(n5422));
+ OR2 U5118 ( .A(n5425), .B(n5426), .Z(n5417));
+ AN2 U5119 ( .A(n5427), .B(n5165), .Z(n5426));
+ AN2 U5120 ( .A(n5428), .B(pi107), .Z(n5425));
+ IV2 U5121 ( .A(n5427), .Z(n5428));
+ OR2 U5122 ( .A(n5429), .B(n5430), .Z(n5427));
+ AN2 U5123 ( .A(pi201), .B(n5431), .Z(n5430));
+ AN2 U5124 ( .A(pi206), .B(n3141), .Z(n5429));
+ OR2 U5125 ( .A(n5432), .B(n5433), .Z(n5385));
+ IV2 U5126 ( .A(n5434), .Z(n5433));
+ OR2 U5127 ( .A(n5435), .B(pi059), .Z(n5434));
+ AN2 U5128 ( .A(n5435), .B(pi059), .Z(n5432));
+ AN2 U5129 ( .A(n5436), .B(n5437), .Z(n5435));
+ OR2 U5130 ( .A(n5438), .B(pi197), .Z(n5437));
+ IV2 U5131 ( .A(pi131), .Z(n5438));
+ OR2 U5132 ( .A(n5439), .B(pi131), .Z(n5436));
+ OR2 U5133 ( .A(n5440), .B(n5441), .Z(po026));
+ AN2 U5134 ( .A(n3355), .B(n5442), .Z(n5441));
+ OR2 U5135 ( .A(n5443), .B(n5444), .Z(n5442));
+ OR2 U5136 ( .A(n5445), .B(n5446), .Z(n5444));
+ AN2 U5137 ( .A(po036), .B(n5447), .Z(n5446));
+ OR2 U5138 ( .A(n4418), .B(n5448), .Z(n5447));
+ AN2 U5139 ( .A(n5449), .B(n3236), .Z(n5445));
+ AN2 U5140 ( .A(n5450), .B(n5451), .Z(n5449));
+ OR2 U5141 ( .A(n5452), .B(n2837), .Z(n5451));
+ OR2 U5142 ( .A(pi192), .B(n5453), .Z(n5450));
+ AN2 U5143 ( .A(n4418), .B(n5448), .Z(n5443));
+ AN2 U5144 ( .A(n3352), .B(n5454), .Z(n5440));
+ IV2 U5145 ( .A(n5455), .Z(po022));
+ AN2 U5146 ( .A(n5456), .B(n5457), .Z(n5455));
+ AN2 U5147 ( .A(pi074), .B(pi046), .Z(n5457));
+ AN2 U5148 ( .A(pi178), .B(pi113), .Z(n5456));
+ OR2 U5149 ( .A(n5458), .B(n5459), .Z(po019));
+ AN2 U5150 ( .A(n4478), .B(n5460), .Z(n5459));
+ OR2 U5151 ( .A(n5461), .B(n4511), .Z(n5460));
+ OR2 U5152 ( .A(n5462), .B(n5463), .Z(n4511));
+ OR2 U5153 ( .A(n5464), .B(n5465), .Z(n5463));
+ AN2 U5154 ( .A(n5466), .B(pi192), .Z(n5465));
+ AN2 U5155 ( .A(n5467), .B(n2837), .Z(n5464));
+ AN2 U5156 ( .A(n4475), .B(n5468), .Z(n5458));
+ OR2 U5157 ( .A(n5469), .B(n5470), .Z(n5468));
+ OR2 U5158 ( .A(n5471), .B(n4509), .Z(n5470));
+ OR2 U5159 ( .A(n5472), .B(n5473), .Z(n4509));
+ OR2 U5160 ( .A(n5474), .B(n5475), .Z(n5473));
+ AN2 U5161 ( .A(n5476), .B(n4078), .Z(n5475));
+ AN2 U5162 ( .A(n5477), .B(n5322), .Z(n5476));
+ AN2 U5163 ( .A(n5478), .B(n4551), .Z(n5472));
+ IV2 U5164 ( .A(n4544), .Z(n4551));
+ OR2 U5165 ( .A(n4561), .B(n4066), .Z(n4544));
+ AN2 U5166 ( .A(pi192), .B(n3901), .Z(n5478));
+ AN2 U5167 ( .A(po102), .B(n4347), .Z(n5471));
+ OR2 U5168 ( .A(n5479), .B(n4524), .Z(n4347));
+ AN2 U5169 ( .A(n5480), .B(n4078), .Z(n4524));
+ IV2 U5170 ( .A(n4066), .Z(n4078));
+ AN2 U5171 ( .A(n4521), .B(n4072), .Z(n5479));
+ OR2 U5172 ( .A(n5481), .B(n5482), .Z(n4521));
+ AN2 U5173 ( .A(po059), .B(n5480), .Z(n5482));
+ OR2 U5174 ( .A(n5483), .B(po024), .Z(n5480));
+ AN2 U5175 ( .A(n5477), .B(n4074), .Z(n5481));
+ OR2 U5176 ( .A(n5484), .B(n5485), .Z(n5469));
+ AN2 U5177 ( .A(n4517), .B(n3780), .Z(n5485));
+ OR2 U5178 ( .A(n5486), .B(n5487), .Z(n4517));
+ AN2 U5179 ( .A(n4356), .B(n5488), .Z(n5487));
+ AN2 U5180 ( .A(n4076), .B(n5489), .Z(n4356));
+ AN2 U5181 ( .A(n4077), .B(n4578), .Z(n5489));
+ AN2 U5182 ( .A(n5490), .B(n4543), .Z(n5486));
+ AN2 U5183 ( .A(n4348), .B(n4353), .Z(n4543));
+ AN2 U5184 ( .A(n3890), .B(n5491), .Z(n5490));
+ AN2 U5185 ( .A(n4512), .B(n4072), .Z(n5484));
+ OR2 U5186 ( .A(n5492), .B(n3773), .Z(n4072));
+ AN2 U5187 ( .A(po025), .B(n3780), .Z(n5492));
+ IV2 U5188 ( .A(n4087), .Z(n3780));
+ OR2 U5189 ( .A(n5493), .B(n5494), .Z(n4512));
+ OR2 U5190 ( .A(n5495), .B(n5496), .Z(n5494));
+ AN2 U5191 ( .A(n5497), .B(pi192), .Z(n5496));
+ AN2 U5192 ( .A(n5498), .B(n4348), .Z(n5497));
+ OR2 U5193 ( .A(n5499), .B(n5500), .Z(n5498));
+ AN2 U5194 ( .A(po102), .B(n3880), .Z(n5500));
+ AN2 U5195 ( .A(n4353), .B(n3901), .Z(n5499));
+ AN2 U5196 ( .A(n5501), .B(n4076), .Z(n5495));
+ AN2 U5197 ( .A(n5488), .B(n4358), .Z(n5501));
+ AN2 U5198 ( .A(n5502), .B(n4076), .Z(n5493));
+ AN2 U5199 ( .A(n2837), .B(n5503), .Z(n4076));
+ AN2 U5200 ( .A(po024), .B(n5322), .Z(n5502));
+ OR2 U5201 ( .A(n5504), .B(n5505), .Z(po074));
+ AN2 U5202 ( .A(n5506), .B(n5507), .Z(n5505));
+ OR2 U5203 ( .A(n4167), .B(n5508), .Z(n5507));
+ OR2 U5204 ( .A(pi054), .B(n5509), .Z(n5508));
+ AN2 U5205 ( .A(pi025), .B(pi146), .Z(n5509));
+ OR2 U5206 ( .A(n5510), .B(n5511), .Z(n5506));
+ OR2 U5207 ( .A(n5512), .B(n5513), .Z(n5511));
+ AN2 U5208 ( .A(n3926), .B(n5514), .Z(n5513));
+ OR2 U5209 ( .A(n5515), .B(n5516), .Z(n5514));
+ OR2 U5210 ( .A(n5517), .B(n5518), .Z(n5516));
+ OR2 U5211 ( .A(pi056), .B(pi035), .Z(n5518));
+ OR2 U5212 ( .A(pi100), .B(n5519), .Z(n5515));
+ OR2 U5213 ( .A(pi190), .B(pi126), .Z(n5519));
+ AN2 U5214 ( .A(n5520), .B(n4319), .Z(n5512));
+ OR2 U5215 ( .A(n5521), .B(n5522), .Z(n5520));
+ AN2 U5216 ( .A(pi198), .B(n3945), .Z(n5522));
+ AN2 U5217 ( .A(n5523), .B(n5524), .Z(n5521));
+ AN2 U5218 ( .A(n5525), .B(n5517), .Z(n5524));
+ AN2 U5219 ( .A(n5056), .B(n4201), .Z(n5525));
+ AN2 U5220 ( .A(n4391), .B(pi192), .Z(n5523));
+ OR2 U5221 ( .A(n5526), .B(n5527), .Z(n5510));
+ AN2 U5222 ( .A(n5528), .B(n5529), .Z(n5527));
+ OR2 U5223 ( .A(pi198), .B(n4319), .Z(n5529));
+ OR2 U5224 ( .A(n5530), .B(n5531), .Z(n5528));
+ AN2 U5225 ( .A(n3945), .B(n5532), .Z(n5531));
+ OR2 U5226 ( .A(n5533), .B(n5534), .Z(n5532));
+ AN2 U5227 ( .A(pi061), .B(n4013), .Z(n5534));
+ AN2 U5228 ( .A(n5535), .B(pi134), .Z(n5533));
+ AN2 U5229 ( .A(n5536), .B(n4201), .Z(n5535));
+ AN2 U5230 ( .A(n5537), .B(n5538), .Z(n5530));
+ AN2 U5231 ( .A(n5536), .B(n3261), .Z(n5538));
+ OR2 U5232 ( .A(pi061), .B(n4013), .Z(n5536));
+ AN2 U5233 ( .A(n5539), .B(n5540), .Z(n5537));
+ OR2 U5234 ( .A(pi134), .B(n4201), .Z(n5540));
+ OR2 U5235 ( .A(n5541), .B(n5542), .Z(n5539));
+ AN2 U5236 ( .A(n5543), .B(n5517), .Z(n5542));
+ AN2 U5237 ( .A(pi192), .B(n5544), .Z(n5541));
+ OR2 U5238 ( .A(n5545), .B(n5546), .Z(n5544));
+ AN2 U5239 ( .A(pi006), .B(n3265), .Z(n5546));
+ AN2 U5240 ( .A(n5543), .B(n5056), .Z(n5545));
+ OR2 U5241 ( .A(pi006), .B(n3265), .Z(n5543));
+ AN2 U5242 ( .A(n5547), .B(n5548), .Z(n5526));
+ AN2 U5243 ( .A(n5549), .B(n5550), .Z(n5548));
+ AN2 U5244 ( .A(n5517), .B(n2837), .Z(n5550));
+ OR2 U5245 ( .A(n5551), .B(n5552), .Z(n5517));
+ OR2 U5246 ( .A(n5553), .B(n5554), .Z(n5552));
+ AN2 U5247 ( .A(n3945), .B(n5555), .Z(n5554));
+ OR2 U5248 ( .A(n5556), .B(n5557), .Z(n5555));
+ OR2 U5249 ( .A(n5558), .B(n5559), .Z(n5557));
+ AN2 U5250 ( .A(n5560), .B(n3380), .Z(n5559));
+ AN2 U5251 ( .A(n5561), .B(n5562), .Z(n5558));
+ OR2 U5252 ( .A(n5563), .B(n5564), .Z(n5561));
+ AN2 U5253 ( .A(pi055), .B(n3512), .Z(n5564));
+ AN2 U5254 ( .A(n5565), .B(pi124), .Z(n5563));
+ AN2 U5255 ( .A(n5566), .B(n3363), .Z(n5565));
+ AN2 U5256 ( .A(pi109), .B(n4975), .Z(n5556));
+ AN2 U5257 ( .A(n5567), .B(n5568), .Z(n5553));
+ OR2 U5258 ( .A(n5569), .B(n5570), .Z(n5568));
+ OR2 U5259 ( .A(n5571), .B(n5572), .Z(n5570));
+ AN2 U5260 ( .A(n5573), .B(n5566), .Z(n5572));
+ OR2 U5261 ( .A(pi055), .B(n3512), .Z(n5566));
+ AN2 U5262 ( .A(n5574), .B(n3261), .Z(n5573));
+ OR2 U5263 ( .A(n5575), .B(n5576), .Z(n5574));
+ AN2 U5264 ( .A(pi124), .B(n5562), .Z(n5576));
+ OR2 U5265 ( .A(n5577), .B(n5560), .Z(n5562));
+ AN2 U5266 ( .A(n5578), .B(n3380), .Z(n5577));
+ AN2 U5267 ( .A(n5579), .B(n3363), .Z(n5575));
+ OR2 U5268 ( .A(n5580), .B(n5560), .Z(n5579));
+ AN2 U5269 ( .A(n5578), .B(pi186), .Z(n5560));
+ OR2 U5270 ( .A(pi109), .B(n4975), .Z(n5578));
+ AN2 U5271 ( .A(pi109), .B(n3380), .Z(n5580));
+ AN2 U5272 ( .A(n5581), .B(n5582), .Z(n5571));
+ AN2 U5273 ( .A(n4975), .B(n3380), .Z(n5582));
+ AN2 U5274 ( .A(n5583), .B(n3363), .Z(n5581));
+ OR2 U5275 ( .A(n5584), .B(n5585), .Z(n5583));
+ AN2 U5276 ( .A(pi192), .B(n3512), .Z(n5585));
+ AN2 U5277 ( .A(pi055), .B(n3261), .Z(n5584));
+ OR2 U5278 ( .A(n3926), .B(n5586), .Z(n5569));
+ AN2 U5279 ( .A(n5587), .B(n5588), .Z(n5586));
+ AN2 U5280 ( .A(n5589), .B(pi110), .Z(n5588));
+ AN2 U5281 ( .A(pi167), .B(n2837), .Z(n5589));
+ AN2 U5282 ( .A(pi019), .B(pi085), .Z(n5587));
+ AN2 U5283 ( .A(n5590), .B(n5591), .Z(n5567));
+ OR2 U5284 ( .A(pi192), .B(n5592), .Z(n5591));
+ AN2 U5285 ( .A(n5593), .B(n5594), .Z(n5592));
+ OR2 U5286 ( .A(pi164), .B(n3261), .Z(n5594));
+ OR2 U5287 ( .A(n5595), .B(n5596), .Z(n5593));
+ OR2 U5288 ( .A(n5597), .B(n5598), .Z(n5596));
+ AN2 U5289 ( .A(n5599), .B(pi024), .Z(n5598));
+ AN2 U5290 ( .A(pi195), .B(n5600), .Z(n5597));
+ OR2 U5291 ( .A(n5601), .B(n5599), .Z(n5600));
+ AN2 U5292 ( .A(n5602), .B(n5603), .Z(n5599));
+ IV2 U5293 ( .A(n5604), .Z(n5603));
+ AN2 U5294 ( .A(n5605), .B(n5606), .Z(n5604));
+ OR2 U5295 ( .A(n5607), .B(n5608), .Z(n5606));
+ AN2 U5296 ( .A(n5609), .B(n5610), .Z(n5608));
+ OR2 U5297 ( .A(n5611), .B(n4961), .Z(n5610));
+ IV2 U5298 ( .A(pi030), .Z(n4961));
+ AN2 U5299 ( .A(n5612), .B(n3597), .Z(n5611));
+ OR2 U5300 ( .A(n5612), .B(n3597), .Z(n5609));
+ AN2 U5301 ( .A(n4969), .B(n4440), .Z(n5607));
+ OR2 U5302 ( .A(n4440), .B(n4969), .Z(n5605));
+ IV2 U5303 ( .A(pi159), .Z(n4969));
+ AN2 U5304 ( .A(pi024), .B(n5602), .Z(n5601));
+ OR2 U5305 ( .A(pi087), .B(pi130), .Z(n5602));
+ AN2 U5306 ( .A(pi087), .B(pi130), .Z(n5595));
+ OR2 U5307 ( .A(n2837), .B(n5613), .Z(n5590));
+ OR2 U5308 ( .A(n5614), .B(n5615), .Z(n5613));
+ AN2 U5309 ( .A(n5347), .B(n5616), .Z(n5615));
+ AN2 U5310 ( .A(n5617), .B(n4943), .Z(n5614));
+ OR2 U5311 ( .A(n5347), .B(n5616), .Z(n5617));
+ OR2 U5312 ( .A(n5618), .B(n5619), .Z(n5616));
+ OR2 U5313 ( .A(n5620), .B(n5621), .Z(n5619));
+ AN2 U5314 ( .A(n5622), .B(pi099), .Z(n5621));
+ AN2 U5315 ( .A(n5623), .B(n4937), .Z(n5620));
+ OR2 U5316 ( .A(n5624), .B(n5622), .Z(n5623));
+ AN2 U5317 ( .A(n5625), .B(n5626), .Z(n5622));
+ IV2 U5318 ( .A(n5627), .Z(n5626));
+ AN2 U5319 ( .A(n5628), .B(n5629), .Z(n5627));
+ OR2 U5320 ( .A(n5630), .B(n5631), .Z(n5629));
+ AN2 U5321 ( .A(n5632), .B(n5633), .Z(n5631));
+ OR2 U5322 ( .A(po011), .B(n5634), .Z(n5633));
+ AN2 U5323 ( .A(n5612), .B(n5358), .Z(n5634));
+ OR2 U5324 ( .A(n5612), .B(n5358), .Z(n5632));
+ IV2 U5325 ( .A(pi172), .Z(n5358));
+ IV2 U5326 ( .A(po062), .Z(n5612));
+ OR2 U5327 ( .A(n5635), .B(n5636), .Z(po062));
+ AN2 U5328 ( .A(n5637), .B(n2837), .Z(n5636));
+ OR2 U5329 ( .A(n5638), .B(n5639), .Z(n5637));
+ AN2 U5330 ( .A(pi020), .B(pi095), .Z(n5639));
+ AN2 U5331 ( .A(n5640), .B(n5641), .Z(n5638));
+ OR2 U5332 ( .A(pi020), .B(pi095), .Z(n5641));
+ OR2 U5333 ( .A(n5642), .B(n5643), .Z(n5640));
+ AN2 U5334 ( .A(pi151), .B(n5644), .Z(n5643));
+ AN2 U5335 ( .A(pi153), .B(n5645), .Z(n5642));
+ OR2 U5336 ( .A(pi151), .B(n5644), .Z(n5645));
+ OR2 U5337 ( .A(n5646), .B(n5647), .Z(n5644));
+ AN2 U5338 ( .A(pi075), .B(pi156), .Z(n5647));
+ AN2 U5339 ( .A(n5648), .B(n5649), .Z(n5646));
+ OR2 U5340 ( .A(pi075), .B(pi156), .Z(n5649));
+ OR2 U5341 ( .A(n5650), .B(n5651), .Z(n5648));
+ AN2 U5342 ( .A(pi040), .B(n5652), .Z(n5651));
+ AN2 U5343 ( .A(pi047), .B(n5653), .Z(n5650));
+ OR2 U5344 ( .A(pi040), .B(n5652), .Z(n5653));
+ AN2 U5345 ( .A(pi192), .B(n5654), .Z(n5635));
+ OR2 U5346 ( .A(n5655), .B(n5656), .Z(n5654));
+ OR2 U5347 ( .A(n5657), .B(n5658), .Z(n5656));
+ AN2 U5348 ( .A(pi101), .B(n5659), .Z(n5658));
+ AN2 U5349 ( .A(n5660), .B(n4628), .Z(n5657));
+ OR2 U5350 ( .A(n5661), .B(n5659), .Z(n5660));
+ OR2 U5351 ( .A(n5662), .B(n5663), .Z(n5659));
+ AN2 U5352 ( .A(n5664), .B(pi036), .Z(n5663));
+ AN2 U5353 ( .A(n5665), .B(n4861), .Z(n5662));
+ OR2 U5354 ( .A(n5666), .B(n5664), .Z(n5665));
+ AN2 U5355 ( .A(n5667), .B(n5668), .Z(n5664));
+ IV2 U5356 ( .A(n5669), .Z(n5668));
+ AN2 U5357 ( .A(n5670), .B(n5671), .Z(n5669));
+ OR2 U5358 ( .A(po039), .B(n5672), .Z(n5671));
+ AN2 U5359 ( .A(n5673), .B(n5331), .Z(n5672));
+ OR2 U5360 ( .A(n5673), .B(n5331), .Z(n5670));
+ IV2 U5361 ( .A(pi168), .Z(n5331));
+ IV2 U5362 ( .A(n5652), .Z(n5673));
+ OR2 U5363 ( .A(n5674), .B(n5675), .Z(n5652));
+ AN2 U5364 ( .A(n5676), .B(n2837), .Z(n5675));
+ OR2 U5365 ( .A(n5677), .B(n5678), .Z(n5676));
+ AN2 U5366 ( .A(pi143), .B(pi108), .Z(n5678));
+ AN2 U5367 ( .A(n5679), .B(n5680), .Z(n5677));
+ OR2 U5368 ( .A(pi108), .B(pi143), .Z(n5680));
+ OR2 U5369 ( .A(n5681), .B(n5682), .Z(n5679));
+ AN2 U5370 ( .A(pi014), .B(pi114), .Z(n5682));
+ AN2 U5371 ( .A(n5683), .B(n5684), .Z(n5681));
+ OR2 U5372 ( .A(pi014), .B(pi114), .Z(n5684));
+ OR2 U5373 ( .A(n5685), .B(n5686), .Z(n5683));
+ OR2 U5374 ( .A(n5687), .B(n5688), .Z(n5686));
+ AN2 U5375 ( .A(n5689), .B(pi170), .Z(n5688));
+ AN2 U5376 ( .A(pi176), .B(n5690), .Z(n5687));
+ OR2 U5377 ( .A(n5691), .B(n5689), .Z(n5690));
+ AN2 U5378 ( .A(n5692), .B(n5693), .Z(n5689));
+ IV2 U5379 ( .A(n5694), .Z(n5693));
+ AN2 U5380 ( .A(n5695), .B(n5696), .Z(n5694));
+ OR2 U5381 ( .A(n5697), .B(n4899), .Z(n5696));
+ IV2 U5382 ( .A(pi097), .Z(n4899));
+ AN2 U5383 ( .A(n5698), .B(n4077), .Z(n5697));
+ OR2 U5384 ( .A(n5698), .B(n4077), .Z(n5695));
+ AN2 U5385 ( .A(pi170), .B(n5692), .Z(n5691));
+ OR2 U5386 ( .A(pi160), .B(pi189), .Z(n5692));
+ AN2 U5387 ( .A(pi189), .B(pi160), .Z(n5685));
+ AN2 U5388 ( .A(pi192), .B(n5699), .Z(n5674));
+ OR2 U5389 ( .A(n5700), .B(n5701), .Z(n5699));
+ AN2 U5390 ( .A(pi089), .B(n4881), .Z(n5701));
+ AN2 U5391 ( .A(n5702), .B(n5703), .Z(n5700));
+ OR2 U5392 ( .A(pi089), .B(n4881), .Z(n5703));
+ OR2 U5393 ( .A(n5704), .B(n5705), .Z(n5702));
+ AN2 U5394 ( .A(pi027), .B(n4885), .Z(n5705));
+ AN2 U5395 ( .A(n5706), .B(n5707), .Z(n5704));
+ OR2 U5396 ( .A(pi027), .B(n4885), .Z(n5707));
+ OR2 U5397 ( .A(n5708), .B(n5709), .Z(n5706));
+ OR2 U5398 ( .A(n5710), .B(n5711), .Z(n5709));
+ AN2 U5399 ( .A(n5712), .B(pi083), .Z(n5711));
+ AN2 U5400 ( .A(n5713), .B(n4877), .Z(n5710));
+ OR2 U5401 ( .A(n5714), .B(n5712), .Z(n5713));
+ AN2 U5402 ( .A(n5715), .B(n5716), .Z(n5712));
+ IV2 U5403 ( .A(n5717), .Z(n5716));
+ AN2 U5404 ( .A(n5718), .B(n5719), .Z(n5717));
+ OR2 U5405 ( .A(po025), .B(n5720), .Z(n5719));
+ AN2 U5406 ( .A(n5698), .B(n5303), .Z(n5720));
+ OR2 U5407 ( .A(n5698), .B(n5303), .Z(n5718));
+ IV2 U5408 ( .A(pi140), .Z(n5303));
+ IV2 U5409 ( .A(n5721), .Z(n5698));
+ OR2 U5410 ( .A(n5722), .B(n5723), .Z(n5721));
+ AN2 U5411 ( .A(n5724), .B(n2837), .Z(n5723));
+ OR2 U5412 ( .A(n5725), .B(n5726), .Z(n5724));
+ OR2 U5413 ( .A(n5727), .B(n5728), .Z(n5726));
+ AN2 U5414 ( .A(n5729), .B(pi094), .Z(n5728));
+ AN2 U5415 ( .A(pi128), .B(n5730), .Z(n5727));
+ OR2 U5416 ( .A(n5731), .B(n5729), .Z(n5730));
+ AN2 U5417 ( .A(n5732), .B(n5733), .Z(n5729));
+ IV2 U5418 ( .A(n5734), .Z(n5733));
+ AN2 U5419 ( .A(n5735), .B(n5736), .Z(n5734));
+ OR2 U5420 ( .A(n5737), .B(n5738), .Z(n5736));
+ AN2 U5421 ( .A(n5739), .B(n5740), .Z(n5738));
+ OR2 U5422 ( .A(n5741), .B(n5115), .Z(n5740));
+ AN2 U5423 ( .A(n5742), .B(n4778), .Z(n5741));
+ OR2 U5424 ( .A(n5742), .B(n4778), .Z(n5739));
+ IV2 U5425 ( .A(pi163), .Z(n4778));
+ AN2 U5426 ( .A(n3177), .B(n4770), .Z(n5737));
+ OR2 U5427 ( .A(n3177), .B(n4770), .Z(n5735));
+ IV2 U5428 ( .A(pi028), .Z(n4770));
+ AN2 U5429 ( .A(pi094), .B(n5732), .Z(n5731));
+ OR2 U5430 ( .A(pi173), .B(pi185), .Z(n5732));
+ AN2 U5431 ( .A(pi173), .B(pi185), .Z(n5725));
+ AN2 U5432 ( .A(pi192), .B(n5743), .Z(n5722));
+ OR2 U5433 ( .A(n5744), .B(n5745), .Z(n5743));
+ OR2 U5434 ( .A(n5746), .B(n5747), .Z(n5745));
+ AN2 U5435 ( .A(pi131), .B(n5748), .Z(n5747));
+ AN2 U5436 ( .A(n5749), .B(n5040), .Z(n5746));
+ OR2 U5437 ( .A(n5750), .B(n5748), .Z(n5749));
+ OR2 U5438 ( .A(n5751), .B(n5752), .Z(n5748));
+ AN2 U5439 ( .A(n5753), .B(pi059), .Z(n5752));
+ AN2 U5440 ( .A(n5754), .B(n3286), .Z(n5751));
+ OR2 U5441 ( .A(n5755), .B(n5753), .Z(n5754));
+ AN2 U5442 ( .A(n5756), .B(n5757), .Z(n5753));
+ IV2 U5443 ( .A(n5758), .Z(n5757));
+ AN2 U5444 ( .A(n5759), .B(n5760), .Z(n5758));
+ OR2 U5445 ( .A(po010), .B(n5761), .Z(n5760));
+ AN2 U5446 ( .A(n5742), .B(n5439), .Z(n5761));
+ OR2 U5447 ( .A(n5742), .B(n5439), .Z(n5759));
+ IV2 U5448 ( .A(pi197), .Z(n5439));
+ IV2 U5449 ( .A(n5762), .Z(n5742));
+ OR2 U5450 ( .A(n5763), .B(n5764), .Z(n5762));
+ AN2 U5451 ( .A(n5765), .B(n2837), .Z(n5764));
+ OR2 U5452 ( .A(n5766), .B(n5767), .Z(n5765));
+ AN2 U5453 ( .A(pi021), .B(pi201), .Z(n5767));
+ AN2 U5454 ( .A(n5768), .B(n5769), .Z(n5766));
+ OR2 U5455 ( .A(pi021), .B(pi201), .Z(n5769));
+ OR2 U5456 ( .A(n5770), .B(n5771), .Z(n5768));
+ IV2 U5457 ( .A(n5772), .Z(n5771));
+ AN2 U5458 ( .A(n5773), .B(n5774), .Z(n5772));
+ OR2 U5459 ( .A(n5775), .B(n5022), .Z(n5774));
+ OR2 U5460 ( .A(n5431), .B(n5776), .Z(n5773));
+ AN2 U5461 ( .A(n5777), .B(n5775), .Z(n5776));
+ OR2 U5462 ( .A(n5778), .B(n5779), .Z(n5775));
+ AN2 U5463 ( .A(n5780), .B(n5781), .Z(n5779));
+ OR2 U5464 ( .A(n5782), .B(n5783), .Z(n5781));
+ AN2 U5465 ( .A(n5784), .B(n5785), .Z(n5783));
+ OR2 U5466 ( .A(n5786), .B(n5787), .Z(n5785));
+ IV2 U5467 ( .A(pi181), .Z(n5787));
+ AN2 U5468 ( .A(n2982), .B(n5019), .Z(n5786));
+ OR2 U5469 ( .A(n2982), .B(n5019), .Z(n5784));
+ IV2 U5470 ( .A(pi011), .Z(n5019));
+ AN2 U5471 ( .A(n5027), .B(n2957), .Z(n5782));
+ OR2 U5472 ( .A(n2957), .B(n5027), .Z(n5780));
+ IV2 U5473 ( .A(pi086), .Z(n5027));
+ OR2 U5474 ( .A(n5022), .B(n5778), .Z(n5777));
+ AN2 U5475 ( .A(n5165), .B(n5031), .Z(n5778));
+ IV2 U5476 ( .A(pi165), .Z(n5031));
+ IV2 U5477 ( .A(pi032), .Z(n5022));
+ AN2 U5478 ( .A(pi165), .B(pi107), .Z(n5770));
+ AN2 U5479 ( .A(pi192), .B(n5788), .Z(n5763));
+ OR2 U5480 ( .A(n5789), .B(n5790), .Z(n5788));
+ AN2 U5481 ( .A(pi121), .B(n5000), .Z(n5790));
+ AN2 U5482 ( .A(n5791), .B(n5792), .Z(n5789));
+ OR2 U5483 ( .A(pi121), .B(n5000), .Z(n5792));
+ OR2 U5484 ( .A(n5793), .B(n5794), .Z(n5791));
+ AN2 U5485 ( .A(pi053), .B(n5795), .Z(n5794));
+ AN2 U5486 ( .A(n5796), .B(n5004), .Z(n5793));
+ OR2 U5487 ( .A(pi053), .B(n5795), .Z(n5796));
+ OR2 U5488 ( .A(n5797), .B(n5798), .Z(n5795));
+ AN2 U5489 ( .A(pi184), .B(n5008), .Z(n5798));
+ AN2 U5490 ( .A(n5799), .B(n5800), .Z(n5797));
+ OR2 U5491 ( .A(pi184), .B(n5008), .Z(n5800));
+ OR2 U5492 ( .A(n5801), .B(n5802), .Z(n5799));
+ AN2 U5493 ( .A(pi181), .B(pi103), .Z(n5802));
+ AN2 U5494 ( .A(n5803), .B(n2962), .Z(n5801));
+ OR2 U5495 ( .A(pi103), .B(pi181), .Z(n5803));
+ AN2 U5496 ( .A(pi059), .B(n5756), .Z(n5755));
+ AN2 U5497 ( .A(pi131), .B(n5756), .Z(n5750));
+ OR2 U5498 ( .A(pi001), .B(n5037), .Z(n5756));
+ AN2 U5499 ( .A(pi001), .B(n5037), .Z(n5744));
+ AN2 U5500 ( .A(pi083), .B(n5715), .Z(n5714));
+ OR2 U5501 ( .A(pi162), .B(n4874), .Z(n5715));
+ AN2 U5502 ( .A(pi162), .B(n4874), .Z(n5708));
+ AN2 U5503 ( .A(pi036), .B(n5667), .Z(n5666));
+ AN2 U5504 ( .A(pi101), .B(n5667), .Z(n5661));
+ OR2 U5505 ( .A(pi205), .B(n4915), .Z(n5667));
+ AN2 U5506 ( .A(pi205), .B(n4915), .Z(n5655));
+ AN2 U5507 ( .A(po036), .B(n5350), .Z(n5630));
+ OR2 U5508 ( .A(po036), .B(n5350), .Z(n5628));
+ IV2 U5509 ( .A(pi018), .Z(n5350));
+ AN2 U5510 ( .A(pi099), .B(n5625), .Z(n5624));
+ OR2 U5511 ( .A(pi180), .B(n4947), .Z(n5625));
+ AN2 U5512 ( .A(pi180), .B(n4947), .Z(n5618));
+ AN2 U5513 ( .A(n3261), .B(pi049), .Z(n5347));
+ AN2 U5514 ( .A(n3926), .B(n5804), .Z(n5551));
+ OR2 U5515 ( .A(n5805), .B(n5806), .Z(n5804));
+ OR2 U5516 ( .A(pi085), .B(pi019), .Z(n5806));
+ OR2 U5517 ( .A(pi110), .B(n5807), .Z(n5805));
+ OR2 U5518 ( .A(pi167), .B(pi164), .Z(n5807));
+ AN2 U5519 ( .A(pi126), .B(pi190), .Z(n5549));
+ AN2 U5520 ( .A(n5808), .B(pi035), .Z(n5547));
+ AN2 U5521 ( .A(pi056), .B(pi100), .Z(n5808));
+ AN2 U5522 ( .A(pi054), .B(n5809), .Z(n5504));
+ OR2 U5523 ( .A(n4167), .B(n5810), .Z(n5809));
+ OR2 U5524 ( .A(pi146), .B(pi025), .Z(n5810));
+ AN2 U5525 ( .A(n5811), .B(n2882), .Z(po017));
+ OR2 U5526 ( .A(pi200), .B(n3003), .Z(n5811));
+ OR2 U5527 ( .A(n5812), .B(n5813), .Z(po016));
+ OR2 U5528 ( .A(n5814), .B(n5815), .Z(n5813));
+ AN2 U5529 ( .A(n3280), .B(n3064), .Z(n5815));
+ AN2 U5530 ( .A(n5100), .B(n5816), .Z(n5814));
+ OR2 U5531 ( .A(n5817), .B(n5818), .Z(n5816));
+ AN2 U5532 ( .A(n3055), .B(n5819), .Z(n5818));
+ OR2 U5533 ( .A(n2845), .B(n3143), .Z(n5819));
+ OR2 U5534 ( .A(n2978), .B(n3147), .Z(n3143));
+ AN2 U5535 ( .A(n3127), .B(n5820), .Z(n5817));
+ OR2 U5536 ( .A(n2833), .B(n3138), .Z(n5820));
+ OR2 U5537 ( .A(n2880), .B(n3147), .Z(n3138));
+ OR2 U5538 ( .A(n2998), .B(n5821), .Z(n3147));
+ OR2 U5539 ( .A(n2882), .B(n2862), .Z(n5821));
+ OR2 U5540 ( .A(n2925), .B(n2901), .Z(n2882));
+ AN2 U5541 ( .A(pi192), .B(n3036), .Z(n3127));
+ IV2 U5542 ( .A(n5822), .Z(n5100));
+ OR2 U5543 ( .A(n5823), .B(n5824), .Z(n5812));
+ AN2 U5544 ( .A(n5825), .B(pi192), .Z(n5824));
+ AN2 U5545 ( .A(n5826), .B(po010), .Z(n5825));
+ AN2 U5546 ( .A(n5827), .B(n2837), .Z(n5823));
+ AN2 U5547 ( .A(n5828), .B(n5829), .Z(n5827));
+ OR2 U5548 ( .A(n5830), .B(n5831), .Z(po008));
+ AN2 U5549 ( .A(n3344), .B(n3251), .Z(n5831));
+ OR2 U5550 ( .A(n5832), .B(n5833), .Z(n3251));
+ AN2 U5551 ( .A(n3355), .B(n5454), .Z(n5832));
+ OR2 U5552 ( .A(n5834), .B(n5835), .Z(n5454));
+ AN2 U5553 ( .A(n5836), .B(n4426), .Z(n5834));
+ IV2 U5554 ( .A(n3352), .Z(n3355));
+ AN2 U5555 ( .A(n3250), .B(n5837), .Z(n5830));
+ OR2 U5556 ( .A(n5838), .B(n5839), .Z(n5837));
+ OR2 U5557 ( .A(n5840), .B(n3245), .Z(n5839));
+ OR2 U5558 ( .A(n5841), .B(n5842), .Z(n3245));
+ AN2 U5559 ( .A(n3244), .B(n3699), .Z(n5842));
+ AN2 U5560 ( .A(n3242), .B(n3700), .Z(n5841));
+ IV2 U5561 ( .A(n5843), .Z(n3242));
+ AN2 U5562 ( .A(n3352), .B(n3701), .Z(n5840));
+ OR2 U5563 ( .A(n5844), .B(n5845), .Z(n5838));
+ AN2 U5564 ( .A(n4418), .B(n3762), .Z(n5845));
+ AN2 U5565 ( .A(n5846), .B(n3236), .Z(n5844));
+ OR2 U5566 ( .A(pi037), .B(n5847), .Z(po007));
+ IV2 U5567 ( .A(pi116), .Z(n5847));
+ OR2 U5568 ( .A(n5848), .B(n5849), .Z(po006));
+ AN2 U5569 ( .A(n3370), .B(n5850), .Z(n5849));
+ OR2 U5570 ( .A(n5851), .B(n5852), .Z(n5850));
+ OR2 U5571 ( .A(n5853), .B(n5138), .Z(n5852));
+ OR2 U5572 ( .A(n5854), .B(n3566), .Z(n5138));
+ AN2 U5573 ( .A(n3512), .B(n3926), .Z(n3566));
+ AN2 U5574 ( .A(n3926), .B(n4368), .Z(n5854));
+ OR2 U5575 ( .A(n5855), .B(n5856), .Z(n5851));
+ AN2 U5576 ( .A(n5139), .B(n3380), .Z(n5856));
+ OR2 U5577 ( .A(n5857), .B(n5858), .Z(n5139));
+ AN2 U5578 ( .A(n5859), .B(n3261), .Z(n5857));
+ AN2 U5579 ( .A(n5860), .B(pi118), .Z(n5855));
+ AN2 U5580 ( .A(n5861), .B(n3261), .Z(n5860));
+ OR2 U5581 ( .A(n5858), .B(n5859), .Z(n5861));
+ OR2 U5582 ( .A(n5862), .B(n5863), .Z(n5859));
+ OR2 U5583 ( .A(n3404), .B(n5864), .Z(n5863));
+ AN2 U5584 ( .A(n5865), .B(pi060), .Z(n5864));
+ AN2 U5585 ( .A(n4368), .B(n5866), .Z(n5865));
+ IV2 U5586 ( .A(n3446), .Z(n3404));
+ AN2 U5587 ( .A(n4367), .B(pi196), .Z(n5862));
+ IV2 U5588 ( .A(n4364), .Z(n4367));
+ IV2 U5589 ( .A(n5867), .Z(n5858));
+ IV2 U5590 ( .A(n3393), .Z(n3370));
+ AN2 U5591 ( .A(n3393), .B(n5868), .Z(n5848));
+ OR2 U5592 ( .A(n5869), .B(n5870), .Z(n5868));
+ OR2 U5593 ( .A(n5135), .B(n5871), .Z(n5870));
+ AN2 U5594 ( .A(n3480), .B(n5872), .Z(n5871));
+ AN2 U5595 ( .A(n5867), .B(n3321), .Z(n5135));
+ OR2 U5596 ( .A(po104), .B(n4364), .Z(n5867));
+ OR2 U5597 ( .A(n5873), .B(n5874), .Z(n5869));
+ OR2 U5598 ( .A(n5875), .B(n5876), .Z(n5874));
+ AN2 U5599 ( .A(n5877), .B(po071), .Z(n5876));
+ OR2 U5600 ( .A(n5136), .B(n5878), .Z(n5877));
+ OR2 U5601 ( .A(n5879), .B(n5880), .Z(n5136));
+ OR2 U5602 ( .A(n5881), .B(n5882), .Z(n5880));
+ AN2 U5603 ( .A(n3398), .B(n4364), .Z(n5882));
+ AN2 U5604 ( .A(n4363), .B(n3419), .Z(n5879));
+ AN2 U5605 ( .A(n5883), .B(n3398), .Z(n5875));
+ AN2 U5606 ( .A(n3446), .B(n3533), .Z(n3398));
+ AN2 U5607 ( .A(n4364), .B(n3913), .Z(n5883));
+ OR2 U5608 ( .A(n4062), .B(po027), .Z(n4364));
+ IV2 U5609 ( .A(n4061), .Z(n4062));
+ AN2 U5610 ( .A(n3416), .B(n4363), .Z(n5873));
+ IV2 U5611 ( .A(n4368), .Z(n4363));
+ OR2 U5612 ( .A(n3363), .B(n4061), .Z(n4368));
+ OR2 U5613 ( .A(n5884), .B(n5885), .Z(n4061));
+ OR2 U5614 ( .A(n5886), .B(n5887), .Z(n5885));
+ AN2 U5615 ( .A(n5888), .B(n4943), .Z(n5887));
+ AN2 U5616 ( .A(n5889), .B(n3989), .Z(n5886));
+ OR2 U5617 ( .A(n5890), .B(n5891), .Z(n5884));
+ OR2 U5618 ( .A(n5892), .B(n3490), .Z(n5891));
+ AN2 U5619 ( .A(n5893), .B(n5894), .Z(n5890));
+ AN2 U5620 ( .A(n3495), .B(n5895), .Z(n5893));
+ AN2 U5621 ( .A(n3446), .B(n3480), .Z(n3416));
+ OR2 U5622 ( .A(po104), .B(n3942), .Z(n3446));
+ OR2 U5623 ( .A(n5896), .B(n3253), .Z(po012));
+ AN2 U5624 ( .A(n5897), .B(pi054), .Z(n3253));
+ OR2 U5625 ( .A(n4133), .B(n5898), .Z(n5897));
+ AN2 U5626 ( .A(n4127), .B(n3255), .Z(n5896));
+ OR2 U5627 ( .A(pi054), .B(n5120), .Z(n3255));
+ OR2 U5628 ( .A(n5899), .B(n4167), .Z(n5120));
+ AN2 U5629 ( .A(n4133), .B(n4128), .Z(n5899));
+ IV2 U5630 ( .A(po064), .Z(n4133));
+ OR2 U5631 ( .A(n5900), .B(n4372), .Z(n4127));
+ OR2 U5632 ( .A(n5901), .B(n5902), .Z(n4372));
+ AN2 U5633 ( .A(n4380), .B(n4319), .Z(n5901));
+ AN2 U5634 ( .A(n5903), .B(n4374), .Z(n5900));
+ OR2 U5635 ( .A(n5904), .B(n5905), .Z(n4374));
+ AN2 U5636 ( .A(n5906), .B(n3261), .Z(n5905));
+ OR2 U5637 ( .A(n5907), .B(n5908), .Z(n5906));
+ OR2 U5638 ( .A(n5909), .B(n5910), .Z(n5908));
+ AN2 U5639 ( .A(n5911), .B(po103), .Z(n5910));
+ AN2 U5640 ( .A(n5912), .B(pi058), .Z(n5911));
+ AN2 U5641 ( .A(n5913), .B(n5914), .Z(n5912));
+ AN2 U5642 ( .A(n5915), .B(n5916), .Z(n5913));
+ OR2 U5643 ( .A(pi204), .B(n5917), .Z(n5916));
+ AN2 U5644 ( .A(n4057), .B(n4013), .Z(n5917));
+ OR2 U5645 ( .A(n5918), .B(n5919), .Z(n5915));
+ AN2 U5646 ( .A(po040), .B(n3966), .Z(n5918));
+ AN2 U5647 ( .A(n5920), .B(n3265), .Z(n5909));
+ AN2 U5648 ( .A(n5921), .B(n5922), .Z(n5920));
+ AN2 U5649 ( .A(n4057), .B(n4316), .Z(n5922));
+ AN2 U5650 ( .A(n4157), .B(n5914), .Z(n5921));
+ OR2 U5651 ( .A(n5923), .B(n4319), .Z(n5914));
+ AN2 U5652 ( .A(pi065), .B(pi192), .Z(n5923));
+ OR2 U5653 ( .A(pi204), .B(n4013), .Z(n4157));
+ AN2 U5654 ( .A(n5924), .B(n4046), .Z(n5907));
+ AN2 U5655 ( .A(po040), .B(n3263), .Z(n5924));
+ OR2 U5656 ( .A(n5925), .B(n2837), .Z(n3263));
+ AN2 U5657 ( .A(n3264), .B(pi058), .Z(n5925));
+ AN2 U5658 ( .A(n4391), .B(n4319), .Z(n5904));
+ AN2 U5659 ( .A(n3265), .B(n4013), .Z(n4391));
+ IV2 U5660 ( .A(n4158), .Z(n5903));
+ OR2 U5661 ( .A(n4312), .B(n5926), .Z(n4158));
+ OR2 U5662 ( .A(n4040), .B(n4229), .Z(n5926));
+ IV2 U5663 ( .A(n4184), .Z(n4229));
+ OR2 U5664 ( .A(n5927), .B(n5928), .Z(n4184));
+ OR2 U5665 ( .A(n5929), .B(n5930), .Z(n5928));
+ AN2 U5666 ( .A(n5931), .B(n5932), .Z(n5929));
+ OR2 U5667 ( .A(n5933), .B(n5934), .Z(n5932));
+ AN2 U5668 ( .A(n3457), .B(n3493), .Z(n5934));
+ IV2 U5669 ( .A(n3661), .Z(n3493));
+ OR2 U5670 ( .A(n5935), .B(n5936), .Z(n3661));
+ OR2 U5671 ( .A(n3229), .B(n3235), .Z(n5936));
+ OR2 U5672 ( .A(n5937), .B(n5938), .Z(n3235));
+ OR2 U5673 ( .A(n5939), .B(n5940), .Z(n5938));
+ AN2 U5674 ( .A(n5452), .B(n3241), .Z(n5940));
+ AN2 U5675 ( .A(n5453), .B(n3243), .Z(n5939));
+ AN2 U5676 ( .A(po082), .B(n5846), .Z(n5937));
+ OR2 U5677 ( .A(n5941), .B(n5942), .Z(n5846));
+ AN2 U5678 ( .A(n5452), .B(n3700), .Z(n5942));
+ AN2 U5679 ( .A(n3638), .B(n3635), .Z(n5452));
+ IV2 U5680 ( .A(pi098), .Z(n3638));
+ AN2 U5681 ( .A(n5453), .B(n3699), .Z(n5941));
+ AN2 U5682 ( .A(n3597), .B(n3593), .Z(n5453));
+ OR2 U5683 ( .A(n5943), .B(n5944), .Z(n3229));
+ AN2 U5684 ( .A(po082), .B(n3344), .Z(n5944));
+ AN2 U5685 ( .A(n3352), .B(n5945), .Z(n5943));
+ OR2 U5686 ( .A(n5946), .B(n5947), .Z(n5945));
+ OR2 U5687 ( .A(n3241), .B(n3243), .Z(n5947));
+ AN2 U5688 ( .A(po082), .B(n3701), .Z(n5946));
+ IV2 U5689 ( .A(n5833), .Z(n3701));
+ OR2 U5690 ( .A(n3233), .B(n5948), .Z(n5935));
+ AN2 U5691 ( .A(n3339), .B(n5949), .Z(n5948));
+ AN2 U5692 ( .A(n5949), .B(po011), .Z(n3233));
+ OR2 U5693 ( .A(n5950), .B(n5951), .Z(n5949));
+ OR2 U5694 ( .A(n5952), .B(n5953), .Z(n5951));
+ AN2 U5695 ( .A(n3241), .B(n3635), .Z(n5953));
+ AN2 U5696 ( .A(n3992), .B(n3700), .Z(n3241));
+ AN2 U5697 ( .A(n3632), .B(pi192), .Z(n3700));
+ IV2 U5698 ( .A(pi004), .Z(n3992));
+ AN2 U5699 ( .A(n3243), .B(n3593), .Z(n5952));
+ OR2 U5700 ( .A(po036), .B(n4440), .Z(n3593));
+ AN2 U5701 ( .A(n5372), .B(n3699), .Z(n3243));
+ AN2 U5702 ( .A(po082), .B(n3762), .Z(n5950));
+ OR2 U5703 ( .A(n5954), .B(n5955), .Z(n3762));
+ OR2 U5704 ( .A(n5956), .B(n5957), .Z(n5955));
+ AN2 U5705 ( .A(po036), .B(n5958), .Z(n5957));
+ OR2 U5706 ( .A(n5959), .B(po001), .Z(n5958));
+ AN2 U5707 ( .A(pi192), .B(n5960), .Z(n5956));
+ OR2 U5708 ( .A(n5961), .B(n5962), .Z(n5960));
+ AN2 U5709 ( .A(po001), .B(n4001), .Z(n5962));
+ AN2 U5710 ( .A(n3635), .B(n3998), .Z(n5961));
+ OR2 U5711 ( .A(po036), .B(n4001), .Z(n3635));
+ IV2 U5712 ( .A(pi171), .Z(n4001));
+ AN2 U5713 ( .A(n3699), .B(n4440), .Z(n5954));
+ AN2 U5714 ( .A(n2837), .B(n3590), .Z(n3699));
+ AN2 U5715 ( .A(n5963), .B(n3667), .Z(n5933));
+ AN2 U5716 ( .A(n3291), .B(n3341), .Z(n3667));
+ IV2 U5717 ( .A(n3339), .Z(n3341));
+ OR2 U5718 ( .A(n5964), .B(n5965), .Z(n3339));
+ AN2 U5719 ( .A(n5966), .B(n4441), .Z(n5965));
+ AN2 U5720 ( .A(n5448), .B(po036), .Z(n5964));
+ IV2 U5721 ( .A(n5966), .Z(n5448));
+ OR2 U5722 ( .A(n5967), .B(n5968), .Z(n3291));
+ AN2 U5723 ( .A(n5969), .B(n3688), .Z(n5968));
+ IV2 U5724 ( .A(n3746), .Z(n5969));
+ AN2 U5725 ( .A(po011), .B(n3746), .Z(n5967));
+ OR2 U5726 ( .A(n3717), .B(n3705), .Z(n3746));
+ AN2 U5727 ( .A(n3495), .B(n5970), .Z(n5963));
+ OR2 U5728 ( .A(n5971), .B(n5972), .Z(n5970));
+ OR2 U5729 ( .A(n5973), .B(n5974), .Z(n5972));
+ AN2 U5730 ( .A(n5975), .B(pi192), .Z(n5974));
+ AN2 U5731 ( .A(n3567), .B(n5976), .Z(n5975));
+ OR2 U5732 ( .A(n5977), .B(n5978), .Z(n5976));
+ OR2 U5733 ( .A(n5979), .B(n5980), .Z(n5978));
+ AN2 U5734 ( .A(n4635), .B(n5981), .Z(n5979));
+ IV2 U5735 ( .A(n4464), .Z(n4635));
+ OR2 U5736 ( .A(po039), .B(n3870), .Z(n4464));
+ IV2 U5737 ( .A(pi016), .Z(n3870));
+ OR2 U5738 ( .A(n5982), .B(n5983), .Z(n5977));
+ AN2 U5739 ( .A(n5984), .B(n3033), .Z(n5983));
+ IV2 U5740 ( .A(n3038), .Z(n3033));
+ OR2 U5741 ( .A(po070), .B(n3199), .Z(n3038));
+ IV2 U5742 ( .A(pi096), .Z(n3199));
+ AN2 U5743 ( .A(n5985), .B(n5986), .Z(n5982));
+ OR2 U5744 ( .A(n5987), .B(n3042), .Z(n5986));
+ IV2 U5745 ( .A(n3037), .Z(n3042));
+ OR2 U5746 ( .A(po099), .B(n3171), .Z(n3037));
+ AN2 U5747 ( .A(n3063), .B(n5988), .Z(n5987));
+ OR2 U5748 ( .A(n5989), .B(n5990), .Z(n5988));
+ AN2 U5749 ( .A(n3036), .B(n5991), .Z(n5989));
+ OR2 U5750 ( .A(n5992), .B(n3010), .Z(n5991));
+ OR2 U5751 ( .A(n5993), .B(n5994), .Z(n3010));
+ AN2 U5752 ( .A(pi088), .B(n3012), .Z(n5992));
+ IV2 U5753 ( .A(n5995), .Z(n3036));
+ OR2 U5754 ( .A(n5996), .B(n5990), .Z(n5995));
+ AN2 U5755 ( .A(pi166), .B(n3049), .Z(n5990));
+ AN2 U5756 ( .A(po010), .B(n3106), .Z(n5996));
+ OR2 U5757 ( .A(n3534), .B(n3363), .Z(n3567));
+ AN2 U5758 ( .A(n5997), .B(n3457), .Z(n5973));
+ IV2 U5759 ( .A(n4060), .Z(n3457));
+ OR2 U5760 ( .A(n5998), .B(n5999), .Z(n4060));
+ AN2 U5761 ( .A(po027), .B(n3451), .Z(n5998));
+ AN2 U5762 ( .A(n3760), .B(n4652), .Z(n5997));
+ AN2 U5763 ( .A(n6000), .B(n6001), .Z(n5971));
+ OR2 U5764 ( .A(n3261), .B(n3525), .Z(n6001));
+ AN2 U5765 ( .A(n3363), .B(n3321), .Z(n3525));
+ OR2 U5766 ( .A(n6002), .B(n6003), .Z(n6000));
+ AN2 U5767 ( .A(n6004), .B(n2837), .Z(n6003));
+ OR2 U5768 ( .A(n6005), .B(n6006), .Z(n6004));
+ OR2 U5769 ( .A(n6007), .B(n6008), .Z(n6006));
+ AN2 U5770 ( .A(n4641), .B(n5981), .Z(n6007));
+ IV2 U5771 ( .A(n4468), .Z(n4641));
+ OR2 U5772 ( .A(po039), .B(n4735), .Z(n4468));
+ IV2 U5773 ( .A(pi040), .Z(n4735));
+ OR2 U5774 ( .A(n6009), .B(n6010), .Z(n6005));
+ AN2 U5775 ( .A(n5985), .B(n6011), .Z(n6010));
+ OR2 U5776 ( .A(n6012), .B(n6013), .Z(n6011));
+ OR2 U5777 ( .A(n3066), .B(n6014), .Z(n6013));
+ AN2 U5778 ( .A(n6015), .B(n6016), .Z(n6014));
+ IV2 U5779 ( .A(n3112), .Z(n3066));
+ OR2 U5780 ( .A(po099), .B(n3177), .Z(n3112));
+ AN2 U5781 ( .A(n6017), .B(n6018), .Z(n6012));
+ OR2 U5782 ( .A(n6019), .B(n6020), .Z(n6018));
+ AN2 U5783 ( .A(n6021), .B(n3119), .Z(n6019));
+ OR2 U5784 ( .A(n6022), .B(n5993), .Z(n6021));
+ AN2 U5785 ( .A(n2890), .B(n5000), .Z(n5993));
+ AN2 U5786 ( .A(pi201), .B(n3012), .Z(n6022));
+ OR2 U5787 ( .A(n2890), .B(n5000), .Z(n3012));
+ IV2 U5788 ( .A(n2886), .Z(n2890));
+ OR2 U5789 ( .A(n6023), .B(n6024), .Z(n2886));
+ OR2 U5790 ( .A(n6025), .B(n6026), .Z(n6024));
+ AN2 U5791 ( .A(n6027), .B(n2998), .Z(n6026));
+ AN2 U5792 ( .A(po079), .B(n6028), .Z(n6025));
+ OR2 U5793 ( .A(n6029), .B(n4095), .Z(n6028));
+ OR2 U5794 ( .A(n6030), .B(n6031), .Z(n4095));
+ AN2 U5795 ( .A(n4098), .B(n2887), .Z(n6031));
+ AN2 U5796 ( .A(n6032), .B(po031), .Z(n6030));
+ AN2 U5797 ( .A(n2990), .B(n2974), .Z(n6032));
+ AN2 U5798 ( .A(n2990), .B(n5169), .Z(n6029));
+ OR2 U5799 ( .A(n6033), .B(po106), .Z(n2990));
+ AN2 U5800 ( .A(n2837), .B(n5431), .Z(n6033));
+ OR2 U5801 ( .A(n6034), .B(n6035), .Z(n6023));
+ AN2 U5802 ( .A(n4099), .B(n6036), .Z(n6035));
+ OR2 U5803 ( .A(n6037), .B(n6038), .Z(n6036));
+ AN2 U5804 ( .A(n6039), .B(n5165), .Z(n6038));
+ OR2 U5805 ( .A(n6040), .B(n5169), .Z(n6039));
+ OR2 U5806 ( .A(n2978), .B(n2862), .Z(n5169));
+ AN2 U5807 ( .A(po031), .B(n2974), .Z(n6040));
+ AN2 U5808 ( .A(n6041), .B(n2974), .Z(n6037));
+ AN2 U5809 ( .A(n5172), .B(n2957), .Z(n6041));
+ AN2 U5810 ( .A(n2947), .B(n2837), .Z(n4099));
+ AN2 U5811 ( .A(n6042), .B(n4098), .Z(n6034));
+ AN2 U5812 ( .A(n2891), .B(pi192), .Z(n4098));
+ IV2 U5813 ( .A(n2892), .Z(n2891));
+ AN2 U5814 ( .A(n6043), .B(n3847), .Z(n6042));
+ IV2 U5815 ( .A(n2885), .Z(n6043));
+ AN2 U5816 ( .A(n5984), .B(n3076), .Z(n6009));
+ IV2 U5817 ( .A(n3109), .Z(n3076));
+ OR2 U5818 ( .A(po070), .B(n3205), .Z(n3109));
+ IV2 U5819 ( .A(pi128), .Z(n3205));
+ AN2 U5820 ( .A(n5985), .B(n6044), .Z(n6002));
+ OR2 U5821 ( .A(n6045), .B(n6046), .Z(n5927));
+ AN2 U5822 ( .A(n6047), .B(n3945), .Z(n6046));
+ IV2 U5823 ( .A(n4313), .Z(n3945));
+ OR2 U5824 ( .A(n3321), .B(n2837), .Z(n4313));
+ AN2 U5825 ( .A(pi050), .B(n4975), .Z(n6047));
+ AN2 U5826 ( .A(n6048), .B(n6049), .Z(n6045));
+ AN2 U5827 ( .A(n6050), .B(n6051), .Z(n6049));
+ OR2 U5828 ( .A(n3363), .B(n6052), .Z(n6051));
+ OR2 U5829 ( .A(po027), .B(n3989), .Z(n6050));
+ AN2 U5830 ( .A(n6053), .B(n4943), .Z(n6048));
+ OR2 U5831 ( .A(n4239), .B(n4192), .Z(n4312));
+ OR2 U5832 ( .A(n6054), .B(n6055), .Z(po003));
+ OR2 U5833 ( .A(n6056), .B(n6057), .Z(n6055));
+ AN2 U5834 ( .A(n6058), .B(pi054), .Z(n6057));
+ OR2 U5835 ( .A(n6059), .B(n6060), .Z(n6058));
+ AN2 U5836 ( .A(n4177), .B(n5126), .Z(n6060));
+ AN2 U5837 ( .A(n5125), .B(n5898), .Z(n6059));
+ AN2 U5838 ( .A(n6061), .B(n4129), .Z(n6056));
+ AN2 U5839 ( .A(n4177), .B(n5125), .Z(n6061));
+ OR2 U5840 ( .A(n6062), .B(n3257), .Z(n5125));
+ OR2 U5841 ( .A(n5902), .B(n6063), .Z(n3257));
+ OR2 U5842 ( .A(n6064), .B(n6065), .Z(n6063));
+ AN2 U5843 ( .A(n4403), .B(n4319), .Z(n6065));
+ IV2 U5844 ( .A(po004), .Z(n4319));
+ OR2 U5845 ( .A(n6066), .B(n4380), .Z(n4403));
+ AN2 U5846 ( .A(n6067), .B(n3259), .Z(n6066));
+ AN2 U5847 ( .A(n4053), .B(n4013), .Z(n6067));
+ OR2 U5848 ( .A(n6068), .B(n3265), .Z(n4053));
+ AN2 U5849 ( .A(pi058), .B(n3261), .Z(n6068));
+ AN2 U5850 ( .A(n6069), .B(n6070), .Z(n6064));
+ AN2 U5851 ( .A(n4387), .B(n4013), .Z(n6070));
+ IV2 U5852 ( .A(po040), .Z(n4013));
+ AN2 U5853 ( .A(pi065), .B(n3259), .Z(n6069));
+ OR2 U5854 ( .A(n6071), .B(n4379), .Z(n5902));
+ IV2 U5855 ( .A(n4159), .Z(n4379));
+ AN2 U5856 ( .A(n4380), .B(n4404), .Z(n6071));
+ IV2 U5857 ( .A(n4161), .Z(n4404));
+ IV2 U5858 ( .A(n4141), .Z(n4380));
+ OR2 U5859 ( .A(n4016), .B(n6072), .Z(n4141));
+ OR2 U5860 ( .A(n6073), .B(n6074), .Z(n6072));
+ AN2 U5861 ( .A(n6075), .B(n4242), .Z(n6074));
+ OR2 U5862 ( .A(n6076), .B(n6077), .Z(n4016));
+ AN2 U5863 ( .A(n4040), .B(n3951), .Z(n6076));
+ AN2 U5864 ( .A(n3259), .B(n6078), .Z(n6062));
+ OR2 U5865 ( .A(n6079), .B(n3926), .Z(n6078));
+ AN2 U5866 ( .A(n3264), .B(n4387), .Z(n6079));
+ AN2 U5867 ( .A(n3261), .B(n4026), .Z(n4387));
+ IV2 U5868 ( .A(n6080), .Z(n3264));
+ OR2 U5869 ( .A(n6081), .B(n5919), .Z(n6080));
+ AN2 U5870 ( .A(n4330), .B(n6082), .Z(n3259));
+ AN2 U5871 ( .A(n4205), .B(n3314), .Z(n6082));
+ IV2 U5872 ( .A(n5898), .Z(n4177));
+ AN2 U5873 ( .A(n4172), .B(n5126), .Z(n6054));
+ OR2 U5874 ( .A(n6083), .B(n6084), .Z(n5126));
+ OR2 U5875 ( .A(n6085), .B(n6086), .Z(n6084));
+ AN2 U5876 ( .A(n4227), .B(n4159), .Z(n6086));
+ OR2 U5877 ( .A(po004), .B(n4161), .Z(n4159));
+ OR2 U5878 ( .A(n4310), .B(n3321), .Z(n4161));
+ OR2 U5879 ( .A(n6087), .B(n6088), .Z(n4227));
+ OR2 U5880 ( .A(n6089), .B(n6077), .Z(n6088));
+ OR2 U5881 ( .A(n6090), .B(n6091), .Z(n6077));
+ OR2 U5882 ( .A(n3317), .B(n6092), .Z(n6091));
+ AN2 U5883 ( .A(n4291), .B(n4056), .Z(n6092));
+ AN2 U5884 ( .A(n3321), .B(po103), .Z(n3317));
+ AN2 U5885 ( .A(n4040), .B(n3321), .Z(n6090));
+ AN2 U5886 ( .A(n4192), .B(n6075), .Z(n6089));
+ OR2 U5887 ( .A(n3321), .B(n6093), .Z(n6075));
+ OR2 U5888 ( .A(n6073), .B(n6094), .Z(n6087));
+ AN2 U5889 ( .A(n4040), .B(n4291), .Z(n6094));
+ AN2 U5890 ( .A(po040), .B(n6095), .Z(n6073));
+ OR2 U5891 ( .A(n4040), .B(n6096), .Z(n6095));
+ OR2 U5892 ( .A(n3318), .B(n4293), .Z(n6096));
+ OR2 U5893 ( .A(n3951), .B(n3321), .Z(n4293));
+ AN2 U5894 ( .A(n4056), .B(n6097), .Z(n3318));
+ AN2 U5895 ( .A(n4057), .B(pi192), .Z(n6097));
+ IV2 U5896 ( .A(n4026), .Z(n4056));
+ OR2 U5897 ( .A(pi058), .B(n3265), .Z(n4026));
+ IV2 U5898 ( .A(n3314), .Z(n4040));
+ OR2 U5899 ( .A(n6098), .B(n4201), .Z(n3314));
+ IV2 U5900 ( .A(po091), .Z(n4201));
+ AN2 U5901 ( .A(n3261), .B(n4200), .Z(n6098));
+ AN2 U5902 ( .A(n6081), .B(pi192), .Z(n6085));
+ AN2 U5903 ( .A(n4150), .B(po004), .Z(n6081));
+ IV2 U5904 ( .A(pi065), .Z(n4150));
+ OR2 U5905 ( .A(n6099), .B(n4396), .Z(n6083));
+ AN2 U5906 ( .A(n4406), .B(n6100), .Z(n4396));
+ OR2 U5907 ( .A(n6101), .B(n3321), .Z(n6100));
+ AN2 U5908 ( .A(n6102), .B(n6103), .Z(n6101));
+ AN2 U5909 ( .A(n4223), .B(n4057), .Z(n6103));
+ AN2 U5910 ( .A(n4310), .B(n6104), .Z(n6102));
+ OR2 U5911 ( .A(po040), .B(n5919), .Z(n6104));
+ IV2 U5912 ( .A(pi204), .Z(n5919));
+ IV2 U5913 ( .A(n4156), .Z(n4310));
+ OR2 U5914 ( .A(pi065), .B(n2837), .Z(n4156));
+ AN2 U5915 ( .A(po004), .B(n6105), .Z(n6099));
+ OR2 U5916 ( .A(n6106), .B(n3321), .Z(n6105));
+ AN2 U5917 ( .A(n4406), .B(n6093), .Z(n6106));
+ OR2 U5918 ( .A(n6107), .B(n4028), .Z(n6093));
+ AN2 U5919 ( .A(n4223), .B(n4291), .Z(n4028));
+ AN2 U5920 ( .A(n4057), .B(n3951), .Z(n4291));
+ IV2 U5921 ( .A(n4041), .Z(n3951));
+ OR2 U5922 ( .A(pi204), .B(n2837), .Z(n4041));
+ OR2 U5923 ( .A(po103), .B(n4316), .Z(n4223));
+ IV2 U5924 ( .A(pi058), .Z(n4316));
+ AN2 U5925 ( .A(po040), .B(n3322), .Z(n6107));
+ OR2 U5926 ( .A(n4046), .B(n4045), .Z(n3322));
+ OR2 U5927 ( .A(n6108), .B(n6109), .Z(n4045));
+ AN2 U5928 ( .A(n4148), .B(n4057), .Z(n6109));
+ OR2 U5929 ( .A(po091), .B(n3966), .Z(n4057));
+ IV2 U5930 ( .A(pi129), .Z(n3966));
+ AN2 U5931 ( .A(n4203), .B(po103), .Z(n6108));
+ IV2 U5932 ( .A(n4200), .Z(n4203));
+ OR2 U5933 ( .A(pi129), .B(n2837), .Z(n4200));
+ AN2 U5934 ( .A(po103), .B(po091), .Z(n4046));
+ AN2 U5935 ( .A(n5898), .B(n4129), .Z(n4172));
+ IV2 U5936 ( .A(pi054), .Z(n4129));
+ OR2 U5937 ( .A(n4167), .B(n4128), .Z(n5898));
+ IV2 U5938 ( .A(po085), .Z(n4128));
+ IV2 U5939 ( .A(pi052), .Z(n4167));
+ AN2 U5940 ( .A(n6110), .B(n6111), .Z(po002));
+ OR2 U5941 ( .A(n3306), .B(n4450), .Z(n6111));
+ OR2 U5942 ( .A(n4458), .B(n4606), .Z(n6110));
+ IV2 U5943 ( .A(n3306), .Z(n4458));
+ OR2 U5944 ( .A(n6112), .B(n4652), .Z(n3306));
+ OR2 U5945 ( .A(n6113), .B(n6114), .Z(n4652));
+ AN2 U5946 ( .A(n6115), .B(n2837), .Z(n6114));
+ OR2 U5947 ( .A(n6116), .B(n6117), .Z(n6115));
+ AN2 U5948 ( .A(pi108), .B(n4881), .Z(n6117));
+ AN2 U5949 ( .A(n4475), .B(n6118), .Z(n6116));
+ OR2 U5950 ( .A(n5467), .B(n6119), .Z(n6118));
+ IV2 U5951 ( .A(n5488), .Z(n6119));
+ OR2 U5952 ( .A(po102), .B(n5322), .Z(n5488));
+ IV2 U5953 ( .A(pi114), .Z(n5322));
+ AN2 U5954 ( .A(n6120), .B(n6121), .Z(n5467));
+ OR2 U5955 ( .A(pi114), .B(n4885), .Z(n6120));
+ AN2 U5956 ( .A(pi192), .B(n6122), .Z(n6113));
+ OR2 U5957 ( .A(n6123), .B(n6124), .Z(n6122));
+ AN2 U5958 ( .A(pi148), .B(n4881), .Z(n6124));
+ AN2 U5959 ( .A(n4475), .B(n6125), .Z(n6123));
+ OR2 U5960 ( .A(n5466), .B(n6126), .Z(n6125));
+ IV2 U5961 ( .A(n5491), .Z(n6126));
+ OR2 U5962 ( .A(po102), .B(n3901), .Z(n5491));
+ IV2 U5963 ( .A(pi069), .Z(n3901));
+ AN2 U5964 ( .A(n6127), .B(n6128), .Z(n5466));
+ OR2 U5965 ( .A(pi069), .B(n4885), .Z(n6127));
+ AN2 U5966 ( .A(n5461), .B(n4475), .Z(n6112));
+ AN2 U5967 ( .A(n4087), .B(n6129), .Z(n5461));
+ AN2 U5968 ( .A(n6130), .B(n4341), .Z(n6129));
+ IV2 U5969 ( .A(n5474), .Z(n6130));
+ AN2 U5970 ( .A(n6131), .B(po102), .Z(n5474));
+ AN2 U5971 ( .A(n4334), .B(n4333), .Z(n4087));
+ OR2 U5972 ( .A(n6132), .B(n4656), .Z(n4334));
+ OR2 U5973 ( .A(n6133), .B(n6134), .Z(n4656));
+ AN2 U5974 ( .A(n5074), .B(n3083), .Z(n6133));
+ AN2 U5975 ( .A(n6135), .B(n3083), .Z(n6132));
+ AN2 U5976 ( .A(n3018), .B(n4326), .Z(n6135));
+ OR2 U5977 ( .A(n6136), .B(n5077), .Z(n4326));
+ OR2 U5978 ( .A(n6137), .B(n3100), .Z(n5077));
+ AN2 U5979 ( .A(n3280), .B(n4666), .Z(n6137));
+ OR2 U5980 ( .A(n3286), .B(n6138), .Z(n4666));
+ AN2 U5981 ( .A(n5829), .B(n3049), .Z(n3280));
+ AN2 U5982 ( .A(n6139), .B(n3284), .Z(n6136));
+ OR2 U5983 ( .A(n3049), .B(n5829), .Z(n3284));
+ OR2 U5984 ( .A(n6140), .B(n3287), .Z(n6139));
+ OR2 U5985 ( .A(n6141), .B(n6142), .Z(n3287));
+ AN2 U5986 ( .A(pi141), .B(n3173), .Z(n6141));
+ AN2 U5987 ( .A(n6143), .B(n3286), .Z(n6140));
+ OR2 U5988 ( .A(n3173), .B(n3064), .Z(n6143));
+ OR2 U5989 ( .A(n6144), .B(n6145), .Z(po000));
+ AN2 U5990 ( .A(n6146), .B(po103), .Z(n6145));
+ OR2 U5991 ( .A(n6147), .B(n6148), .Z(n6146));
+ AN2 U5992 ( .A(n6149), .B(n3326), .Z(n6148));
+ AN2 U5993 ( .A(n4217), .B(n3320), .Z(n6147));
+ AN2 U5994 ( .A(n6150), .B(n3265), .Z(n6144));
+ IV2 U5995 ( .A(po103), .Z(n3265));
+ OR2 U5996 ( .A(n6151), .B(n6152), .Z(n6150));
+ AN2 U5997 ( .A(n6149), .B(n3320), .Z(n6152));
+ OR2 U5998 ( .A(n4406), .B(n4192), .Z(n3320));
+ IV2 U5999 ( .A(n4205), .Z(n4192));
+ AN2 U6000 ( .A(n4242), .B(n4331), .Z(n4406));
+ IV2 U6001 ( .A(n4330), .Z(n4331));
+ AN2 U6002 ( .A(n4217), .B(n3326), .Z(n6151));
+ OR2 U6003 ( .A(n6153), .B(n4239), .Z(n3326));
+ IV2 U6004 ( .A(n4242), .Z(n4239));
+ OR2 U6005 ( .A(po028), .B(n6154), .Z(n4242));
+ AN2 U6006 ( .A(n6155), .B(n6156), .Z(n6154));
+ OR2 U6007 ( .A(n3321), .B(n3969), .Z(n6156));
+ IV2 U6008 ( .A(pi169), .Z(n3969));
+ AN2 U6009 ( .A(n4330), .B(n4205), .Z(n6153));
+ OR2 U6010 ( .A(n6157), .B(n5056), .Z(n4205));
+ IV2 U6011 ( .A(po028), .Z(n5056));
+ AN2 U6012 ( .A(n3261), .B(n6158), .Z(n6157));
+ OR2 U6013 ( .A(pi169), .B(n2837), .Z(n6158));
+ OR2 U6014 ( .A(n6159), .B(n6160), .Z(n4330));
+ OR2 U6015 ( .A(n6161), .B(n5930), .Z(n6160));
+ OR2 U6016 ( .A(n6162), .B(n6163), .Z(n5930));
+ OR2 U6017 ( .A(n6164), .B(n6165), .Z(n6163));
+ AN2 U6018 ( .A(n3393), .B(n6166), .Z(n6165));
+ OR2 U6019 ( .A(n6167), .B(n5853), .Z(n6166));
+ AN2 U6020 ( .A(n6168), .B(n3371), .Z(n6167));
+ IV2 U6021 ( .A(n3412), .Z(n3371));
+ AN2 U6022 ( .A(n5999), .B(n6053), .Z(n6164));
+ AN2 U6023 ( .A(n3453), .B(n3363), .Z(n5999));
+ AN2 U6024 ( .A(n3926), .B(n4975), .Z(n6162));
+ AN2 U6025 ( .A(n3940), .B(n4975), .Z(n6161));
+ OR2 U6026 ( .A(n6169), .B(n6170), .Z(n6159));
+ AN2 U6027 ( .A(n5931), .B(n6171), .Z(n6170));
+ OR2 U6028 ( .A(n6172), .B(n6173), .Z(n6171));
+ OR2 U6029 ( .A(n6174), .B(n6175), .Z(n6173));
+ AN2 U6030 ( .A(n5888), .B(n3363), .Z(n6175));
+ OR2 U6031 ( .A(n6176), .B(n6177), .Z(n5888));
+ OR2 U6032 ( .A(n3248), .B(n6178), .Z(n6177));
+ AN2 U6033 ( .A(n5833), .B(n3250), .Z(n6178));
+ AN2 U6034 ( .A(n4937), .B(n6179), .Z(n5833));
+ OR2 U6035 ( .A(n6180), .B(n6181), .Z(n6176));
+ AN2 U6036 ( .A(n3495), .B(n5835), .Z(n6181));
+ OR2 U6037 ( .A(n6182), .B(n5894), .Z(n5835));
+ AN2 U6038 ( .A(n5966), .B(n6183), .Z(n6182));
+ OR2 U6039 ( .A(n6184), .B(n6185), .Z(n5966));
+ AN2 U6040 ( .A(pi171), .B(pi192), .Z(n6185));
+ AN2 U6041 ( .A(pi142), .B(n2837), .Z(n6184));
+ AN2 U6042 ( .A(n6186), .B(n5836), .Z(n6180));
+ OR2 U6043 ( .A(n6187), .B(n6188), .Z(n5836));
+ AN2 U6044 ( .A(n3705), .B(n5843), .Z(n6188));
+ AN2 U6045 ( .A(pi192), .B(pi098), .Z(n3705));
+ AN2 U6046 ( .A(n3717), .B(n6189), .Z(n6187));
+ AN2 U6047 ( .A(n2837), .B(pi003), .Z(n3717));
+ AN2 U6048 ( .A(n5889), .B(n3534), .Z(n6174));
+ AN2 U6049 ( .A(n3261), .B(pi060), .Z(n3534));
+ AN2 U6050 ( .A(pi192), .B(n6190), .Z(n5889));
+ OR2 U6051 ( .A(n6191), .B(n6192), .Z(n6190));
+ OR2 U6052 ( .A(n6193), .B(n6194), .Z(n6192));
+ AN2 U6053 ( .A(pi004), .B(n4947), .Z(n6194));
+ AN2 U6054 ( .A(n3640), .B(n3250), .Z(n6193));
+ IV2 U6055 ( .A(n3344), .Z(n3250));
+ IV2 U6056 ( .A(n3632), .Z(n3640));
+ OR2 U6057 ( .A(po001), .B(n3998), .Z(n3632));
+ OR2 U6058 ( .A(n6195), .B(n6196), .Z(n6191));
+ AN2 U6059 ( .A(n6197), .B(n3495), .Z(n6196));
+ AN2 U6060 ( .A(pi171), .B(n6183), .Z(n6197));
+ AN2 U6061 ( .A(n6198), .B(n6186), .Z(n6195));
+ IV2 U6062 ( .A(n6199), .Z(n6186));
+ AN2 U6063 ( .A(pi098), .B(n5843), .Z(n6198));
+ OR2 U6064 ( .A(pi171), .B(n4441), .Z(n5843));
+ OR2 U6065 ( .A(n5892), .B(n6200), .Z(n6172));
+ AN2 U6066 ( .A(n6201), .B(n5894), .Z(n6200));
+ AN2 U6067 ( .A(n4441), .B(n4417), .Z(n5894));
+ AN2 U6068 ( .A(n3495), .B(n3453), .Z(n6201));
+ IV2 U6069 ( .A(n3451), .Z(n3453));
+ OR2 U6070 ( .A(n3533), .B(n3321), .Z(n3451));
+ IV2 U6071 ( .A(n3477), .Z(n3533));
+ OR2 U6072 ( .A(pi060), .B(n2837), .Z(n3477));
+ IV2 U6073 ( .A(n6202), .Z(n3495));
+ IV2 U6074 ( .A(n6203), .Z(n5892));
+ OR2 U6075 ( .A(n6204), .B(n6155), .Z(n6203));
+ AN2 U6076 ( .A(n6205), .B(n6206), .Z(n6204));
+ AN2 U6077 ( .A(n6207), .B(n6208), .Z(n6206));
+ OR2 U6078 ( .A(n6199), .B(n6209), .Z(n6208));
+ OR2 U6079 ( .A(n3244), .B(n3597), .Z(n6209));
+ IV2 U6080 ( .A(pi003), .Z(n3597));
+ IV2 U6081 ( .A(n6189), .Z(n3244));
+ OR2 U6082 ( .A(pi142), .B(n4441), .Z(n6189));
+ OR2 U6083 ( .A(n4418), .B(n6202), .Z(n6199));
+ IV2 U6084 ( .A(n4426), .Z(n4418));
+ OR2 U6085 ( .A(n3688), .B(n3290), .Z(n4426));
+ IV2 U6086 ( .A(po011), .Z(n3688));
+ OR2 U6087 ( .A(n6202), .B(n6210), .Z(n6207));
+ OR2 U6088 ( .A(n4430), .B(n4440), .Z(n6210));
+ IV2 U6089 ( .A(pi142), .Z(n4440));
+ IV2 U6090 ( .A(n6183), .Z(n4430));
+ OR2 U6091 ( .A(n4417), .B(n4441), .Z(n6183));
+ IV2 U6092 ( .A(po036), .Z(n4441));
+ IV2 U6093 ( .A(n3236), .Z(n4417));
+ OR2 U6094 ( .A(n3234), .B(po011), .Z(n3236));
+ IV2 U6095 ( .A(n3290), .Z(n3234));
+ OR2 U6096 ( .A(n6211), .B(n6212), .Z(n3290));
+ OR2 U6097 ( .A(n6213), .B(n6214), .Z(n6212));
+ OR2 U6098 ( .A(n6215), .B(n6216), .Z(n6214));
+ AN2 U6099 ( .A(pi192), .B(n5980), .Z(n6216));
+ OR2 U6100 ( .A(n6217), .B(n6218), .Z(n5980));
+ OR2 U6101 ( .A(n6219), .B(n6220), .Z(n6218));
+ AN2 U6102 ( .A(pi045), .B(n4915), .Z(n6220));
+ AN2 U6103 ( .A(n4621), .B(n4751), .Z(n6219));
+ IV2 U6104 ( .A(n4465), .Z(n4621));
+ OR2 U6105 ( .A(po014), .B(n3908), .Z(n4465));
+ IV2 U6106 ( .A(pi079), .Z(n3908));
+ OR2 U6107 ( .A(n6221), .B(n6222), .Z(n6217));
+ AN2 U6108 ( .A(n6223), .B(n3757), .Z(n6222));
+ AN2 U6109 ( .A(pi158), .B(n4628), .Z(n6223));
+ AN2 U6110 ( .A(n6224), .B(n6225), .Z(n6221));
+ AN2 U6111 ( .A(pi175), .B(n5037), .Z(n6224));
+ AN2 U6112 ( .A(n6008), .B(n2837), .Z(n6215));
+ OR2 U6113 ( .A(n6226), .B(n6227), .Z(n6008));
+ OR2 U6114 ( .A(n6228), .B(n6229), .Z(n6227));
+ AN2 U6115 ( .A(pi095), .B(n4915), .Z(n6229));
+ AN2 U6116 ( .A(n4623), .B(n4751), .Z(n6228));
+ IV2 U6117 ( .A(n4469), .Z(n4623));
+ OR2 U6118 ( .A(po014), .B(n4648), .Z(n4469));
+ IV2 U6119 ( .A(pi156), .Z(n4648));
+ OR2 U6120 ( .A(n6230), .B(n6231), .Z(n6226));
+ AN2 U6121 ( .A(n6232), .B(n3757), .Z(n6231));
+ AN2 U6122 ( .A(pi151), .B(n4628), .Z(n6232));
+ AN2 U6123 ( .A(n6233), .B(n6225), .Z(n6230));
+ AN2 U6124 ( .A(pi185), .B(n5037), .Z(n6233));
+ AN2 U6125 ( .A(n5985), .B(n6234), .Z(n6213));
+ OR2 U6126 ( .A(n6235), .B(n6236), .Z(n6234));
+ OR2 U6127 ( .A(n6237), .B(n6238), .Z(n6236));
+ OR2 U6128 ( .A(n6239), .B(n6240), .Z(n6238));
+ AN2 U6129 ( .A(n6241), .B(n3055), .Z(n6240));
+ AN2 U6130 ( .A(n5822), .B(n3119), .Z(n6241));
+ OR2 U6131 ( .A(n6242), .B(n6016), .Z(n3119));
+ AN2 U6132 ( .A(pi141), .B(po099), .Z(n6242));
+ AN2 U6133 ( .A(n5994), .B(n6243), .Z(n6239));
+ AN2 U6134 ( .A(n6244), .B(n3049), .Z(n6237));
+ OR2 U6135 ( .A(n6243), .B(n6245), .Z(n6244));
+ OR2 U6136 ( .A(n6020), .B(n6246), .Z(n6245));
+ AN2 U6137 ( .A(n6247), .B(n5826), .Z(n6246));
+ AN2 U6138 ( .A(n3106), .B(n5829), .Z(n5826));
+ OR2 U6139 ( .A(n5994), .B(n5822), .Z(n5829));
+ IV2 U6140 ( .A(pi166), .Z(n3106));
+ AN2 U6141 ( .A(n3063), .B(pi192), .Z(n6247));
+ AN2 U6142 ( .A(n6016), .B(n5994), .Z(n6020));
+ AN2 U6143 ( .A(n3286), .B(n3177), .Z(n6016));
+ OR2 U6144 ( .A(n6142), .B(n6248), .Z(n6243));
+ AN2 U6145 ( .A(n3207), .B(n3286), .Z(n6248));
+ OR2 U6146 ( .A(n6249), .B(n6250), .Z(n3207));
+ AN2 U6147 ( .A(n3064), .B(n3171), .Z(n6250));
+ AN2 U6148 ( .A(n3173), .B(n3177), .Z(n6249));
+ IV2 U6149 ( .A(pi141), .Z(n3177));
+ AN2 U6150 ( .A(pi033), .B(n3064), .Z(n6142));
+ OR2 U6151 ( .A(n6251), .B(n6252), .Z(n6235));
+ OR2 U6152 ( .A(n6044), .B(n3100), .Z(n6252));
+ AN2 U6153 ( .A(n3286), .B(n6138), .Z(n3100));
+ OR2 U6154 ( .A(n6253), .B(n6254), .Z(n6138));
+ AN2 U6155 ( .A(pi033), .B(pi192), .Z(n6254));
+ AN2 U6156 ( .A(pi141), .B(n2837), .Z(n6253));
+ AN2 U6157 ( .A(n6255), .B(pi141), .Z(n6044));
+ OR2 U6158 ( .A(n3071), .B(n6256), .Z(n6255));
+ AN2 U6159 ( .A(n3055), .B(n5994), .Z(n6256));
+ IV2 U6160 ( .A(n6257), .Z(n5994));
+ OR2 U6161 ( .A(n2925), .B(n5099), .Z(n6257));
+ OR2 U6162 ( .A(n6258), .B(n6259), .Z(n5099));
+ OR2 U6163 ( .A(n3146), .B(n6260), .Z(n6259));
+ OR2 U6164 ( .A(n6261), .B(n6262), .Z(n6260));
+ AN2 U6165 ( .A(n2845), .B(n2837), .Z(n6262));
+ IV2 U6166 ( .A(n2846), .Z(n2845));
+ AN2 U6167 ( .A(n6263), .B(n6264), .Z(n2846));
+ OR2 U6168 ( .A(n3141), .B(po044), .Z(n6263));
+ IV2 U6169 ( .A(pi201), .Z(n3141));
+ AN2 U6170 ( .A(pi192), .B(n2833), .Z(n6261));
+ IV2 U6171 ( .A(n2834), .Z(n2833));
+ AN2 U6172 ( .A(n6265), .B(n6266), .Z(n2834));
+ OR2 U6173 ( .A(n3136), .B(po044), .Z(n6265));
+ IV2 U6174 ( .A(pi088), .Z(n3136));
+ OR2 U6175 ( .A(n6267), .B(n6268), .Z(n3146));
+ AN2 U6176 ( .A(n2880), .B(pi192), .Z(n6268));
+ IV2 U6177 ( .A(n2878), .Z(n2880));
+ OR2 U6178 ( .A(pi077), .B(n2962), .Z(n2878));
+ AN2 U6179 ( .A(n2978), .B(n2837), .Z(n6267));
+ IV2 U6180 ( .A(n2939), .Z(n2978));
+ OR2 U6181 ( .A(n2998), .B(n6269), .Z(n6258));
+ OR2 U6182 ( .A(n2901), .B(n2862), .Z(n6269));
+ IV2 U6183 ( .A(pi200), .Z(n2901));
+ IV2 U6184 ( .A(n3003), .Z(n2925));
+ OR2 U6185 ( .A(pi192), .B(n2960), .Z(n3003));
+ IV2 U6186 ( .A(n6270), .Z(n2960));
+ OR2 U6187 ( .A(n6271), .B(n6272), .Z(n6270));
+ AN2 U6188 ( .A(pi081), .B(n2931), .Z(n6272));
+ IV2 U6189 ( .A(po107), .Z(n2931));
+ AN2 U6190 ( .A(po107), .B(n2982), .Z(n6271));
+ AN2 U6191 ( .A(n2837), .B(n6017), .Z(n3055));
+ IV2 U6192 ( .A(n5828), .Z(n6017));
+ OR2 U6193 ( .A(n6273), .B(n6015), .Z(n5828));
+ AN2 U6194 ( .A(pi174), .B(n3049), .Z(n6015));
+ AN2 U6195 ( .A(po010), .B(n5115), .Z(n6273));
+ IV2 U6196 ( .A(pi174), .Z(n5115));
+ AN2 U6197 ( .A(n3049), .B(n3173), .Z(n3071));
+ AN2 U6198 ( .A(n2837), .B(pi174), .Z(n3173));
+ IV2 U6199 ( .A(po010), .Z(n3049));
+ AN2 U6200 ( .A(n6274), .B(n3063), .Z(n6251));
+ IV2 U6201 ( .A(n6275), .Z(n3063));
+ OR2 U6202 ( .A(n6276), .B(n6277), .Z(n6275));
+ AN2 U6203 ( .A(pi033), .B(n3286), .Z(n6277));
+ IV2 U6204 ( .A(po099), .Z(n3286));
+ AN2 U6205 ( .A(po099), .B(n3171), .Z(n6276));
+ IV2 U6206 ( .A(pi033), .Z(n3171));
+ AN2 U6207 ( .A(n3064), .B(n5822), .Z(n6274));
+ OR2 U6208 ( .A(n6278), .B(n6279), .Z(n5822));
+ OR2 U6209 ( .A(n6280), .B(n6281), .Z(n6279));
+ AN2 U6210 ( .A(n6282), .B(pi192), .Z(n6281));
+ AN2 U6211 ( .A(n5156), .B(n6266), .Z(n6282));
+ OR2 U6212 ( .A(pi088), .B(n5000), .Z(n6266));
+ OR2 U6213 ( .A(n6283), .B(n5153), .Z(n5156));
+ AN2 U6214 ( .A(n2861), .B(n6284), .Z(n6283));
+ OR2 U6215 ( .A(n2885), .B(n2892), .Z(n6284));
+ AN2 U6216 ( .A(n5008), .B(pi157), .Z(n2892));
+ AN2 U6217 ( .A(n2930), .B(n2876), .Z(n2885));
+ IV2 U6218 ( .A(n2887), .Z(n2876));
+ OR2 U6219 ( .A(po031), .B(n3846), .Z(n2887));
+ IV2 U6220 ( .A(pi077), .Z(n3846));
+ AN2 U6221 ( .A(n6285), .B(n2837), .Z(n6280));
+ AN2 U6222 ( .A(n5175), .B(n6264), .Z(n6285));
+ OR2 U6223 ( .A(pi201), .B(n5000), .Z(n6264));
+ OR2 U6224 ( .A(n6286), .B(n6287), .Z(n5175));
+ AN2 U6225 ( .A(n2861), .B(n6288), .Z(n6286));
+ OR2 U6226 ( .A(n6289), .B(n2929), .Z(n6288));
+ IV2 U6227 ( .A(n2947), .Z(n2929));
+ OR2 U6228 ( .A(po106), .B(n5431), .Z(n2947));
+ IV2 U6229 ( .A(pi206), .Z(n5431));
+ AN2 U6230 ( .A(n2930), .B(n4113), .Z(n6289));
+ OR2 U6231 ( .A(n2919), .B(n2936), .Z(n4113));
+ IV2 U6232 ( .A(n2946), .Z(n2936));
+ OR2 U6233 ( .A(po031), .B(n2957), .Z(n2946));
+ IV2 U6234 ( .A(pi082), .Z(n2957));
+ AN2 U6235 ( .A(n2902), .B(n2939), .Z(n2919));
+ OR2 U6236 ( .A(pi082), .B(n2962), .Z(n2939));
+ IV2 U6237 ( .A(po031), .Z(n2962));
+ IV2 U6238 ( .A(n2974), .Z(n2902));
+ OR2 U6239 ( .A(po107), .B(n2982), .Z(n2974));
+ IV2 U6240 ( .A(pi081), .Z(n2982));
+ IV2 U6241 ( .A(n2862), .Z(n2930));
+ OR2 U6242 ( .A(n6290), .B(n6291), .Z(n2862));
+ AN2 U6243 ( .A(n6292), .B(n5008), .Z(n6291));
+ IV2 U6244 ( .A(po106), .Z(n5008));
+ AN2 U6245 ( .A(n6293), .B(po106), .Z(n6290));
+ IV2 U6246 ( .A(n6292), .Z(n6293));
+ OR2 U6247 ( .A(n6294), .B(n6295), .Z(n6292));
+ AN2 U6248 ( .A(pi192), .B(pi157), .Z(n6295));
+ AN2 U6249 ( .A(pi206), .B(n2837), .Z(n6294));
+ IV2 U6250 ( .A(n2998), .Z(n2861));
+ OR2 U6251 ( .A(n6296), .B(n6297), .Z(n2998));
+ OR2 U6252 ( .A(n6298), .B(n6299), .Z(n6297));
+ AN2 U6253 ( .A(n5153), .B(pi192), .Z(n6299));
+ AN2 U6254 ( .A(n5004), .B(pi026), .Z(n5153));
+ IV2 U6255 ( .A(po079), .Z(n5004));
+ AN2 U6256 ( .A(n6287), .B(n2837), .Z(n6298));
+ IV2 U6257 ( .A(n5172), .Z(n6287));
+ OR2 U6258 ( .A(po079), .B(n5165), .Z(n5172));
+ AN2 U6259 ( .A(po079), .B(n6027), .Z(n6296));
+ OR2 U6260 ( .A(n6300), .B(n6301), .Z(n6027));
+ AN2 U6261 ( .A(pi192), .B(n3847), .Z(n6301));
+ IV2 U6262 ( .A(pi026), .Z(n3847));
+ AN2 U6263 ( .A(n5165), .B(n2837), .Z(n6300));
+ IV2 U6264 ( .A(pi107), .Z(n5165));
+ AN2 U6265 ( .A(n3011), .B(n5000), .Z(n6278));
+ IV2 U6266 ( .A(po044), .Z(n5000));
+ OR2 U6267 ( .A(n6302), .B(n6303), .Z(n3011));
+ AN2 U6268 ( .A(pi088), .B(pi192), .Z(n6303));
+ AN2 U6269 ( .A(pi201), .B(n2837), .Z(n6302));
+ AN2 U6270 ( .A(pi192), .B(pi166), .Z(n3064));
+ AN2 U6271 ( .A(n3018), .B(n5984), .Z(n5985));
+ AN2 U6272 ( .A(n6304), .B(n5104), .Z(n3018));
+ IV2 U6273 ( .A(n5074), .Z(n5104));
+ OR2 U6274 ( .A(n6305), .B(n5040), .Z(n6304));
+ OR2 U6275 ( .A(n6306), .B(n6307), .Z(n6211));
+ OR2 U6276 ( .A(n6308), .B(n6309), .Z(n6307));
+ AN2 U6277 ( .A(n4624), .B(n5981), .Z(n6309));
+ AN2 U6278 ( .A(n3300), .B(n3305), .Z(n4624));
+ AN2 U6279 ( .A(n5984), .B(n5074), .Z(n6308));
+ AN2 U6280 ( .A(n5040), .B(n6305), .Z(n5074));
+ OR2 U6281 ( .A(n6310), .B(n6311), .Z(n6305));
+ AN2 U6282 ( .A(pi096), .B(pi192), .Z(n6311));
+ AN2 U6283 ( .A(pi128), .B(n2837), .Z(n6310));
+ IV2 U6284 ( .A(po070), .Z(n5040));
+ AN2 U6285 ( .A(n3083), .B(n6225), .Z(n5984));
+ AN2 U6286 ( .A(n6312), .B(n6313), .Z(n6225));
+ AN2 U6287 ( .A(n3760), .B(n4341), .Z(n6313));
+ AN2 U6288 ( .A(n4333), .B(n4482), .Z(n6312));
+ OR2 U6289 ( .A(n6314), .B(n6315), .Z(n4333));
+ AN2 U6290 ( .A(po025), .B(n6316), .Z(n6315));
+ OR2 U6291 ( .A(n6317), .B(n3888), .Z(n6316));
+ AN2 U6292 ( .A(pi192), .B(pi191), .Z(n3888));
+ AN2 U6293 ( .A(pi076), .B(n2837), .Z(n6317));
+ AN2 U6294 ( .A(n3781), .B(n4557), .Z(n6314));
+ OR2 U6295 ( .A(n4538), .B(n3890), .Z(n3781));
+ IV2 U6296 ( .A(n6318), .Z(n3890));
+ OR2 U6297 ( .A(pi191), .B(n2837), .Z(n6318));
+ AN2 U6298 ( .A(n4077), .B(n2837), .Z(n4538));
+ IV2 U6299 ( .A(n3021), .Z(n3083));
+ OR2 U6300 ( .A(n6319), .B(n6134), .Z(n3021));
+ AN2 U6301 ( .A(n6320), .B(n5037), .Z(n6134));
+ IV2 U6302 ( .A(po035), .Z(n5037));
+ AN2 U6303 ( .A(n6321), .B(po035), .Z(n6319));
+ IV2 U6304 ( .A(n6320), .Z(n6321));
+ OR2 U6305 ( .A(n6322), .B(n6323), .Z(n6320));
+ AN2 U6306 ( .A(pi175), .B(pi192), .Z(n6323));
+ AN2 U6307 ( .A(pi185), .B(n2837), .Z(n6322));
+ AN2 U6308 ( .A(n3760), .B(n6324), .Z(n6306));
+ OR2 U6309 ( .A(n6325), .B(n6326), .Z(n6324));
+ OR2 U6310 ( .A(n6327), .B(n6328), .Z(n6326));
+ AN2 U6311 ( .A(n4482), .B(n4340), .Z(n6328));
+ OR2 U6312 ( .A(n6329), .B(n6330), .Z(n4340));
+ AN2 U6313 ( .A(n6121), .B(n2837), .Z(n6330));
+ OR2 U6314 ( .A(n6331), .B(n4567), .Z(n6121));
+ IV2 U6315 ( .A(n4578), .Z(n4567));
+ OR2 U6316 ( .A(po024), .B(n4358), .Z(n4578));
+ AN2 U6317 ( .A(n4084), .B(n4066), .Z(n6331));
+ OR2 U6318 ( .A(n6332), .B(n4539), .Z(n4084));
+ IV2 U6319 ( .A(n5503), .Z(n4539));
+ OR2 U6320 ( .A(po059), .B(n4074), .Z(n5503));
+ IV2 U6321 ( .A(pi170), .Z(n4074));
+ AN2 U6322 ( .A(n4576), .B(n3778), .Z(n6332));
+ IV2 U6323 ( .A(n4580), .Z(n4576));
+ OR2 U6324 ( .A(po025), .B(n4077), .Z(n4580));
+ IV2 U6325 ( .A(pi076), .Z(n4077));
+ AN2 U6326 ( .A(pi192), .B(n6128), .Z(n6329));
+ OR2 U6327 ( .A(n6333), .B(n6334), .Z(n6128));
+ OR2 U6328 ( .A(n4561), .B(n6335), .Z(n6334));
+ AN2 U6329 ( .A(n6336), .B(n4341), .Z(n6335));
+ AN2 U6330 ( .A(n4066), .B(n3778), .Z(n4341));
+ IV2 U6331 ( .A(n3773), .Z(n3778));
+ OR2 U6332 ( .A(n6337), .B(n6338), .Z(n3773));
+ AN2 U6333 ( .A(n6339), .B(n4877), .Z(n6338));
+ IV2 U6334 ( .A(po059), .Z(n4877));
+ AN2 U6335 ( .A(n6340), .B(po059), .Z(n6337));
+ IV2 U6336 ( .A(n6339), .Z(n6340));
+ OR2 U6337 ( .A(n6341), .B(n6342), .Z(n6339));
+ AN2 U6338 ( .A(pi135), .B(pi192), .Z(n6342));
+ AN2 U6339 ( .A(pi170), .B(n2837), .Z(n6341));
+ AN2 U6340 ( .A(pi191), .B(n4557), .Z(n6336));
+ IV2 U6341 ( .A(po025), .Z(n4557));
+ IV2 U6342 ( .A(n4348), .Z(n4561));
+ OR2 U6343 ( .A(po024), .B(n3896), .Z(n4348));
+ AN2 U6344 ( .A(n4085), .B(n4066), .Z(n6333));
+ OR2 U6345 ( .A(n6343), .B(n6344), .Z(n4066));
+ OR2 U6346 ( .A(n6345), .B(n6346), .Z(n6344));
+ AN2 U6347 ( .A(n6347), .B(po024), .Z(n6346));
+ AN2 U6348 ( .A(pi005), .B(pi192), .Z(n6347));
+ AN2 U6349 ( .A(n6348), .B(n4874), .Z(n6345));
+ IV2 U6350 ( .A(po024), .Z(n4874));
+ OR2 U6351 ( .A(n6349), .B(n5483), .Z(n6348));
+ AN2 U6352 ( .A(pi192), .B(n3896), .Z(n5483));
+ IV2 U6353 ( .A(pi005), .Z(n3896));
+ AN2 U6354 ( .A(n4358), .B(n2837), .Z(n6349));
+ IV2 U6355 ( .A(pi160), .Z(n4358));
+ AN2 U6356 ( .A(pi160), .B(n5477), .Z(n6343));
+ AN2 U6357 ( .A(n2837), .B(po024), .Z(n5477));
+ IV2 U6358 ( .A(n4353), .Z(n4085));
+ OR2 U6359 ( .A(po059), .B(n3880), .Z(n4353));
+ IV2 U6360 ( .A(pi135), .Z(n3880));
+ AN2 U6361 ( .A(n4342), .B(n4475), .Z(n4482));
+ AN2 U6362 ( .A(n6350), .B(n6351), .Z(n4342));
+ OR2 U6363 ( .A(n6131), .B(po102), .Z(n6351));
+ IV2 U6364 ( .A(n6352), .Z(n6131));
+ OR2 U6365 ( .A(n6352), .B(n4885), .Z(n6350));
+ AN2 U6366 ( .A(n5462), .B(n4475), .Z(n6327));
+ IV2 U6367 ( .A(n4478), .Z(n4475));
+ OR2 U6368 ( .A(n6353), .B(n6325), .Z(n4478));
+ AN2 U6369 ( .A(n6354), .B(po072), .Z(n6353));
+ IV2 U6370 ( .A(n6355), .Z(n6354));
+ AN2 U6371 ( .A(n6352), .B(n4885), .Z(n5462));
+ IV2 U6372 ( .A(po102), .Z(n4885));
+ OR2 U6373 ( .A(n6356), .B(n6357), .Z(n6352));
+ AN2 U6374 ( .A(pi069), .B(pi192), .Z(n6357));
+ AN2 U6375 ( .A(pi114), .B(n2837), .Z(n6356));
+ AN2 U6376 ( .A(n6355), .B(n4881), .Z(n6325));
+ IV2 U6377 ( .A(po072), .Z(n4881));
+ OR2 U6378 ( .A(n6358), .B(n6359), .Z(n6355));
+ AN2 U6379 ( .A(pi148), .B(pi192), .Z(n6359));
+ AN2 U6380 ( .A(pi108), .B(n2837), .Z(n6358));
+ AN2 U6381 ( .A(n4450), .B(n5981), .Z(n3760));
+ AN2 U6382 ( .A(n3301), .B(n4751), .Z(n5981));
+ AN2 U6383 ( .A(n4006), .B(n3757), .Z(n4751));
+ IV2 U6384 ( .A(n4444), .Z(n3757));
+ OR2 U6385 ( .A(n6360), .B(n3754), .Z(n4444));
+ AN2 U6386 ( .A(n6361), .B(n4915), .Z(n3754));
+ IV2 U6387 ( .A(po063), .Z(n4915));
+ AN2 U6388 ( .A(n6362), .B(po063), .Z(n6360));
+ IV2 U6389 ( .A(n6361), .Z(n6362));
+ OR2 U6390 ( .A(n6363), .B(n6364), .Z(n6361));
+ AN2 U6391 ( .A(pi045), .B(pi192), .Z(n6364));
+ AN2 U6392 ( .A(pi095), .B(n2837), .Z(n6363));
+ AN2 U6393 ( .A(n6365), .B(n6366), .Z(n4006));
+ OR2 U6394 ( .A(n6367), .B(po092), .Z(n6366));
+ IV2 U6395 ( .A(n4752), .Z(n6367));
+ OR2 U6396 ( .A(n4752), .B(n4628), .Z(n6365));
+ IV2 U6397 ( .A(po092), .Z(n4628));
+ OR2 U6398 ( .A(n6368), .B(n6369), .Z(n4752));
+ AN2 U6399 ( .A(pi158), .B(pi192), .Z(n6369));
+ AN2 U6400 ( .A(pi151), .B(n2837), .Z(n6368));
+ IV2 U6401 ( .A(n3295), .Z(n3301));
+ OR2 U6402 ( .A(n6370), .B(n6371), .Z(n3295));
+ AN2 U6403 ( .A(n4703), .B(n4861), .Z(n6371));
+ IV2 U6404 ( .A(po014), .Z(n4861));
+ AN2 U6405 ( .A(n4736), .B(po014), .Z(n6370));
+ IV2 U6406 ( .A(n4703), .Z(n4736));
+ OR2 U6407 ( .A(n6372), .B(n6373), .Z(n4703));
+ AN2 U6408 ( .A(pi079), .B(pi192), .Z(n6373));
+ AN2 U6409 ( .A(pi156), .B(n2837), .Z(n6372));
+ IV2 U6410 ( .A(n4606), .Z(n4450));
+ AN2 U6411 ( .A(n6374), .B(n6375), .Z(n4606));
+ OR2 U6412 ( .A(n3305), .B(po039), .Z(n6375));
+ OR2 U6413 ( .A(n3300), .B(n6376), .Z(n6374));
+ IV2 U6414 ( .A(n3305), .Z(n6376));
+ OR2 U6415 ( .A(n4685), .B(n4692), .Z(n3305));
+ AN2 U6416 ( .A(pi192), .B(pi016), .Z(n4692));
+ AN2 U6417 ( .A(n2837), .B(pi040), .Z(n4685));
+ IV2 U6418 ( .A(po039), .Z(n3300));
+ OR2 U6419 ( .A(n3352), .B(n3344), .Z(n6202));
+ AN2 U6420 ( .A(n6377), .B(n6378), .Z(n3352));
+ OR2 U6421 ( .A(n6179), .B(po001), .Z(n6378));
+ IV2 U6422 ( .A(n6379), .Z(n6179));
+ OR2 U6423 ( .A(n6379), .B(n4937), .Z(n6377));
+ IV2 U6424 ( .A(po001), .Z(n4937));
+ OR2 U6425 ( .A(n5959), .B(n6380), .Z(n6379));
+ AN2 U6426 ( .A(pi192), .B(n3998), .Z(n6380));
+ IV2 U6427 ( .A(pi068), .Z(n3998));
+ AN2 U6428 ( .A(n2837), .B(n5379), .Z(n5959));
+ AN2 U6429 ( .A(n6381), .B(n6382), .Z(n6205));
+ OR2 U6430 ( .A(n3344), .B(n3590), .Z(n6382));
+ OR2 U6431 ( .A(po001), .B(n5379), .Z(n3590));
+ IV2 U6432 ( .A(pi195), .Z(n5379));
+ OR2 U6433 ( .A(n6383), .B(n3248), .Z(n3344));
+ AN2 U6434 ( .A(n6384), .B(n4947), .Z(n3248));
+ IV2 U6435 ( .A(po082), .Z(n4947));
+ AN2 U6436 ( .A(n6385), .B(po082), .Z(n6383));
+ IV2 U6437 ( .A(n6384), .Z(n6385));
+ OR2 U6438 ( .A(n6386), .B(n6387), .Z(n6384));
+ AN2 U6439 ( .A(pi004), .B(pi192), .Z(n6387));
+ AN2 U6440 ( .A(pi130), .B(n2837), .Z(n6386));
+ OR2 U6441 ( .A(po082), .B(n5372), .Z(n6381));
+ IV2 U6442 ( .A(pi130), .Z(n5372));
+ AN2 U6443 ( .A(n3225), .B(n6053), .Z(n5931));
+ IV2 U6444 ( .A(n3247), .Z(n3225));
+ OR2 U6445 ( .A(n6388), .B(n3490), .Z(n3247));
+ AN2 U6446 ( .A(n4943), .B(n5895), .Z(n3490));
+ OR2 U6447 ( .A(n3926), .B(n3989), .Z(n5895));
+ IV2 U6448 ( .A(n6389), .Z(n6388));
+ OR2 U6449 ( .A(n4943), .B(n6390), .Z(n6389));
+ AN2 U6450 ( .A(n6391), .B(n3261), .Z(n6390));
+ OR2 U6451 ( .A(n2837), .B(pi133), .Z(n6391));
+ AN2 U6452 ( .A(n6392), .B(n6053), .Z(n6169));
+ AN2 U6453 ( .A(n3393), .B(n6393), .Z(n6053));
+ IV2 U6454 ( .A(n3461), .Z(n6393));
+ OR2 U6455 ( .A(n3401), .B(n3412), .Z(n3461));
+ OR2 U6456 ( .A(n6394), .B(n5853), .Z(n3412));
+ OR2 U6457 ( .A(n3466), .B(n3392), .Z(n5853));
+ AN2 U6458 ( .A(n3380), .B(n3926), .Z(n3392));
+ IV2 U6459 ( .A(po071), .Z(n3380));
+ AN2 U6460 ( .A(n3261), .B(n3381), .Z(n3466));
+ IV2 U6461 ( .A(n3399), .Z(n3381));
+ OR2 U6462 ( .A(po071), .B(n3913), .Z(n3399));
+ AN2 U6463 ( .A(po071), .B(n5878), .Z(n6394));
+ OR2 U6464 ( .A(n3480), .B(n3321), .Z(n5878));
+ AN2 U6465 ( .A(n3913), .B(pi192), .Z(n3480));
+ IV2 U6466 ( .A(pi118), .Z(n3913));
+ OR2 U6467 ( .A(n5881), .B(n6395), .Z(n3401));
+ OR2 U6468 ( .A(n6168), .B(n6396), .Z(n6395));
+ AN2 U6469 ( .A(po104), .B(n3321), .Z(n6396));
+ AN2 U6470 ( .A(n3485), .B(n3261), .Z(n6168));
+ IV2 U6471 ( .A(n3419), .Z(n3485));
+ OR2 U6472 ( .A(n6397), .B(po104), .Z(n3419));
+ AN2 U6473 ( .A(pi192), .B(n3942), .Z(n6397));
+ IV2 U6474 ( .A(pi196), .Z(n3942));
+ AN2 U6475 ( .A(pi192), .B(n5872), .Z(n5881));
+ IV2 U6476 ( .A(n5866), .Z(n5872));
+ OR2 U6477 ( .A(pi196), .B(n3512), .Z(n5866));
+ IV2 U6478 ( .A(po104), .Z(n3512));
+ OR2 U6479 ( .A(n6398), .B(n6399), .Z(n3393));
+ AN2 U6480 ( .A(n6400), .B(n4975), .Z(n6399));
+ IV2 U6481 ( .A(po038), .Z(n4975));
+ OR2 U6482 ( .A(n6401), .B(n3321), .Z(n6400));
+ AN2 U6483 ( .A(pi192), .B(n3943), .Z(n6401));
+ IV2 U6484 ( .A(pi050), .Z(n3943));
+ AN2 U6485 ( .A(po038), .B(n6402), .Z(n6398));
+ OR2 U6486 ( .A(n3940), .B(n3926), .Z(n6402));
+ AN2 U6487 ( .A(n3261), .B(pi050), .Z(n3940));
+ AN2 U6488 ( .A(n6403), .B(n4943), .Z(n6392));
+ IV2 U6489 ( .A(po057), .Z(n4943));
+ OR2 U6490 ( .A(n6404), .B(n6052), .Z(n6403));
+ OR2 U6491 ( .A(n6405), .B(n3926), .Z(n6052));
+ IV2 U6492 ( .A(n6155), .Z(n3926));
+ OR2 U6493 ( .A(pi192), .B(n3321), .Z(n6155));
+ AN2 U6494 ( .A(pi060), .B(n3989), .Z(n6405));
+ AN2 U6495 ( .A(n3989), .B(n3363), .Z(n6404));
+ IV2 U6496 ( .A(po027), .Z(n3363));
+ AN2 U6497 ( .A(n3261), .B(pi133), .Z(n3989));
+ IV2 U6498 ( .A(n3321), .Z(n3261));
+ IV2 U6499 ( .A(n6149), .Z(n4217));
+ OR2 U6500 ( .A(n4148), .B(n3321), .Z(n6149));
+ AN2 U6501 ( .A(pi161), .B(pi012), .Z(n3321));
+ IV2 U6502 ( .A(n4247), .Z(n4148));
+ OR2 U6503 ( .A(pi058), .B(n2837), .Z(n4247));
+ IV2 U6504 ( .A(pi192), .Z(n2837));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/C7552.ys b/examples/smtbmc/glift/C7552.ys
new file mode 100644
index 000000000..a9a1f5dc2
--- /dev/null
+++ b/examples/smtbmc/glift/C7552.ys
@@ -0,0 +1,41 @@
+read_verilog C7552.v
+techmap
+flatten
+select C7552_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename C7552_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog C7552.v
+techmap
+flatten
+select C7552_lev2
+glift -create-precise-model
+techmap
+opt
+rename C7552_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution C7552.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file C7552.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/C880.v b/examples/smtbmc/glift/C880.v
new file mode 100755
index 000000000..18dc24cc5
--- /dev/null
+++ b/examples/smtbmc/glift/C880.v
@@ -0,0 +1,451 @@
+module C880_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50, pi51, pi52, pi53, pi54, pi55, pi56, pi57, pi58, pi59,
+ po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20, po21, po22, po23, po24, po25);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50, pi51, pi52, pi53, pi54, pi55, pi56, pi57, pi58, pi59;
+
+output po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20, po21, po22, po23, po24, po25;
+
+wire n137, n346, n364, n415, n295, n427, n351, n377, n454, n357,
+ n358, n359, n360, n361, n362, n363, n365, n366, n367, n368,
+ n369, n370, n371, n372, n373, n374, n375, n376, n378, n379,
+ n380, n381, n382, n383, n384, n385, n386, n387, n388, n389,
+ n390, n391, n392, n393, n394, n395, n396, n397, n398, n399,
+ n400, n401, n402, n403, n404, n405, n406, n407, n408, n409,
+ n410, n411, n412, n413, n414, n416, n417, n418, n419, n420,
+ n421, n422, n423, n424, n425, n426, n428, n429, n430, n431,
+ n432, n433, n434, n435, n436, n437, n438, n439, n440, n441,
+ n442, n443, n444, n445, n446, n447, n448, n449, n450, n451,
+ n452, n453, n455, n456, n457, n458, n459, n460, n461, n462,
+ n463, n464, n465, n466, n467, n468, n469, n470, n471, n472,
+ n473, n474, n475, n476, n477, n478, n479, n480, n481, n482,
+ n483, n484, n485, n486, n487, n488, n489, n490, n491, n492,
+ n493, n494, n495, n496, n497, n498, n499, n500, n501, n502,
+ n503, n504, n505, n506, n507, n508, n509, n510, n511, n512,
+ n513, n514, n515, n516, n517, n518, n519, n520, n521, n522,
+ n523, n524, n525, n526, n527, n528, n529, n530, n531, n532,
+ n533, n534, n535, n536, n537, n538, n539, n540, n541, n542,
+ n543, n544, n545, n546, n547, n548, n549, n550, n551, n552,
+ n553, n554, n555, n556, n557, n558, n559, n560, n561, n562,
+ n563, n564, n565, n566, n567, n568, n569, n570, n571, n572,
+ n573, n574, n575, n576, n577, n578, n579, n580, n581, n582,
+ n583, n584, n585, n586, n587, n588, n589, n590, n591, n592,
+ n593, n594, n595, n596, n597, n598, n599, n600, n601, n602,
+ n603, n604, n605, n606, n607, n608, n609, n610, n611, n612,
+ n613, n614, n615, n616, n617, n618, n619, n620, n621, n622,
+ n623, n624, n625, n626, n627, n628, n629, n630, n631, n632,
+ n633, n634, n635, n636, n637, n638, n639, n640, n641, n642,
+ n643, n644, n645, n646, n647, n648, n649, n650, n651, n652,
+ n653, n654, n655, n656, n657, n658, n659, n660, n661, n662,
+ n663, n664, n665, n666, n667, n668, n669, n670, n671, n672,
+ n673, n674, n675, n676, n677, n678, n679, n680, n681, n682,
+ n683, n684, n685, n686, n687, n688, n689, n690, n691, n692,
+ n693, n694, n695, n696;
+
+
+assign po22 = n137;
+assign po19 = n346;
+assign po16 = n364;
+assign po17 = n415;
+assign po18 = n295;
+assign po00 = n427;
+assign po09 = n351;
+assign po04 = n377;
+assign po06 = n454;
+ AN2 U371 ( .A(pi11), .B(pi08), .Z(n357));
+ AN2 U372 ( .A(pi28), .B(n357), .Z(n346));
+ AN2 U373 ( .A(pi41), .B(pi25), .Z(n369));
+ AN2 U374 ( .A(pi52), .B(n369), .Z(n361));
+ AN2 U375 ( .A(pi51), .B(pi54), .Z(n359));
+ AN2 U376 ( .A(pi28), .B(pi31), .Z(n604));
+ AN2 U377 ( .A(n604), .B(pi55), .Z(n358));
+ AN2 U378 ( .A(n359), .B(n358), .Z(n602));
+ AN2 U379 ( .A(pi53), .B(n602), .Z(n360));
+ AN2 U380 ( .A(n361), .B(n360), .Z(n577));
+ IV2 U381 ( .A(pi20), .Z(n607));
+ OR2 U382 ( .A(n607), .B(pi25), .Z(n362));
+ IV2 U383 ( .A(n362), .Z(n365));
+ AN2 U384 ( .A(pi25), .B(n607), .Z(n363));
+ OR2 U385 ( .A(n365), .B(n363), .Z(n367));
+ AN2 U386 ( .A(pi41), .B(pi24), .Z(n378));
+ AN2 U387 ( .A(n346), .B(n378), .Z(n366));
+ AN2 U388 ( .A(n367), .B(n366), .Z(n373));
+ AN2 U389 ( .A(pi28), .B(pi54), .Z(n368));
+ AN2 U390 ( .A(pi20), .B(n368), .Z(n603));
+ AN2 U391 ( .A(pi08), .B(n603), .Z(n371));
+ IV2 U392 ( .A(pi56), .Z(n694));
+ IV2 U393 ( .A(n369), .Z(n692));
+ OR2 U394 ( .A(n694), .B(n692), .Z(n370));
+ AN2 U395 ( .A(n371), .B(n370), .Z(n372));
+ OR2 U396 ( .A(n373), .B(n372), .Z(n424));
+ AN2 U397 ( .A(pi14), .B(n424), .Z(n384));
+ AN2 U398 ( .A(pi56), .B(pi48), .Z(n608));
+ AN2 U399 ( .A(n608), .B(n346), .Z(n374));
+ AN2 U400 ( .A(pi07), .B(n374), .Z(n376));
+ IV2 U401 ( .A(pi43), .Z(n375));
+ AN2 U402 ( .A(n376), .B(n375), .Z(n406));
+ AN2 U403 ( .A(pi20), .B(n406), .Z(n403));
+ IV2 U404 ( .A(n378), .Z(n379));
+ AN2 U405 ( .A(n346), .B(n379), .Z(n407));
+ AN2 U406 ( .A(pi55), .B(n407), .Z(n399));
+ AN2 U407 ( .A(pi44), .B(n399), .Z(n381));
+ AN2 U408 ( .A(pi37), .B(pi54), .Z(n380));
+ OR2 U409 ( .A(n381), .B(n380), .Z(n382));
+ OR2 U410 ( .A(n403), .B(n382), .Z(n383));
+ OR2 U411 ( .A(n384), .B(n383), .Z(n436));
+ AN2 U412 ( .A(pi26), .B(n436), .Z(n385));
+ OR2 U413 ( .A(n577), .B(n385), .Z(n386));
+ AN2 U414 ( .A(pi34), .B(n386), .Z(n448));
+ AN2 U415 ( .A(pi43), .B(pi05), .Z(n388));
+ AN2 U416 ( .A(pi32), .B(n436), .Z(n387));
+ OR2 U417 ( .A(n388), .B(n387), .Z(n446));
+ AN2 U418 ( .A(pi08), .B(pi37), .Z(n393));
+ AN2 U419 ( .A(pi50), .B(n399), .Z(n390));
+ AN2 U420 ( .A(pi18), .B(n424), .Z(n389));
+ OR2 U421 ( .A(n390), .B(n389), .Z(n391));
+ OR2 U422 ( .A(n403), .B(n391), .Z(n392));
+ OR2 U423 ( .A(n393), .B(n392), .Z(n494));
+ AN2 U424 ( .A(pi27), .B(n494), .Z(n497));
+ OR2 U425 ( .A(pi27), .B(n494), .Z(n499));
+ AN2 U426 ( .A(pi20), .B(pi37), .Z(n398));
+ AN2 U427 ( .A(pi45), .B(n399), .Z(n395));
+ AN2 U428 ( .A(pi22), .B(n424), .Z(n394));
+ OR2 U429 ( .A(n395), .B(n394), .Z(n396));
+ OR2 U430 ( .A(n403), .B(n396), .Z(n397));
+ OR2 U431 ( .A(n398), .B(n397), .Z(n536));
+ AN2 U432 ( .A(pi17), .B(n536), .Z(n539));
+ OR2 U433 ( .A(pi17), .B(n536), .Z(n541));
+ AN2 U434 ( .A(pi23), .B(n424), .Z(n405));
+ AN2 U435 ( .A(pi30), .B(pi37), .Z(n401));
+ AN2 U436 ( .A(pi29), .B(n399), .Z(n400));
+ OR2 U437 ( .A(n401), .B(n400), .Z(n402));
+ OR2 U438 ( .A(n403), .B(n402), .Z(n404));
+ OR2 U439 ( .A(n405), .B(n404), .Z(n579));
+ AN2 U440 ( .A(pi21), .B(n579), .Z(n582));
+ OR2 U441 ( .A(pi21), .B(n579), .Z(n584));
+ AN2 U442 ( .A(n406), .B(pi55), .Z(n429));
+ IV2 U443 ( .A(pi28), .Z(n409));
+ AN2 U444 ( .A(n407), .B(pi20), .Z(n408));
+ OR2 U445 ( .A(n409), .B(n408), .Z(n423));
+ AN2 U446 ( .A(pi50), .B(n423), .Z(n411));
+ AN2 U447 ( .A(pi42), .B(n424), .Z(n410));
+ OR2 U448 ( .A(n411), .B(n410), .Z(n412));
+ OR2 U449 ( .A(n429), .B(n412), .Z(n514));
+ AN2 U450 ( .A(pi15), .B(n514), .Z(n517));
+ OR2 U451 ( .A(pi15), .B(n514), .Z(n519));
+ AN2 U452 ( .A(pi45), .B(n423), .Z(n414));
+ AN2 U453 ( .A(pi40), .B(n424), .Z(n413));
+ OR2 U454 ( .A(n414), .B(n413), .Z(n416));
+ OR2 U455 ( .A(n429), .B(n416), .Z(n556));
+ AN2 U456 ( .A(pi03), .B(n556), .Z(n559));
+ OR2 U457 ( .A(pi03), .B(n556), .Z(n561));
+ AN2 U458 ( .A(pi29), .B(n423), .Z(n418));
+ AN2 U459 ( .A(pi04), .B(n424), .Z(n417));
+ OR2 U460 ( .A(n418), .B(n417), .Z(n419));
+ OR2 U461 ( .A(n429), .B(n419), .Z(n471));
+ AN2 U462 ( .A(pi10), .B(n471), .Z(n480));
+ OR2 U463 ( .A(pi10), .B(n471), .Z(n482));
+ AN2 U464 ( .A(pi46), .B(n482), .Z(n420));
+ OR2 U465 ( .A(n480), .B(n420), .Z(n562));
+ AN2 U466 ( .A(n561), .B(n562), .Z(n421));
+ OR2 U467 ( .A(n559), .B(n421), .Z(n520));
+ AN2 U468 ( .A(n519), .B(n520), .Z(n422));
+ OR2 U469 ( .A(n517), .B(n422), .Z(n449));
+ AN2 U470 ( .A(pi44), .B(n423), .Z(n426));
+ AN2 U471 ( .A(pi49), .B(n424), .Z(n425));
+ OR2 U472 ( .A(n426), .B(n425), .Z(n428));
+ OR2 U473 ( .A(n429), .B(n428), .Z(n464));
+ AN2 U474 ( .A(n449), .B(n464), .Z(n432));
+ OR2 U475 ( .A(n449), .B(n464), .Z(n430));
+ AN2 U476 ( .A(pi09), .B(n430), .Z(n431));
+ OR2 U477 ( .A(n432), .B(n431), .Z(n585));
+ AN2 U478 ( .A(n584), .B(n585), .Z(n433));
+ OR2 U479 ( .A(n582), .B(n433), .Z(n542));
+ AN2 U480 ( .A(n541), .B(n542), .Z(n434));
+ OR2 U481 ( .A(n539), .B(n434), .Z(n500));
+ AN2 U482 ( .A(n499), .B(n500), .Z(n435));
+ OR2 U483 ( .A(n497), .B(n435), .Z(n597));
+ OR2 U484 ( .A(pi34), .B(n436), .Z(n598));
+ AN2 U485 ( .A(n436), .B(pi34), .Z(n600));
+ IV2 U486 ( .A(n600), .Z(n437));
+ AN2 U487 ( .A(n598), .B(n437), .Z(n442));
+ OR2 U488 ( .A(n597), .B(n442), .Z(n440));
+ AN2 U489 ( .A(n597), .B(n442), .Z(n438));
+ IV2 U490 ( .A(n438), .Z(n439));
+ AN2 U491 ( .A(n440), .B(n439), .Z(n441));
+ AN2 U492 ( .A(pi12), .B(n441), .Z(n444));
+ AN2 U493 ( .A(n442), .B(pi19), .Z(n443));
+ OR2 U494 ( .A(n444), .B(n443), .Z(n445));
+ OR2 U495 ( .A(n446), .B(n445), .Z(n447));
+ OR2 U496 ( .A(n448), .B(n447), .Z(n137));
+ IV2 U497 ( .A(n464), .Z(n459));
+ AN2 U498 ( .A(pi12), .B(n449), .Z(n456));
+ AN2 U499 ( .A(n459), .B(n456), .Z(n453));
+ IV2 U500 ( .A(n449), .Z(n450));
+ AN2 U501 ( .A(n450), .B(pi12), .Z(n451));
+ OR2 U502 ( .A(pi19), .B(n451), .Z(n458));
+ AN2 U503 ( .A(n464), .B(n458), .Z(n452));
+ OR2 U504 ( .A(n453), .B(n452), .Z(n455));
+ IV2 U505 ( .A(pi09), .Z(n612));
+ AN2 U506 ( .A(n455), .B(n612), .Z(n470));
+ OR2 U507 ( .A(pi26), .B(n456), .Z(n457));
+ AN2 U508 ( .A(n464), .B(n457), .Z(n462));
+ AN2 U509 ( .A(n459), .B(n458), .Z(n460));
+ OR2 U510 ( .A(n577), .B(n460), .Z(n461));
+ OR2 U511 ( .A(n462), .B(n461), .Z(n463));
+ AN2 U512 ( .A(pi09), .B(n463), .Z(n468));
+ AN2 U513 ( .A(pi23), .B(pi05), .Z(n466));
+ AN2 U514 ( .A(pi32), .B(n464), .Z(n465));
+ OR2 U515 ( .A(n466), .B(n465), .Z(n467));
+ OR2 U516 ( .A(n468), .B(n467), .Z(n469));
+ OR2 U517 ( .A(n470), .B(n469), .Z(n295));
+ AN2 U518 ( .A(pi26), .B(n480), .Z(n479));
+ AN2 U519 ( .A(pi40), .B(pi05), .Z(n473));
+ AN2 U520 ( .A(pi32), .B(n471), .Z(n472));
+ OR2 U521 ( .A(n473), .B(n472), .Z(n477));
+ AN2 U522 ( .A(pi38), .B(pi36), .Z(n475));
+ AN2 U523 ( .A(pi10), .B(n577), .Z(n474));
+ OR2 U524 ( .A(n475), .B(n474), .Z(n476));
+ OR2 U525 ( .A(n477), .B(n476), .Z(n478));
+ OR2 U526 ( .A(n479), .B(n478), .Z(n491));
+ IV2 U527 ( .A(n480), .Z(n481));
+ AN2 U528 ( .A(n482), .B(n481), .Z(n487));
+ OR2 U529 ( .A(pi46), .B(n487), .Z(n485));
+ AN2 U530 ( .A(pi46), .B(n487), .Z(n483));
+ IV2 U531 ( .A(n483), .Z(n484));
+ AN2 U532 ( .A(n485), .B(n484), .Z(n486));
+ AN2 U533 ( .A(pi12), .B(n486), .Z(n489));
+ AN2 U534 ( .A(n487), .B(pi19), .Z(n488));
+ OR2 U535 ( .A(n489), .B(n488), .Z(n490));
+ OR2 U536 ( .A(n491), .B(n490), .Z(n351));
+ AN2 U537 ( .A(pi26), .B(n494), .Z(n492));
+ OR2 U538 ( .A(n577), .B(n492), .Z(n493));
+ AN2 U539 ( .A(pi27), .B(n493), .Z(n511));
+ AN2 U540 ( .A(pi14), .B(pi05), .Z(n496));
+ AN2 U541 ( .A(pi32), .B(n494), .Z(n495));
+ OR2 U542 ( .A(n496), .B(n495), .Z(n509));
+ IV2 U543 ( .A(n497), .Z(n498));
+ AN2 U544 ( .A(n499), .B(n498), .Z(n505));
+ OR2 U545 ( .A(n500), .B(n505), .Z(n503));
+ AN2 U546 ( .A(n500), .B(n505), .Z(n501));
+ IV2 U547 ( .A(n501), .Z(n502));
+ AN2 U548 ( .A(n503), .B(n502), .Z(n504));
+ AN2 U549 ( .A(pi12), .B(n504), .Z(n507));
+ AN2 U550 ( .A(n505), .B(pi19), .Z(n506));
+ OR2 U551 ( .A(n507), .B(n506), .Z(n508));
+ OR2 U552 ( .A(n509), .B(n508), .Z(n510));
+ OR2 U553 ( .A(n511), .B(n510), .Z(n364));
+ AN2 U554 ( .A(pi26), .B(n514), .Z(n512));
+ OR2 U555 ( .A(n577), .B(n512), .Z(n513));
+ AN2 U556 ( .A(pi15), .B(n513), .Z(n533));
+ AN2 U557 ( .A(pi49), .B(pi05), .Z(n531));
+ AN2 U558 ( .A(pi33), .B(pi36), .Z(n516));
+ AN2 U559 ( .A(pi32), .B(n514), .Z(n515));
+ OR2 U560 ( .A(n516), .B(n515), .Z(n529));
+ IV2 U561 ( .A(n517), .Z(n518));
+ AN2 U562 ( .A(n519), .B(n518), .Z(n525));
+ OR2 U563 ( .A(n520), .B(n525), .Z(n523));
+ AN2 U564 ( .A(n520), .B(n525), .Z(n521));
+ IV2 U565 ( .A(n521), .Z(n522));
+ AN2 U566 ( .A(n523), .B(n522), .Z(n524));
+ AN2 U567 ( .A(pi12), .B(n524), .Z(n527));
+ AN2 U568 ( .A(n525), .B(pi19), .Z(n526));
+ OR2 U569 ( .A(n527), .B(n526), .Z(n528));
+ OR2 U570 ( .A(n529), .B(n528), .Z(n530));
+ OR2 U571 ( .A(n531), .B(n530), .Z(n532));
+ OR2 U572 ( .A(n533), .B(n532), .Z(n377));
+ AN2 U573 ( .A(pi26), .B(n536), .Z(n534));
+ OR2 U574 ( .A(n577), .B(n534), .Z(n535));
+ AN2 U575 ( .A(pi17), .B(n535), .Z(n553));
+ AN2 U576 ( .A(pi18), .B(pi05), .Z(n538));
+ AN2 U577 ( .A(pi32), .B(n536), .Z(n537));
+ OR2 U578 ( .A(n538), .B(n537), .Z(n551));
+ IV2 U579 ( .A(n539), .Z(n540));
+ AN2 U580 ( .A(n541), .B(n540), .Z(n547));
+ OR2 U581 ( .A(n542), .B(n547), .Z(n545));
+ AN2 U582 ( .A(n542), .B(n547), .Z(n543));
+ IV2 U583 ( .A(n543), .Z(n544));
+ AN2 U584 ( .A(n545), .B(n544), .Z(n546));
+ AN2 U585 ( .A(pi12), .B(n546), .Z(n549));
+ AN2 U586 ( .A(n547), .B(pi19), .Z(n548));
+ OR2 U587 ( .A(n549), .B(n548), .Z(n550));
+ OR2 U588 ( .A(n551), .B(n550), .Z(n552));
+ OR2 U589 ( .A(n553), .B(n552), .Z(n415));
+ AN2 U590 ( .A(pi26), .B(n556), .Z(n554));
+ OR2 U591 ( .A(n577), .B(n554), .Z(n555));
+ AN2 U592 ( .A(pi03), .B(n555), .Z(n575));
+ AN2 U593 ( .A(pi42), .B(pi05), .Z(n573));
+ AN2 U594 ( .A(pi47), .B(pi36), .Z(n558));
+ AN2 U595 ( .A(pi32), .B(n556), .Z(n557));
+ OR2 U596 ( .A(n558), .B(n557), .Z(n571));
+ IV2 U597 ( .A(n559), .Z(n560));
+ AN2 U598 ( .A(n561), .B(n560), .Z(n567));
+ OR2 U599 ( .A(n562), .B(n567), .Z(n565));
+ AN2 U600 ( .A(n562), .B(n567), .Z(n563));
+ IV2 U601 ( .A(n563), .Z(n564));
+ AN2 U602 ( .A(n565), .B(n564), .Z(n566));
+ AN2 U603 ( .A(pi12), .B(n566), .Z(n569));
+ AN2 U604 ( .A(n567), .B(pi19), .Z(n568));
+ OR2 U605 ( .A(n569), .B(n568), .Z(n570));
+ OR2 U606 ( .A(n571), .B(n570), .Z(n572));
+ OR2 U607 ( .A(n573), .B(n572), .Z(n574));
+ OR2 U608 ( .A(n575), .B(n574), .Z(n427));
+ AN2 U609 ( .A(pi26), .B(n579), .Z(n576));
+ OR2 U610 ( .A(n577), .B(n576), .Z(n578));
+ AN2 U611 ( .A(pi21), .B(n578), .Z(n596));
+ AN2 U612 ( .A(pi22), .B(pi05), .Z(n581));
+ AN2 U613 ( .A(pi32), .B(n579), .Z(n580));
+ OR2 U614 ( .A(n581), .B(n580), .Z(n594));
+ IV2 U615 ( .A(n582), .Z(n583));
+ AN2 U616 ( .A(n584), .B(n583), .Z(n590));
+ OR2 U617 ( .A(n585), .B(n590), .Z(n588));
+ AN2 U618 ( .A(n585), .B(n590), .Z(n586));
+ IV2 U619 ( .A(n586), .Z(n587));
+ AN2 U620 ( .A(n588), .B(n587), .Z(n589));
+ AN2 U621 ( .A(pi12), .B(n589), .Z(n592));
+ AN2 U622 ( .A(n590), .B(pi19), .Z(n591));
+ OR2 U623 ( .A(n592), .B(n591), .Z(n593));
+ OR2 U624 ( .A(n594), .B(n593), .Z(n595));
+ OR2 U625 ( .A(n596), .B(n595), .Z(n454));
+ AN2 U626 ( .A(n598), .B(n597), .Z(n599));
+ OR2 U627 ( .A(n600), .B(n599), .Z(po07));
+ OR2 U628 ( .A(pi58), .B(pi00), .Z(n609));
+ AN2 U629 ( .A(pi59), .B(n609), .Z(po24));
+ AN2 U630 ( .A(n602), .B(pi57), .Z(n601));
+ AN2 U631 ( .A(pi41), .B(n601), .Z(po13));
+ AN2 U632 ( .A(pi48), .B(n602), .Z(po08));
+ AN2 U633 ( .A(n603), .B(pi31), .Z(po03));
+ AN2 U634 ( .A(pi48), .B(pi16), .Z(n610));
+ AN2 U635 ( .A(pi25), .B(n610), .Z(po25));
+ AN2 U636 ( .A(pi11), .B(n604), .Z(n605));
+ IV2 U637 ( .A(n605), .Z(n606));
+ OR2 U638 ( .A(n607), .B(n606), .Z(n691));
+ OR2 U639 ( .A(po25), .B(n691), .Z(po02));
+ AN2 U640 ( .A(n608), .B(pi25), .Z(po10));
+ AN2 U641 ( .A(pi13), .B(n609), .Z(po12));
+ AN2 U642 ( .A(pi07), .B(n610), .Z(po14));
+ IV2 U643 ( .A(pi15), .Z(n611));
+ AN2 U644 ( .A(pi09), .B(n611), .Z(n614));
+ AN2 U645 ( .A(pi15), .B(n612), .Z(n613));
+ OR2 U646 ( .A(n614), .B(n613), .Z(n618));
+ IV2 U647 ( .A(pi35), .Z(n654));
+ OR2 U648 ( .A(n654), .B(pi06), .Z(n617));
+ IV2 U649 ( .A(pi06), .Z(n615));
+ OR2 U650 ( .A(n615), .B(pi35), .Z(n616));
+ AN2 U651 ( .A(n617), .B(n616), .Z(n619));
+ OR2 U652 ( .A(n618), .B(n619), .Z(n622));
+ AN2 U653 ( .A(n619), .B(n618), .Z(n620));
+ IV2 U654 ( .A(n620), .Z(n621));
+ AN2 U655 ( .A(n622), .B(n621), .Z(n628));
+ IV2 U656 ( .A(pi10), .Z(n624));
+ OR2 U657 ( .A(n624), .B(pi03), .Z(n623));
+ IV2 U658 ( .A(n623), .Z(n626));
+ AN2 U659 ( .A(pi03), .B(n624), .Z(n625));
+ OR2 U660 ( .A(n626), .B(n625), .Z(n627));
+ OR2 U661 ( .A(n628), .B(n627), .Z(n631));
+ AN2 U662 ( .A(n628), .B(n627), .Z(n629));
+ IV2 U663 ( .A(n629), .Z(n630));
+ AN2 U664 ( .A(n631), .B(n630), .Z(n637));
+ IV2 U665 ( .A(pi34), .Z(n632));
+ AN2 U666 ( .A(pi27), .B(n632), .Z(n635));
+ OR2 U667 ( .A(n632), .B(pi27), .Z(n633));
+ IV2 U668 ( .A(n633), .Z(n634));
+ OR2 U669 ( .A(n635), .B(n634), .Z(n636));
+ OR2 U670 ( .A(n637), .B(n636), .Z(n640));
+ AN2 U671 ( .A(n637), .B(n636), .Z(n638));
+ IV2 U672 ( .A(n638), .Z(n639));
+ AN2 U673 ( .A(n640), .B(n639), .Z(n647));
+ IV2 U674 ( .A(pi21), .Z(n642));
+ OR2 U675 ( .A(n642), .B(pi17), .Z(n641));
+ IV2 U676 ( .A(n641), .Z(n644));
+ AN2 U677 ( .A(pi17), .B(n642), .Z(n643));
+ OR2 U678 ( .A(n644), .B(n643), .Z(n646));
+ OR2 U679 ( .A(n647), .B(n646), .Z(n645));
+ IV2 U680 ( .A(n645), .Z(n649));
+ AN2 U681 ( .A(n647), .B(n646), .Z(n648));
+ OR2 U682 ( .A(n649), .B(n648), .Z(po15));
+ IV2 U683 ( .A(pi42), .Z(n650));
+ AN2 U684 ( .A(pi49), .B(n650), .Z(n653));
+ IV2 U685 ( .A(pi49), .Z(n651));
+ AN2 U686 ( .A(pi42), .B(n651), .Z(n652));
+ OR2 U687 ( .A(n653), .B(n652), .Z(n658));
+ OR2 U688 ( .A(n654), .B(pi39), .Z(n657));
+ IV2 U689 ( .A(pi39), .Z(n655));
+ OR2 U690 ( .A(n655), .B(pi35), .Z(n656));
+ AN2 U691 ( .A(n657), .B(n656), .Z(n659));
+ OR2 U692 ( .A(n658), .B(n659), .Z(n662));
+ AN2 U693 ( .A(n659), .B(n658), .Z(n660));
+ IV2 U694 ( .A(n660), .Z(n661));
+ AN2 U695 ( .A(n662), .B(n661), .Z(n668));
+ IV2 U696 ( .A(pi04), .Z(n664));
+ OR2 U697 ( .A(n664), .B(pi18), .Z(n663));
+ IV2 U698 ( .A(n663), .Z(n666));
+ AN2 U699 ( .A(pi18), .B(n664), .Z(n665));
+ OR2 U700 ( .A(n666), .B(n665), .Z(n667));
+ OR2 U701 ( .A(n668), .B(n667), .Z(n671));
+ AN2 U702 ( .A(n668), .B(n667), .Z(n669));
+ IV2 U703 ( .A(n669), .Z(n670));
+ AN2 U704 ( .A(n671), .B(n670), .Z(n677));
+ IV2 U705 ( .A(pi22), .Z(n673));
+ OR2 U706 ( .A(n673), .B(pi14), .Z(n672));
+ IV2 U707 ( .A(n672), .Z(n675));
+ AN2 U708 ( .A(pi14), .B(n673), .Z(n674));
+ OR2 U709 ( .A(n675), .B(n674), .Z(n676));
+ OR2 U710 ( .A(n677), .B(n676), .Z(n680));
+ AN2 U711 ( .A(n677), .B(n676), .Z(n678));
+ IV2 U712 ( .A(n678), .Z(n679));
+ AN2 U713 ( .A(n680), .B(n679), .Z(n687));
+ IV2 U714 ( .A(pi40), .Z(n682));
+ OR2 U715 ( .A(n682), .B(pi23), .Z(n681));
+ IV2 U716 ( .A(n681), .Z(n684));
+ AN2 U717 ( .A(pi23), .B(n682), .Z(n683));
+ OR2 U718 ( .A(n684), .B(n683), .Z(n686));
+ OR2 U719 ( .A(n687), .B(n686), .Z(n685));
+ IV2 U720 ( .A(n685), .Z(n689));
+ AN2 U721 ( .A(n687), .B(n686), .Z(n688));
+ OR2 U722 ( .A(n689), .B(n688), .Z(po20));
+ AN2 U723 ( .A(pi01), .B(pi02), .Z(po21));
+ IV2 U724 ( .A(po25), .Z(n690));
+ OR2 U725 ( .A(n691), .B(n690), .Z(po23));
+ IV2 U726 ( .A(pi16), .Z(n696));
+ OR2 U727 ( .A(n692), .B(n696), .Z(po11));
+ AN2 U728 ( .A(pi07), .B(pi41), .Z(n693));
+ IV2 U729 ( .A(n693), .Z(n695));
+ OR2 U730 ( .A(n694), .B(n695), .Z(po01));
+ OR2 U731 ( .A(n696), .B(n695), .Z(po05));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/C880.ys b/examples/smtbmc/glift/C880.ys
new file mode 100644
index 000000000..410768f21
--- /dev/null
+++ b/examples/smtbmc/glift/C880.ys
@@ -0,0 +1,41 @@
+read_verilog C880.v
+techmap
+flatten
+select C880_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename C880_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog C880.v
+techmap
+flatten
+select C880_lev2
+glift -create-precise-model
+techmap
+opt
+rename C880_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution C880.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file C880.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/alu2.v b/examples/smtbmc/glift/alu2.v
new file mode 100755
index 000000000..6b6e3d7af
--- /dev/null
+++ b/examples/smtbmc/glift/alu2.v
@@ -0,0 +1,400 @@
+module alu2_lev2(pi0, pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8, pi9,
+ po0, po1, po2, po3, po4, po5);
+
+input pi0, pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8, pi9;
+
+output po0, po1, po2, po3, po4, po5;
+
+wire n358, n359, n360, n361, n362, n363, n364, n365, n366, n367,
+ n368, n369, n370, n371, n372, n373, n374, n375, n376, n377,
+ n378, n379, n380, n381, n382, n383, n384, n385, n386, n387,
+ n388, n389, n390, n391, n392, n393, n394, n395, n396, n397,
+ n398, n399, n400, n401, n402, n403, n404, n405, n406, n407,
+ n408, n409, n410, n411, n412, n413, n414, n415, n416, n417,
+ n418, n419, n420, n421, n422, n423, n424, n425, n426, n427,
+ n428, n429, n430, n431, n432, n433, n434, n435, n436, n437,
+ n438, n439, n440, n441, n442, n443, n444, n445, n446, n447,
+ n448, n449, n450, n451, n452, n453, n454, n455, n456, n457,
+ n458, n459, n460, n461, n462, n463, n464, n465, n466, n467,
+ n468, n469, n470, n471, n472, n473, n474, n475, n476, n477,
+ n478, n479, n480, n481, n482, n483, n484, n485, n486, n487,
+ n488, n489, n490, n491, n492, n493, n494, n495, n496, n497,
+ n498, n499, n500, n501, n502, n503, n504, n505, n506, n507,
+ n508, n509, n510, n511, n512, n513, n514, n515, n516, n517,
+ n518, n519, n520, n521, n522, n523, n524, n525, n526, n527,
+ n528, n529, n530, n531, n532, n533, n534, n535, n536, n537,
+ n538, n539, n540, n541, n542, n543, n544, n545, n546, n547,
+ n548, n549, n550, n551, n552, n553, n554, n555, n556, n557,
+ n558, n559, n560, n561, n562, n563, n564, n565, n566, n567,
+ n568, n569, n570, n571, n572, n573, n574, n575, n576, n577,
+ n578, n579, n580, n581, n582, n583, n584, n585, n586, n587,
+ n588, n589, n590, n591, n592, n593, n594, n595, n596, n597,
+ n598, n599, n600, n601, n602, n603, n604, n605, n606, n607,
+ n608, n609, n610, n611, n612, n613, n614, n615, n616, n617,
+ n618, n619, n620, n621, n622, n623, n624, n625, n626, n627,
+ n628, n629, n630, n631, n632, n633, n634, n635, n636, n637,
+ n638, n639, n640, n641, n642, n643, n644, n645, n646, n647,
+ n648, n649, n650, n651, n652, n653, n654, n655, n656, n657,
+ n658, n659, n660, n661, n662, n663, n664, n665, n666, n667,
+ n668, n669, n670, n671, n672, n673, n674, n675, n676, n677,
+ n678, n679, n680, n681, n682, n683, n684, n685, n686, n687;
+
+ AN2 U363 ( .A(n358), .B(po2), .Z(po5));
+ OR2 U364 ( .A(n359), .B(n360), .Z(n358));
+ AN2 U365 ( .A(n361), .B(n362), .Z(n359));
+ AN2 U366 ( .A(pi9), .B(n363), .Z(po4));
+ OR2 U367 ( .A(n364), .B(n365), .Z(n363));
+ OR2 U368 ( .A(n366), .B(n367), .Z(n365));
+ AN2 U369 ( .A(pi6), .B(n368), .Z(n367));
+ OR2 U370 ( .A(n369), .B(n370), .Z(n368));
+ OR2 U371 ( .A(n371), .B(n372), .Z(n370));
+ OR2 U372 ( .A(n373), .B(n374), .Z(n372));
+ AN2 U373 ( .A(n375), .B(n376), .Z(n374));
+ AN2 U374 ( .A(n377), .B(n378), .Z(n375));
+ OR2 U375 ( .A(n379), .B(n380), .Z(n377));
+ OR2 U376 ( .A(n381), .B(n382), .Z(n380));
+ OR2 U377 ( .A(n383), .B(n384), .Z(n379));
+ AN2 U378 ( .A(n385), .B(pi5), .Z(n384));
+ AN2 U379 ( .A(n386), .B(n387), .Z(n383));
+ AN2 U380 ( .A(pi4), .B(n361), .Z(n386));
+ AN2 U381 ( .A(n388), .B(n389), .Z(n373));
+ OR2 U382 ( .A(n390), .B(n391), .Z(n388));
+ AN2 U383 ( .A(pi1), .B(n392), .Z(n390));
+ OR2 U384 ( .A(n393), .B(n394), .Z(n392));
+ OR2 U385 ( .A(pi7), .B(n395), .Z(n394));
+ AN2 U386 ( .A(n381), .B(n396), .Z(n395));
+ OR2 U387 ( .A(n397), .B(n398), .Z(n369));
+ AN2 U388 ( .A(n399), .B(n400), .Z(n398));
+ AN2 U389 ( .A(n387), .B(n401), .Z(n399));
+ AN2 U390 ( .A(n402), .B(n403), .Z(n397));
+ AN2 U391 ( .A(pi0), .B(n404), .Z(n402));
+ OR2 U392 ( .A(pi1), .B(n389), .Z(n404));
+ AN2 U393 ( .A(n405), .B(n406), .Z(n366));
+ OR2 U394 ( .A(n407), .B(n408), .Z(n406));
+ AN2 U395 ( .A(n360), .B(n409), .Z(n408));
+ OR2 U396 ( .A(n410), .B(n411), .Z(n409));
+ OR2 U397 ( .A(n412), .B(n413), .Z(n411));
+ AN2 U398 ( .A(n414), .B(pi3), .Z(n413));
+ AN2 U399 ( .A(n389), .B(n415), .Z(n410));
+ AN2 U400 ( .A(po3), .B(n416), .Z(n407));
+ OR2 U401 ( .A(n417), .B(n414), .Z(n416));
+ OR2 U402 ( .A(n418), .B(n419), .Z(n364));
+ OR2 U403 ( .A(n420), .B(n421), .Z(n419));
+ AN2 U404 ( .A(n422), .B(n382), .Z(n421));
+ AN2 U405 ( .A(pi7), .B(n389), .Z(n422));
+ AN2 U406 ( .A(n423), .B(n424), .Z(n418));
+ AN2 U407 ( .A(n425), .B(n426), .Z(n423));
+ OR2 U408 ( .A(n427), .B(po3), .Z(po2));
+ AN2 U409 ( .A(n428), .B(n429), .Z(n427));
+ OR2 U410 ( .A(n430), .B(n431), .Z(po1));
+ AN2 U411 ( .A(pi9), .B(n432), .Z(n431));
+ OR2 U412 ( .A(n433), .B(n434), .Z(n432));
+ OR2 U413 ( .A(n435), .B(n436), .Z(n434));
+ AN2 U414 ( .A(n437), .B(n438), .Z(n436));
+ IV2 U415 ( .A(n425), .Z(n438));
+ AN2 U416 ( .A(n424), .B(n426), .Z(n437));
+ OR2 U417 ( .A(n439), .B(n440), .Z(n424));
+ OR2 U418 ( .A(n441), .B(n442), .Z(n440));
+ AN2 U419 ( .A(n381), .B(n443), .Z(n442));
+ OR2 U420 ( .A(n444), .B(n445), .Z(n443));
+ AN2 U421 ( .A(n446), .B(n447), .Z(n441));
+ AN2 U422 ( .A(n387), .B(n361), .Z(n446));
+ AN2 U423 ( .A(n448), .B(n425), .Z(n435));
+ OR2 U424 ( .A(n449), .B(n450), .Z(n425));
+ OR2 U425 ( .A(n420), .B(n451), .Z(n450));
+ OR2 U426 ( .A(n452), .B(n453), .Z(n451));
+ AN2 U427 ( .A(pi6), .B(n454), .Z(n453));
+ OR2 U428 ( .A(n371), .B(n455), .Z(n454));
+ AN2 U429 ( .A(n376), .B(n456), .Z(n455));
+ OR2 U430 ( .A(n457), .B(n458), .Z(n456));
+ OR2 U431 ( .A(n459), .B(n460), .Z(n458));
+ AN2 U432 ( .A(n461), .B(n378), .Z(n460));
+ OR2 U433 ( .A(n462), .B(n463), .Z(n461));
+ AN2 U434 ( .A(n385), .B(n464), .Z(n462));
+ OR2 U435 ( .A(n465), .B(pi5), .Z(n464));
+ AN2 U436 ( .A(pi7), .B(n466), .Z(n459));
+ OR2 U437 ( .A(n467), .B(n468), .Z(n466));
+ OR2 U438 ( .A(n469), .B(n470), .Z(n468));
+ AN2 U439 ( .A(n381), .B(pi1), .Z(n470));
+ AN2 U440 ( .A(n471), .B(n428), .Z(n469));
+ AN2 U441 ( .A(pi0), .B(n387), .Z(n471));
+ AN2 U442 ( .A(n412), .B(n361), .Z(n467));
+ AN2 U443 ( .A(n472), .B(n473), .Z(n457));
+ AN2 U444 ( .A(n360), .B(n428), .Z(n472));
+ AN2 U445 ( .A(n463), .B(n428), .Z(n371));
+ AN2 U446 ( .A(n474), .B(n475), .Z(n452));
+ OR2 U447 ( .A(n476), .B(n477), .Z(n474));
+ OR2 U448 ( .A(n478), .B(n479), .Z(n477));
+ AN2 U449 ( .A(n480), .B(n428), .Z(n479));
+ AN2 U450 ( .A(n481), .B(n482), .Z(n480));
+ OR2 U451 ( .A(n360), .B(n389), .Z(n482));
+ OR2 U452 ( .A(n401), .B(n483), .Z(n481));
+ AN2 U453 ( .A(pi7), .B(n484), .Z(n483));
+ OR2 U454 ( .A(n393), .B(n485), .Z(n484));
+ AN2 U455 ( .A(n376), .B(n415), .Z(n485));
+ AN2 U456 ( .A(n414), .B(n429), .Z(n393));
+ AN2 U457 ( .A(n486), .B(n378), .Z(n478));
+ OR2 U458 ( .A(n412), .B(n389), .Z(n486));
+ AN2 U459 ( .A(n487), .B(pi1), .Z(n412));
+ OR2 U460 ( .A(n488), .B(n489), .Z(n476));
+ AN2 U461 ( .A(n490), .B(n401), .Z(n488));
+ AN2 U462 ( .A(pi1), .B(n429), .Z(n490));
+ AN2 U463 ( .A(n385), .B(n491), .Z(n420));
+ IV2 U464 ( .A(n492), .Z(n491));
+ OR2 U465 ( .A(n493), .B(n487), .Z(n492));
+ AN2 U466 ( .A(n494), .B(n495), .Z(n493));
+ OR2 U467 ( .A(pi6), .B(n389), .Z(n495));
+ OR2 U468 ( .A(pi7), .B(pi1), .Z(n494));
+ OR2 U469 ( .A(n496), .B(n497), .Z(n449));
+ AN2 U470 ( .A(n498), .B(n376), .Z(n497));
+ AN2 U471 ( .A(n381), .B(n382), .Z(n498));
+ AN2 U472 ( .A(n499), .B(n389), .Z(n496));
+ OR2 U473 ( .A(n500), .B(n501), .Z(n499));
+ OR2 U474 ( .A(n502), .B(n503), .Z(n501));
+ AN2 U475 ( .A(n385), .B(n504), .Z(n503));
+ OR2 U476 ( .A(n505), .B(n506), .Z(n504));
+ AN2 U477 ( .A(po3), .B(n400), .Z(n506));
+ AN2 U478 ( .A(n507), .B(n428), .Z(n505));
+ AN2 U479 ( .A(n508), .B(n387), .Z(n502));
+ OR2 U480 ( .A(n509), .B(n510), .Z(n508));
+ OR2 U481 ( .A(n489), .B(n511), .Z(n510));
+ OR2 U482 ( .A(n465), .B(n512), .Z(n511));
+ AN2 U483 ( .A(n513), .B(pi1), .Z(n512));
+ AN2 U484 ( .A(pi0), .B(n514), .Z(n513));
+ OR2 U485 ( .A(n507), .B(n515), .Z(n514));
+ AN2 U486 ( .A(n361), .B(n428), .Z(n465));
+ AN2 U487 ( .A(po3), .B(n360), .Z(n489));
+ OR2 U488 ( .A(n516), .B(n517), .Z(n509));
+ OR2 U489 ( .A(n518), .B(n519), .Z(n517));
+ AN2 U490 ( .A(n391), .B(n362), .Z(n519));
+ AN2 U491 ( .A(n428), .B(n400), .Z(n391));
+ AN2 U492 ( .A(n520), .B(n521), .Z(n518));
+ OR2 U493 ( .A(n522), .B(n362), .Z(n521));
+ AN2 U494 ( .A(n429), .B(n523), .Z(n520));
+ AN2 U495 ( .A(n417), .B(n378), .Z(n516));
+ AN2 U496 ( .A(n522), .B(n382), .Z(n500));
+ AN2 U497 ( .A(pi1), .B(n396), .Z(n382));
+ AN2 U498 ( .A(n361), .B(n378), .Z(n522));
+ OR2 U499 ( .A(n524), .B(n525), .Z(n448));
+ OR2 U500 ( .A(n526), .B(n527), .Z(n525));
+ OR2 U501 ( .A(pi8), .B(n528), .Z(n524));
+ AN2 U502 ( .A(n529), .B(n530), .Z(n430));
+ OR2 U503 ( .A(n531), .B(n532), .Z(n529));
+ OR2 U504 ( .A(n533), .B(n534), .Z(n532));
+ OR2 U505 ( .A(n535), .B(n536), .Z(n534));
+ AN2 U506 ( .A(n537), .B(n376), .Z(n536));
+ IV2 U507 ( .A(n389), .Z(n376));
+ AN2 U508 ( .A(n538), .B(n389), .Z(n535));
+ OR2 U509 ( .A(n539), .B(n540), .Z(n389));
+ OR2 U510 ( .A(n541), .B(n542), .Z(n540));
+ OR2 U511 ( .A(n543), .B(n544), .Z(n542));
+ AN2 U512 ( .A(pi1), .B(n545), .Z(n544));
+ AN2 U513 ( .A(n546), .B(n428), .Z(n543));
+ AN2 U514 ( .A(n547), .B(n548), .Z(n546));
+ OR2 U515 ( .A(pi3), .B(n396), .Z(n548));
+ AN2 U516 ( .A(pi9), .B(n549), .Z(n541));
+ OR2 U517 ( .A(n550), .B(n551), .Z(n549));
+ OR2 U518 ( .A(n552), .B(n553), .Z(n551));
+ AN2 U519 ( .A(n554), .B(n507), .Z(n553));
+ AN2 U520 ( .A(n396), .B(pi0), .Z(n554));
+ AN2 U521 ( .A(n555), .B(n556), .Z(n552));
+ AN2 U522 ( .A(n557), .B(n415), .Z(n556));
+ AN2 U523 ( .A(po3), .B(n558), .Z(n555));
+ OR2 U524 ( .A(n559), .B(n560), .Z(n550));
+ AN2 U525 ( .A(n561), .B(n429), .Z(n560));
+ AN2 U526 ( .A(n417), .B(n562), .Z(n561));
+ OR2 U527 ( .A(n563), .B(n564), .Z(n562));
+ AN2 U528 ( .A(n558), .B(n428), .Z(n564));
+ AN2 U529 ( .A(pi1), .B(n565), .Z(n563));
+ AN2 U530 ( .A(pi3), .B(n566), .Z(n559));
+ OR2 U531 ( .A(n567), .B(n414), .Z(n566));
+ AN2 U532 ( .A(n568), .B(n569), .Z(n567));
+ AN2 U533 ( .A(n565), .B(n428), .Z(n568));
+ OR2 U534 ( .A(n570), .B(n571), .Z(n539));
+ AN2 U535 ( .A(n572), .B(n429), .Z(n571));
+ AN2 U536 ( .A(po3), .B(n573), .Z(n570));
+ OR2 U537 ( .A(n574), .B(n575), .Z(n538));
+ OR2 U538 ( .A(n445), .B(n576), .Z(n575));
+ AN2 U539 ( .A(n577), .B(pi3), .Z(n576));
+ AN2 U540 ( .A(n578), .B(pi1), .Z(n574));
+ AN2 U541 ( .A(n507), .B(pi1), .Z(n533));
+ OR2 U542 ( .A(n579), .B(n580), .Z(n531));
+ OR2 U543 ( .A(n581), .B(n582), .Z(n580));
+ AN2 U544 ( .A(n444), .B(po3), .Z(n582));
+ AN2 U545 ( .A(pi1), .B(pi3), .Z(po3));
+ AN2 U546 ( .A(n583), .B(n557), .Z(n581));
+ AN2 U547 ( .A(n584), .B(n429), .Z(n583));
+ OR2 U548 ( .A(n585), .B(n414), .Z(n584));
+ AN2 U549 ( .A(n417), .B(n428), .Z(n585));
+ AN2 U550 ( .A(n586), .B(pi7), .Z(n579));
+ AN2 U551 ( .A(n587), .B(n588), .Z(n586));
+ OR2 U552 ( .A(pi3), .B(n589), .Z(n588));
+ AN2 U553 ( .A(pi1), .B(n523), .Z(n589));
+ OR2 U554 ( .A(n429), .B(n590), .Z(n587));
+ OR2 U555 ( .A(n417), .B(n591), .Z(n590));
+ AN2 U556 ( .A(n592), .B(n428), .Z(n591));
+ IV2 U557 ( .A(pi1), .Z(n428));
+ IV2 U558 ( .A(pi3), .Z(n429));
+ OR2 U559 ( .A(n593), .B(n594), .Z(po0));
+ OR2 U560 ( .A(n595), .B(n596), .Z(n594));
+ AN2 U561 ( .A(n597), .B(pi8), .Z(n596));
+ AN2 U562 ( .A(n598), .B(n381), .Z(n597));
+ AN2 U563 ( .A(pi0), .B(n385), .Z(n381));
+ AN2 U564 ( .A(n507), .B(n487), .Z(n598));
+ AN2 U565 ( .A(n528), .B(n426), .Z(n595));
+ AN2 U566 ( .A(pi6), .B(n599), .Z(n528));
+ IV2 U567 ( .A(n600), .Z(n599));
+ OR2 U568 ( .A(n601), .B(n361), .Z(n600));
+ AN2 U569 ( .A(n602), .B(n603), .Z(n601));
+ AN2 U570 ( .A(n604), .B(n605), .Z(n603));
+ OR2 U571 ( .A(pi7), .B(n606), .Z(n605));
+ OR2 U572 ( .A(n607), .B(n387), .Z(n606));
+ OR2 U573 ( .A(n378), .B(n487), .Z(n604));
+ AN2 U574 ( .A(n608), .B(n609), .Z(n602));
+ OR2 U575 ( .A(pi2), .B(n415), .Z(n608));
+ OR2 U576 ( .A(n610), .B(n611), .Z(n593));
+ AN2 U577 ( .A(pi9), .B(n612), .Z(n611));
+ OR2 U578 ( .A(n613), .B(n614), .Z(n612));
+ OR2 U579 ( .A(n433), .B(n615), .Z(n614));
+ AN2 U580 ( .A(n527), .B(n426), .Z(n615));
+ OR2 U581 ( .A(n616), .B(n617), .Z(n527));
+ AN2 U582 ( .A(n618), .B(n361), .Z(n617));
+ OR2 U583 ( .A(n619), .B(n620), .Z(n618));
+ OR2 U584 ( .A(n621), .B(n622), .Z(n620));
+ AN2 U585 ( .A(n592), .B(n362), .Z(n622));
+ AN2 U586 ( .A(n385), .B(n623), .Z(n621));
+ OR2 U587 ( .A(n624), .B(n625), .Z(n623));
+ AN2 U588 ( .A(n626), .B(n415), .Z(n625));
+ AN2 U589 ( .A(n507), .B(n523), .Z(n624));
+ AN2 U590 ( .A(n473), .B(n557), .Z(n619));
+ AN2 U591 ( .A(n523), .B(n387), .Z(n473));
+ AN2 U592 ( .A(n569), .B(n387), .Z(n616));
+ AN2 U593 ( .A(n578), .B(n627), .Z(n433));
+ AN2 U594 ( .A(n378), .B(n475), .Z(n627));
+ OR2 U595 ( .A(n628), .B(n629), .Z(n613));
+ AN2 U596 ( .A(n526), .B(n426), .Z(n629));
+ IV2 U597 ( .A(pi8), .Z(n426));
+ AN2 U598 ( .A(n360), .B(n405), .Z(n526));
+ AN2 U599 ( .A(pi8), .B(n630), .Z(n628));
+ OR2 U600 ( .A(n631), .B(n439), .Z(n630));
+ OR2 U601 ( .A(n632), .B(n633), .Z(n439));
+ OR2 U602 ( .A(n634), .B(n635), .Z(n633));
+ AN2 U603 ( .A(n636), .B(n378), .Z(n635));
+ OR2 U604 ( .A(n637), .B(n360), .Z(n636));
+ AN2 U605 ( .A(n387), .B(n475), .Z(n637));
+ AN2 U606 ( .A(n638), .B(n475), .Z(n634));
+ OR2 U607 ( .A(n639), .B(n640), .Z(n638));
+ AN2 U608 ( .A(n558), .B(pi4), .Z(n639));
+ OR2 U609 ( .A(n463), .B(n641), .Z(n632));
+ AN2 U610 ( .A(n642), .B(n385), .Z(n641));
+ AN2 U611 ( .A(n557), .B(n361), .Z(n642));
+ AN2 U612 ( .A(n361), .B(n578), .Z(n463));
+ AN2 U613 ( .A(n403), .B(n361), .Z(n631));
+ IV2 U614 ( .A(n609), .Z(n403));
+ OR2 U615 ( .A(n385), .B(n378), .Z(n609));
+ AN2 U616 ( .A(n643), .B(n530), .Z(n610));
+ OR2 U617 ( .A(n644), .B(n645), .Z(n643));
+ OR2 U618 ( .A(n646), .B(n647), .Z(n645));
+ OR2 U619 ( .A(n648), .B(n649), .Z(n647));
+ AN2 U620 ( .A(n537), .B(n385), .Z(n649));
+ IV2 U621 ( .A(n387), .Z(n385));
+ OR2 U622 ( .A(n650), .B(n651), .Z(n537));
+ AN2 U623 ( .A(n396), .B(pi6), .Z(n651));
+ AN2 U624 ( .A(n400), .B(n475), .Z(n650));
+ AN2 U625 ( .A(n652), .B(n387), .Z(n648));
+ OR2 U626 ( .A(n653), .B(n654), .Z(n387));
+ OR2 U627 ( .A(n655), .B(n656), .Z(n654));
+ OR2 U628 ( .A(n657), .B(n658), .Z(n656));
+ AN2 U629 ( .A(n360), .B(n573), .Z(n658));
+ OR2 U630 ( .A(n659), .B(n660), .Z(n573));
+ AN2 U631 ( .A(n405), .B(n578), .Z(n660));
+ AN2 U632 ( .A(n396), .B(n661), .Z(n659));
+ OR2 U633 ( .A(n405), .B(n557), .Z(n661));
+ AN2 U634 ( .A(n475), .B(pi7), .Z(n405));
+ IV2 U635 ( .A(n607), .Z(n396));
+ OR2 U636 ( .A(pi5), .B(pi4), .Z(n607));
+ AN2 U637 ( .A(n640), .B(n417), .Z(n657));
+ AN2 U638 ( .A(n572), .B(n362), .Z(n655));
+ OR2 U639 ( .A(n662), .B(n663), .Z(n572));
+ OR2 U640 ( .A(n664), .B(n665), .Z(n663));
+ AN2 U641 ( .A(n578), .B(n557), .Z(n665));
+ AN2 U642 ( .A(n417), .B(n626), .Z(n664));
+ AN2 U643 ( .A(n507), .B(n530), .Z(n662));
+ OR2 U644 ( .A(n666), .B(n667), .Z(n653));
+ OR2 U645 ( .A(n668), .B(n669), .Z(n667));
+ AN2 U646 ( .A(n670), .B(n545), .Z(n669));
+ OR2 U647 ( .A(n400), .B(n671), .Z(n545));
+ AN2 U648 ( .A(pi9), .B(n414), .Z(n671));
+ AN2 U649 ( .A(n378), .B(n414), .Z(n400));
+ IV2 U650 ( .A(pi7), .Z(n378));
+ OR2 U651 ( .A(pi0), .B(pi2), .Z(n670));
+ AN2 U652 ( .A(n672), .B(n547), .Z(n668));
+ AN2 U653 ( .A(n475), .B(n530), .Z(n547));
+ IV2 U654 ( .A(pi9), .Z(n530));
+ AN2 U655 ( .A(n361), .B(n415), .Z(n672));
+ AN2 U656 ( .A(n558), .B(n569), .Z(n666));
+ AN2 U657 ( .A(n557), .B(n417), .Z(n569));
+ OR2 U658 ( .A(n673), .B(n674), .Z(n652));
+ OR2 U659 ( .A(n445), .B(n675), .Z(n674));
+ AN2 U660 ( .A(n577), .B(pi2), .Z(n675));
+ AN2 U661 ( .A(n523), .B(n447), .Z(n445));
+ OR2 U662 ( .A(n577), .B(n507), .Z(n447));
+ AN2 U663 ( .A(n475), .B(n415), .Z(n577));
+ AN2 U664 ( .A(n578), .B(pi0), .Z(n673));
+ IV2 U665 ( .A(n487), .Z(n578));
+ OR2 U666 ( .A(n415), .B(n523), .Z(n487));
+ AN2 U667 ( .A(n507), .B(pi0), .Z(n646));
+ AN2 U668 ( .A(pi6), .B(pi7), .Z(n507));
+ OR2 U669 ( .A(n676), .B(n677), .Z(n644));
+ OR2 U670 ( .A(n678), .B(n679), .Z(n677));
+ AN2 U671 ( .A(n444), .B(n360), .Z(n679));
+ IV2 U672 ( .A(n401), .Z(n360));
+ OR2 U673 ( .A(n362), .B(n361), .Z(n401));
+ AN2 U674 ( .A(pi6), .B(n417), .Z(n444));
+ AN2 U675 ( .A(n680), .B(n557), .Z(n678));
+ IV2 U676 ( .A(n626), .Z(n557));
+ OR2 U677 ( .A(pi7), .B(n475), .Z(n626));
+ AN2 U678 ( .A(n681), .B(n362), .Z(n680));
+ OR2 U679 ( .A(n682), .B(n414), .Z(n681));
+ AN2 U680 ( .A(n417), .B(n361), .Z(n682));
+ IV2 U681 ( .A(pi0), .Z(n361));
+ AN2 U682 ( .A(pi7), .B(n683), .Z(n676));
+ OR2 U683 ( .A(n684), .B(n685), .Z(n683));
+ OR2 U684 ( .A(n686), .B(n687), .Z(n685));
+ AN2 U685 ( .A(n592), .B(n558), .Z(n687));
+ IV2 U686 ( .A(n565), .Z(n558));
+ OR2 U687 ( .A(pi0), .B(n362), .Z(n565));
+ AN2 U688 ( .A(n475), .B(n414), .Z(n592));
+ IV2 U689 ( .A(n515), .Z(n414));
+ OR2 U690 ( .A(pi5), .B(n415), .Z(n515));
+ IV2 U691 ( .A(pi6), .Z(n475));
+ AN2 U692 ( .A(n640), .B(n523), .Z(n686));
+ IV2 U693 ( .A(pi5), .Z(n523));
+ AN2 U694 ( .A(n362), .B(pi0), .Z(n640));
+ IV2 U695 ( .A(pi2), .Z(n362));
+ AN2 U696 ( .A(n417), .B(pi2), .Z(n684));
+ AN2 U697 ( .A(n415), .B(pi5), .Z(n417));
+ IV2 U698 ( .A(pi4), .Z(n415));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/alu2.ys b/examples/smtbmc/glift/alu2.ys
new file mode 100644
index 000000000..b1671752e
--- /dev/null
+++ b/examples/smtbmc/glift/alu2.ys
@@ -0,0 +1,41 @@
+read_verilog alu2.v
+techmap
+flatten
+select alu2_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename alu2_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog alu2.v
+techmap
+flatten
+select alu2_lev2
+glift -create-precise-model
+techmap
+opt
+rename alu2_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution alu2.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file alu2.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/alu4.v b/examples/smtbmc/glift/alu4.v
new file mode 100755
index 000000000..e110612e5
--- /dev/null
+++ b/examples/smtbmc/glift/alu4.v
@@ -0,0 +1,802 @@
+module alu4_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, po0, po1, po2, po3, po4, po5, po6, po7);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13;
+
+output po0, po1, po2, po3, po4, po5, po6, po7;
+
+wire n705, n706, n707, n708, n709, n710, n711, n712, n713, n714,
+ n715, n716, n717, n718, n719, n720, n721, n722, n723, n724,
+ n725, n726, n727, n728, n729, n730, n731, n732, n733, n734,
+ n735, n736, n737, n738, n739, n740, n741, n742, n743, n744,
+ n745, n746, n747, n748, n749, n750, n751, n752, n753, n754,
+ n755, n756, n757, n758, n759, n760, n761, n762, n763, n764,
+ n765, n766, n767, n768, n769, n770, n771, n772, n773, n774,
+ n775, n776, n777, n778, n779, n780, n781, n782, n783, n784,
+ n785, n786, n787, n788, n789, n790, n791, n792, n793, n794,
+ n795, n796, n797, n798, n799, n800, n801, n802, n803, n804,
+ n805, n806, n807, n808, n809, n810, n811, n812, n813, n814,
+ n815, n816, n817, n818, n819, n820, n821, n822, n823, n824,
+ n825, n826, n827, n828, n829, n830, n831, n832, n833, n834,
+ n835, n836, n837, n838, n839, n840, n841, n842, n843, n844,
+ n845, n846, n847, n848, n849, n850, n851, n852, n853, n854,
+ n855, n856, n857, n858, n859, n860, n861, n862, n863, n864,
+ n865, n866, n867, n868, n869, n870, n871, n872, n873, n874,
+ n875, n876, n877, n878, n879, n880, n881, n882, n883, n884,
+ n885, n886, n887, n888, n889, n890, n891, n892, n893, n894,
+ n895, n896, n897, n898, n899, n900, n901, n902, n903, n904,
+ n905, n906, n907, n908, n909, n910, n911, n912, n913, n914,
+ n915, n916, n917, n918, n919, n920, n921, n922, n923, n924,
+ n925, n926, n927, n928, n929, n930, n931, n932, n933, n934,
+ n935, n936, n937, n938, n939, n940, n941, n942, n943, n944,
+ n945, n946, n947, n948, n949, n950, n951, n952, n953, n954,
+ n955, n956, n957, n958, n959, n960, n961, n962, n963, n964,
+ n965, n966, n967, n968, n969, n970, n971, n972, n973, n974,
+ n975, n976, n977, n978, n979, n980, n981, n982, n983, n984,
+ n985, n986, n987, n988, n989, n990, n991, n992, n993, n994,
+ n995, n996, n997, n998, n999, n1000, n1001, n1002, n1003, n1004,
+ n1005, n1006, n1007, n1008, n1009, n1010, n1011, n1012, n1013, n1014,
+ n1015, n1016, n1017, n1018, n1019, n1020, n1021, n1022, n1023, n1024,
+ n1025, n1026, n1027, n1028, n1029, n1030, n1031, n1032, n1033, n1034,
+ n1035, n1036, n1037, n1038, n1039, n1040, n1041, n1042, n1043, n1044,
+ n1045, n1046, n1047, n1048, n1049, n1050, n1051, n1052, n1053, n1054,
+ n1055, n1056, n1057, n1058, n1059, n1060, n1061, n1062, n1063, n1064,
+ n1065, n1066, n1067, n1068, n1069, n1070, n1071, n1072, n1073, n1074,
+ n1075, n1076, n1077, n1078, n1079, n1080, n1081, n1082, n1083, n1084,
+ n1085, n1086, n1087, n1088, n1089, n1090, n1091, n1092, n1093, n1094,
+ n1095, n1096, n1097, n1098, n1099, n1100, n1101, n1102, n1103, n1104,
+ n1105, n1106, n1107, n1108, n1109, n1110, n1111, n1112, n1113, n1114,
+ n1115, n1116, n1117, n1118, n1119, n1120, n1121, n1122, n1123, n1124,
+ n1125, n1126, n1127, n1128, n1129, n1130, n1131, n1132, n1133, n1134,
+ n1135, n1136, n1137, n1138, n1139, n1140, n1141, n1142, n1143, n1144,
+ n1145, n1146, n1147, n1148, n1149, n1150, n1151, n1152, n1153, n1154,
+ n1155, n1156, n1157, n1158, n1159, n1160, n1161, n1162, n1163, n1164,
+ n1165, n1166, n1167, n1168, n1169, n1170, n1171, n1172, n1173, n1174,
+ n1175, n1176, n1177, n1178, n1179, n1180, n1181, n1182, n1183, n1184,
+ n1185, n1186, n1187, n1188, n1189, n1190, n1191, n1192, n1193, n1194,
+ n1195, n1196, n1197, n1198, n1199, n1200, n1201, n1202, n1203, n1204,
+ n1205, n1206, n1207, n1208, n1209, n1210, n1211, n1212, n1213, n1214,
+ n1215, n1216, n1217, n1218, n1219, n1220, n1221, n1222, n1223, n1224,
+ n1225, n1226, n1227, n1228, n1229, n1230, n1231, n1232, n1233, n1234,
+ n1235, n1236, n1237, n1238, n1239, n1240, n1241, n1242, n1243, n1244,
+ n1245, n1246, n1247, n1248, n1249, n1250, n1251, n1252, n1253, n1254,
+ n1255, n1256, n1257, n1258, n1259, n1260, n1261, n1262, n1263, n1264,
+ n1265, n1266, n1267, n1268, n1269, n1270, n1271, n1272, n1273, n1274,
+ n1275, n1276, n1277, n1278, n1279, n1280, n1281, n1282, n1283, n1284,
+ n1285, n1286, n1287, n1288, n1289, n1290, n1291, n1292, n1293, n1294,
+ n1295, n1296, n1297, n1298, n1299, n1300, n1301, n1302, n1303, n1304,
+ n1305, n1306, n1307, n1308, n1309, n1310, n1311, n1312, n1313, n1314,
+ n1315, n1316, n1317, n1318, n1319, n1320, n1321, n1322, n1323, n1324,
+ n1325, n1326, n1327, n1328, n1329, n1330, n1331, n1332, n1333, n1334,
+ n1335, n1336, n1337, n1338, n1339, n1340, n1341, n1342, n1343, n1344,
+ n1345, n1346, n1347, n1348, n1349, n1350, n1351, n1352, n1353, n1354,
+ n1355, n1356, n1357, n1358, n1359, n1360, n1361, n1362, n1363, n1364,
+ n1365, n1366, n1367, n1368, n1369, n1370, n1371, n1372, n1373, n1374,
+ n1375, n1376, n1377, n1378, n1379, n1380, n1381, n1382, n1383, n1384,
+ n1385, n1386, n1387, n1388, n1389, n1390, n1391, n1392, n1393, n1394,
+ n1395, n1396;
+
+ AN2 U712 ( .A(n705), .B(po4), .Z(po7));
+ OR2 U713 ( .A(n706), .B(n707), .Z(n705));
+ AN2 U714 ( .A(n708), .B(n709), .Z(n707));
+ OR2 U715 ( .A(n710), .B(n711), .Z(n708));
+ AN2 U716 ( .A(n712), .B(n713), .Z(n711));
+ AN2 U717 ( .A(n714), .B(n715), .Z(n710));
+ AN2 U718 ( .A(n716), .B(n717), .Z(n714));
+ AN2 U719 ( .A(n718), .B(n719), .Z(n706));
+ OR2 U720 ( .A(n720), .B(n712), .Z(n719));
+ OR2 U721 ( .A(n721), .B(n722), .Z(n712));
+ AN2 U722 ( .A(n723), .B(n724), .Z(n722));
+ AN2 U723 ( .A(n725), .B(n726), .Z(n721));
+ OR2 U724 ( .A(n724), .B(n727), .Z(n726));
+ AN2 U725 ( .A(n727), .B(n723), .Z(n720));
+ OR2 U726 ( .A(n728), .B(n729), .Z(po6));
+ AN2 U727 ( .A(pi13), .B(n730), .Z(n729));
+ OR2 U728 ( .A(n731), .B(n732), .Z(n730));
+ OR2 U729 ( .A(n733), .B(n734), .Z(n732));
+ OR2 U730 ( .A(n735), .B(n736), .Z(n734));
+ AN2 U731 ( .A(n737), .B(n738), .Z(n736));
+ OR2 U732 ( .A(n739), .B(n740), .Z(n737));
+ OR2 U733 ( .A(n741), .B(n742), .Z(n740));
+ AN2 U734 ( .A(n743), .B(n744), .Z(n742));
+ OR2 U735 ( .A(n745), .B(n746), .Z(n743));
+ AN2 U736 ( .A(pi03), .B(n747), .Z(n745));
+ AN2 U737 ( .A(n748), .B(n749), .Z(n741));
+ AN2 U738 ( .A(n750), .B(n751), .Z(n748));
+ AN2 U739 ( .A(pi11), .B(n752), .Z(n735));
+ OR2 U740 ( .A(n753), .B(n754), .Z(n752));
+ OR2 U741 ( .A(n755), .B(n756), .Z(n754));
+ AN2 U742 ( .A(n757), .B(n747), .Z(n756));
+ OR2 U743 ( .A(n758), .B(n759), .Z(n757));
+ IV2 U744 ( .A(n760), .Z(n755));
+ AN2 U745 ( .A(n761), .B(n762), .Z(n753));
+ OR2 U746 ( .A(n763), .B(po5), .Z(n762));
+ AN2 U747 ( .A(n764), .B(n765), .Z(n763));
+ AN2 U748 ( .A(n766), .B(n767), .Z(n733));
+ OR2 U749 ( .A(n768), .B(n769), .Z(n767));
+ AN2 U750 ( .A(n770), .B(n771), .Z(n768));
+ IV2 U751 ( .A(n772), .Z(n766));
+ OR2 U752 ( .A(n773), .B(n774), .Z(n731));
+ AN2 U753 ( .A(n775), .B(n776), .Z(n774));
+ AN2 U754 ( .A(n777), .B(n778), .Z(n775));
+ AN2 U755 ( .A(n779), .B(n780), .Z(n773));
+ AN2 U756 ( .A(n781), .B(n782), .Z(n779));
+ AN2 U757 ( .A(n783), .B(n781), .Z(n728));
+ AN2 U758 ( .A(n782), .B(n784), .Z(n783));
+ OR2 U759 ( .A(n785), .B(n786), .Z(po3));
+ OR2 U760 ( .A(n787), .B(n788), .Z(n786));
+ OR2 U761 ( .A(n789), .B(n790), .Z(n788));
+ OR2 U762 ( .A(n791), .B(n792), .Z(n790));
+ AN2 U763 ( .A(n793), .B(n782), .Z(n792));
+ AN2 U764 ( .A(n794), .B(n795), .Z(n791));
+ OR2 U765 ( .A(n796), .B(n797), .Z(n789));
+ IV2 U766 ( .A(n798), .Z(n797));
+ OR2 U767 ( .A(n799), .B(n778), .Z(n798));
+ AN2 U768 ( .A(n778), .B(n799), .Z(n796));
+ OR2 U769 ( .A(n800), .B(n801), .Z(n799));
+ IV2 U770 ( .A(n802), .Z(n778));
+ OR2 U771 ( .A(n803), .B(n804), .Z(n802));
+ AN2 U772 ( .A(n805), .B(n806), .Z(n803));
+ AN2 U773 ( .A(n807), .B(n808), .Z(n806));
+ AN2 U774 ( .A(n809), .B(n810), .Z(n808));
+ OR2 U775 ( .A(pi11), .B(n811), .Z(n810));
+ AN2 U776 ( .A(n812), .B(n813), .Z(n811));
+ AN2 U777 ( .A(n814), .B(n815), .Z(n813));
+ OR2 U778 ( .A(n782), .B(n816), .Z(n815));
+ OR2 U779 ( .A(n817), .B(n818), .Z(n814));
+ OR2 U780 ( .A(n819), .B(n820), .Z(n818));
+ AN2 U781 ( .A(n750), .B(n821), .Z(n820));
+ AN2 U782 ( .A(n749), .B(n747), .Z(n819));
+ IV2 U783 ( .A(n821), .Z(n749));
+ AN2 U784 ( .A(n822), .B(n823), .Z(n812));
+ OR2 U785 ( .A(n824), .B(n825), .Z(n823));
+ OR2 U786 ( .A(n826), .B(n827), .Z(n822));
+ AN2 U787 ( .A(pi10), .B(n828), .Z(n826));
+ OR2 U788 ( .A(n829), .B(n830), .Z(n828));
+ OR2 U789 ( .A(n831), .B(n738), .Z(n809));
+ AN2 U790 ( .A(n832), .B(n833), .Z(n831));
+ AN2 U791 ( .A(n834), .B(n760), .Z(n833));
+ OR2 U792 ( .A(n817), .B(n835), .Z(n760));
+ OR2 U793 ( .A(pi03), .B(n836), .Z(n835));
+ OR2 U794 ( .A(n817), .B(n837), .Z(n834));
+ OR2 U795 ( .A(n715), .B(n827), .Z(n837));
+ IV2 U796 ( .A(n836), .Z(n715));
+ AN2 U797 ( .A(n838), .B(n839), .Z(n832));
+ OR2 U798 ( .A(n765), .B(n840), .Z(n839));
+ OR2 U799 ( .A(n841), .B(n825), .Z(n840));
+ OR2 U800 ( .A(n816), .B(n842), .Z(n838));
+ OR2 U801 ( .A(n843), .B(n844), .Z(n842));
+ AN2 U802 ( .A(n845), .B(n846), .Z(n844));
+ OR2 U803 ( .A(n847), .B(n848), .Z(n845));
+ AN2 U804 ( .A(n758), .B(n747), .Z(n848));
+ IV2 U805 ( .A(n849), .Z(n758));
+ AN2 U806 ( .A(n750), .B(n849), .Z(n847));
+ AN2 U807 ( .A(n849), .B(n759), .Z(n843));
+ OR2 U808 ( .A(n850), .B(n851), .Z(n849));
+ AN2 U809 ( .A(n852), .B(n853), .Z(n850));
+ IV2 U810 ( .A(n854), .Z(n816));
+ AN2 U811 ( .A(n855), .B(n856), .Z(n807));
+ OR2 U812 ( .A(n857), .B(n858), .Z(n856));
+ OR2 U813 ( .A(n859), .B(n860), .Z(n858));
+ AN2 U814 ( .A(n861), .B(n739), .Z(n859));
+ OR2 U815 ( .A(n862), .B(n863), .Z(n739));
+ AN2 U816 ( .A(n759), .B(n795), .Z(n862));
+ OR2 U817 ( .A(n846), .B(n864), .Z(n861));
+ IV2 U818 ( .A(n865), .Z(n864));
+ AN2 U819 ( .A(n795), .B(n863), .Z(n865));
+ IV2 U820 ( .A(n759), .Z(n846));
+ OR2 U821 ( .A(n866), .B(n867), .Z(n759));
+ AN2 U822 ( .A(n868), .B(po5), .Z(n867));
+ AN2 U823 ( .A(n750), .B(n869), .Z(n866));
+ OR2 U824 ( .A(n825), .B(n870), .Z(n855));
+ OR2 U825 ( .A(n871), .B(n872), .Z(n870));
+ AN2 U826 ( .A(n764), .B(n873), .Z(n872));
+ IV2 U827 ( .A(po5), .Z(n873));
+ AN2 U828 ( .A(n841), .B(po4), .Z(n871));
+ OR2 U829 ( .A(n874), .B(po5), .Z(po4));
+ IV2 U830 ( .A(n764), .Z(n841));
+ OR2 U831 ( .A(n875), .B(n724), .Z(n764));
+ AN2 U832 ( .A(n876), .B(n877), .Z(n875));
+ AN2 U833 ( .A(n878), .B(n879), .Z(n805));
+ AN2 U834 ( .A(n880), .B(n881), .Z(n879));
+ OR2 U835 ( .A(n782), .B(n882), .Z(n881));
+ OR2 U836 ( .A(n781), .B(n883), .Z(n882));
+ IV2 U837 ( .A(n884), .Z(n781));
+ OR2 U838 ( .A(n795), .B(n885), .Z(n880));
+ AN2 U839 ( .A(n886), .B(n887), .Z(n878));
+ OR2 U840 ( .A(pi03), .B(n888), .Z(n887));
+ AN2 U841 ( .A(n889), .B(n890), .Z(n888));
+ IV2 U842 ( .A(n891), .Z(n890));
+ AN2 U843 ( .A(n830), .B(n892), .Z(n891));
+ OR2 U844 ( .A(n893), .B(n894), .Z(n830));
+ IV2 U845 ( .A(n895), .Z(n894));
+ OR2 U846 ( .A(n746), .B(n750), .Z(n895));
+ AN2 U847 ( .A(n750), .B(n746), .Z(n893));
+ OR2 U848 ( .A(n896), .B(n897), .Z(n746));
+ AN2 U849 ( .A(pi02), .B(n898), .Z(n896));
+ IV2 U850 ( .A(n747), .Z(n750));
+ OR2 U851 ( .A(n899), .B(n900), .Z(n747));
+ AN2 U852 ( .A(n901), .B(n771), .Z(n900));
+ OR2 U853 ( .A(pi03), .B(n795), .Z(n771));
+ AN2 U854 ( .A(n902), .B(n903), .Z(n899));
+ OR2 U855 ( .A(n904), .B(n905), .Z(n903));
+ OR2 U856 ( .A(n906), .B(n907), .Z(n905));
+ AN2 U857 ( .A(n782), .B(n892), .Z(n907));
+ AN2 U858 ( .A(n769), .B(n751), .Z(n906));
+ AN2 U859 ( .A(po5), .B(n908), .Z(n904));
+ OR2 U860 ( .A(n909), .B(n772), .Z(n889));
+ AN2 U861 ( .A(n910), .B(n911), .Z(n909));
+ OR2 U862 ( .A(n912), .B(n795), .Z(n911));
+ OR2 U863 ( .A(n782), .B(n770), .Z(n910));
+ OR2 U864 ( .A(n827), .B(n913), .Z(n886));
+ OR2 U865 ( .A(n914), .B(n772), .Z(n913));
+ OR2 U866 ( .A(n915), .B(n916), .Z(n914));
+ AN2 U867 ( .A(n912), .B(n795), .Z(n916));
+ IV2 U868 ( .A(n770), .Z(n912));
+ AN2 U869 ( .A(n782), .B(n770), .Z(n915));
+ OR2 U870 ( .A(n917), .B(n918), .Z(n770));
+ AN2 U871 ( .A(n919), .B(n920), .Z(n917));
+ IV2 U872 ( .A(n795), .Z(n782));
+ OR2 U873 ( .A(n921), .B(n922), .Z(n787));
+ AN2 U874 ( .A(n923), .B(n824), .Z(n922));
+ AN2 U875 ( .A(n924), .B(n925), .Z(n923));
+ OR2 U876 ( .A(n926), .B(n927), .Z(n925));
+ AN2 U877 ( .A(pi11), .B(pi03), .Z(n926));
+ AN2 U878 ( .A(pi07), .B(n928), .Z(n921));
+ OR2 U879 ( .A(n929), .B(n930), .Z(n928));
+ AN2 U880 ( .A(n931), .B(n804), .Z(n929));
+ OR2 U881 ( .A(n932), .B(n933), .Z(n931));
+ AN2 U882 ( .A(n854), .B(n795), .Z(n933));
+ AN2 U883 ( .A(n934), .B(n827), .Z(n932));
+ OR2 U884 ( .A(n935), .B(n936), .Z(n785));
+ OR2 U885 ( .A(n937), .B(n938), .Z(n936));
+ AN2 U886 ( .A(n939), .B(n940), .Z(n938));
+ OR2 U887 ( .A(n941), .B(n942), .Z(n940));
+ OR2 U888 ( .A(n769), .B(n943), .Z(n942));
+ AN2 U889 ( .A(n874), .B(n944), .Z(n943));
+ AN2 U890 ( .A(n795), .B(pi03), .Z(n769));
+ OR2 U891 ( .A(n945), .B(n946), .Z(n795));
+ OR2 U892 ( .A(n947), .B(n948), .Z(n946));
+ AN2 U893 ( .A(n949), .B(n824), .Z(n948));
+ AN2 U894 ( .A(n950), .B(n765), .Z(n947));
+ IV2 U895 ( .A(n874), .Z(n765));
+ OR2 U896 ( .A(n951), .B(n952), .Z(n945));
+ OR2 U897 ( .A(n953), .B(n954), .Z(n952));
+ AN2 U898 ( .A(n955), .B(n827), .Z(n954));
+ OR2 U899 ( .A(n956), .B(n957), .Z(n955));
+ AN2 U900 ( .A(n958), .B(n784), .Z(n956));
+ AN2 U901 ( .A(pi07), .B(n959), .Z(n958));
+ AN2 U902 ( .A(po5), .B(n960), .Z(n953));
+ OR2 U903 ( .A(n961), .B(n962), .Z(n960));
+ AN2 U904 ( .A(n892), .B(n963), .Z(n962));
+ AN2 U905 ( .A(n964), .B(n965), .Z(n961));
+ AN2 U906 ( .A(pi13), .B(n966), .Z(n951));
+ OR2 U907 ( .A(n967), .B(n968), .Z(n966));
+ OR2 U908 ( .A(n969), .B(n970), .Z(n968));
+ AN2 U909 ( .A(n971), .B(pi02), .Z(n970));
+ AN2 U910 ( .A(n972), .B(n973), .Z(n969));
+ AN2 U911 ( .A(n974), .B(n975), .Z(n972));
+ OR2 U912 ( .A(n874), .B(n959), .Z(n975));
+ AN2 U913 ( .A(n827), .B(n824), .Z(n874));
+ IV2 U914 ( .A(pi03), .Z(n827));
+ OR2 U915 ( .A(n964), .B(n976), .Z(n974));
+ AN2 U916 ( .A(pi03), .B(n824), .Z(n976));
+ IV2 U917 ( .A(pi07), .Z(n824));
+ IV2 U918 ( .A(n959), .Z(n964));
+ OR2 U919 ( .A(n977), .B(n978), .Z(n959));
+ AN2 U920 ( .A(n979), .B(pi02), .Z(n978));
+ AN2 U921 ( .A(n980), .B(n717), .Z(n977));
+ OR2 U922 ( .A(n979), .B(pi02), .Z(n980));
+ AN2 U923 ( .A(n981), .B(po5), .Z(n967));
+ AN2 U924 ( .A(po5), .B(n982), .Z(n941));
+ AN2 U925 ( .A(pi03), .B(pi07), .Z(po5));
+ AN2 U926 ( .A(n983), .B(pi03), .Z(n935));
+ OR2 U927 ( .A(n984), .B(n985), .Z(po2));
+ OR2 U928 ( .A(n986), .B(n987), .Z(n985));
+ OR2 U929 ( .A(n988), .B(n989), .Z(n987));
+ OR2 U930 ( .A(n990), .B(n991), .Z(n989));
+ AN2 U931 ( .A(n793), .B(n992), .Z(n991));
+ AN2 U932 ( .A(n794), .B(n993), .Z(n990));
+ OR2 U933 ( .A(n994), .B(n995), .Z(n988));
+ AN2 U934 ( .A(n777), .B(n801), .Z(n995));
+ IV2 U935 ( .A(n800), .Z(n777));
+ AN2 U936 ( .A(n776), .B(n800), .Z(n994));
+ OR2 U937 ( .A(n996), .B(n804), .Z(n800));
+ AN2 U938 ( .A(n997), .B(n998), .Z(n996));
+ AN2 U939 ( .A(n999), .B(n1000), .Z(n998));
+ AN2 U940 ( .A(n1001), .B(n1002), .Z(n1000));
+ OR2 U941 ( .A(n1003), .B(n817), .Z(n1002));
+ AN2 U942 ( .A(n1004), .B(n836), .Z(n1003));
+ OR2 U943 ( .A(pi00), .B(n1005), .Z(n836));
+ OR2 U944 ( .A(pi02), .B(pi01), .Z(n1005));
+ AN2 U945 ( .A(n1006), .B(n1007), .Z(n1004));
+ OR2 U946 ( .A(pi11), .B(n1008), .Z(n1007));
+ AN2 U947 ( .A(n1009), .B(n821), .Z(n1008));
+ OR2 U948 ( .A(n898), .B(n1010), .Z(n821));
+ OR2 U949 ( .A(n1011), .B(n851), .Z(n1009));
+ AN2 U950 ( .A(n1012), .B(n1013), .Z(n1011));
+ OR2 U951 ( .A(n738), .B(n1014), .Z(n1006));
+ OR2 U952 ( .A(n1015), .B(n1016), .Z(n1014));
+ AN2 U953 ( .A(n713), .B(n1017), .Z(n1015));
+ OR2 U954 ( .A(n1018), .B(n1019), .Z(n1001));
+ OR2 U955 ( .A(n744), .B(n1020), .Z(n1019));
+ OR2 U956 ( .A(n1021), .B(n1022), .Z(n1018));
+ AN2 U957 ( .A(n717), .B(n1023), .Z(n1022));
+ AN2 U958 ( .A(n863), .B(n1024), .Z(n1021));
+ OR2 U959 ( .A(n1025), .B(n1026), .Z(n1024));
+ OR2 U960 ( .A(n992), .B(n852), .Z(n1026));
+ IV2 U961 ( .A(n1027), .Z(n1025));
+ OR2 U962 ( .A(n1028), .B(n1027), .Z(n863));
+ OR2 U963 ( .A(n1029), .B(n1030), .Z(n1027));
+ AN2 U964 ( .A(n1031), .B(n1032), .Z(n1029));
+ AN2 U965 ( .A(n1033), .B(n993), .Z(n1028));
+ AN2 U966 ( .A(n885), .B(n1034), .Z(n999));
+ OR2 U967 ( .A(n825), .B(n1035), .Z(n1034));
+ OR2 U968 ( .A(n1036), .B(n1037), .Z(n1035));
+ AN2 U969 ( .A(n1038), .B(n1039), .Z(n1037));
+ IV2 U970 ( .A(n724), .Z(n1039));
+ OR2 U971 ( .A(n877), .B(n738), .Z(n1038));
+ IV2 U972 ( .A(n876), .Z(n1036));
+ OR2 U973 ( .A(n1040), .B(n884), .Z(n885));
+ OR2 U974 ( .A(n1041), .B(n1042), .Z(n884));
+ OR2 U975 ( .A(n993), .B(n1032), .Z(n1042));
+ AN2 U976 ( .A(n1043), .B(n1044), .Z(n997));
+ AN2 U977 ( .A(n1045), .B(n1046), .Z(n1044));
+ OR2 U978 ( .A(pi02), .B(n1047), .Z(n1046));
+ AN2 U979 ( .A(n1048), .B(n1049), .Z(n1047));
+ OR2 U980 ( .A(n876), .B(n1050), .Z(n1049));
+ OR2 U981 ( .A(n717), .B(n825), .Z(n1050));
+ AN2 U982 ( .A(n1051), .B(n1052), .Z(n1048));
+ OR2 U983 ( .A(n1053), .B(n1054), .Z(n1052));
+ OR2 U984 ( .A(n1055), .B(n772), .Z(n1051));
+ AN2 U985 ( .A(n1056), .B(n1057), .Z(n1055));
+ OR2 U986 ( .A(n1058), .B(n993), .Z(n1057));
+ OR2 U987 ( .A(n992), .B(n919), .Z(n1056));
+ OR2 U988 ( .A(n1059), .B(n1016), .Z(n1045));
+ AN2 U989 ( .A(n1060), .B(n1061), .Z(n1059));
+ AN2 U990 ( .A(n1062), .B(n1063), .Z(n1061));
+ OR2 U991 ( .A(n876), .B(n1064), .Z(n1062));
+ OR2 U992 ( .A(pi06), .B(n825), .Z(n1064));
+ OR2 U993 ( .A(n1065), .B(n725), .Z(n876));
+ AN2 U994 ( .A(n718), .B(n1066), .Z(n1065));
+ AN2 U995 ( .A(n1067), .B(n1068), .Z(n1060));
+ OR2 U996 ( .A(n772), .B(n1069), .Z(n1068));
+ OR2 U997 ( .A(n1070), .B(n1071), .Z(n1069));
+ AN2 U998 ( .A(n1058), .B(n993), .Z(n1071));
+ IV2 U999 ( .A(n919), .Z(n1058));
+ AN2 U1000 ( .A(n992), .B(n919), .Z(n1070));
+ OR2 U1001 ( .A(n1072), .B(n1073), .Z(n919));
+ AN2 U1002 ( .A(n1074), .B(n1075), .Z(n1072));
+ OR2 U1003 ( .A(n1054), .B(n1076), .Z(n1067));
+ IV2 U1004 ( .A(n1053), .Z(n1076));
+ AN2 U1005 ( .A(n1077), .B(n1078), .Z(n1053));
+ OR2 U1006 ( .A(n897), .B(n851), .Z(n1078));
+ IV2 U1007 ( .A(n1079), .Z(n1077));
+ AN2 U1008 ( .A(n851), .B(n897), .Z(n1079));
+ OR2 U1009 ( .A(n1080), .B(n1081), .Z(n897));
+ AN2 U1010 ( .A(pi01), .B(n1082), .Z(n1080));
+ AN2 U1011 ( .A(n1083), .B(n1084), .Z(n1043));
+ OR2 U1012 ( .A(pi10), .B(n1085), .Z(n1084));
+ OR2 U1013 ( .A(n1086), .B(n1087), .Z(n1085));
+ AN2 U1014 ( .A(n1088), .B(n1089), .Z(n1087));
+ AN2 U1015 ( .A(n852), .B(n898), .Z(n1088));
+ IV2 U1016 ( .A(n1033), .Z(n852));
+ AN2 U1017 ( .A(n1090), .B(n853), .Z(n1086));
+ IV2 U1018 ( .A(n1089), .Z(n853));
+ AN2 U1019 ( .A(n1091), .B(n1082), .Z(n1089));
+ OR2 U1020 ( .A(n1031), .B(n1092), .Z(n1091));
+ OR2 U1021 ( .A(n851), .B(n1033), .Z(n1090));
+ OR2 U1022 ( .A(n1093), .B(n1094), .Z(n1033));
+ AN2 U1023 ( .A(n868), .B(n724), .Z(n1094));
+ AN2 U1024 ( .A(n851), .B(n869), .Z(n1093));
+ IV2 U1025 ( .A(n898), .Z(n851));
+ OR2 U1026 ( .A(n1095), .B(n1096), .Z(n898));
+ AN2 U1027 ( .A(n901), .B(n920), .Z(n1096));
+ OR2 U1028 ( .A(pi02), .B(n993), .Z(n920));
+ AN2 U1029 ( .A(n902), .B(n1097), .Z(n1095));
+ OR2 U1030 ( .A(n1098), .B(n1099), .Z(n1097));
+ OR2 U1031 ( .A(n1100), .B(n1101), .Z(n1099));
+ AN2 U1032 ( .A(n992), .B(n892), .Z(n1101));
+ AN2 U1033 ( .A(n918), .B(n751), .Z(n1100));
+ AN2 U1034 ( .A(n908), .B(n724), .Z(n1098));
+ OR2 U1035 ( .A(n1102), .B(n992), .Z(n1083));
+ IV2 U1036 ( .A(n993), .Z(n992));
+ AN2 U1037 ( .A(n1103), .B(n1104), .Z(n1102));
+ OR2 U1038 ( .A(n883), .B(n1105), .Z(n1104));
+ IV2 U1039 ( .A(n1106), .Z(n883));
+ IV2 U1040 ( .A(n801), .Z(n776));
+ OR2 U1041 ( .A(n1107), .B(n1108), .Z(n801));
+ OR2 U1042 ( .A(pi12), .B(n1109), .Z(n1108));
+ OR2 U1043 ( .A(n1110), .B(n1111), .Z(n986));
+ AN2 U1044 ( .A(n1112), .B(n717), .Z(n1111));
+ AN2 U1045 ( .A(n924), .B(n1113), .Z(n1112));
+ OR2 U1046 ( .A(n1114), .B(n927), .Z(n1113));
+ AN2 U1047 ( .A(pi11), .B(pi02), .Z(n1114));
+ AN2 U1048 ( .A(pi06), .B(n1115), .Z(n1110));
+ OR2 U1049 ( .A(n1116), .B(n930), .Z(n1115));
+ AN2 U1050 ( .A(n1117), .B(n804), .Z(n1116));
+ OR2 U1051 ( .A(n1118), .B(n1119), .Z(n1117));
+ AN2 U1052 ( .A(n854), .B(n993), .Z(n1119));
+ AN2 U1053 ( .A(n934), .B(n1016), .Z(n1118));
+ OR2 U1054 ( .A(n1120), .B(n1121), .Z(n984));
+ OR2 U1055 ( .A(n937), .B(n1122), .Z(n1121));
+ AN2 U1056 ( .A(n939), .B(n1123), .Z(n1122));
+ OR2 U1057 ( .A(n1124), .B(n1125), .Z(n1123));
+ OR2 U1058 ( .A(n918), .B(n1126), .Z(n1125));
+ AN2 U1059 ( .A(n724), .B(n982), .Z(n1126));
+ AN2 U1060 ( .A(n993), .B(pi02), .Z(n918));
+ OR2 U1061 ( .A(n1127), .B(n1128), .Z(n993));
+ OR2 U1062 ( .A(n1129), .B(n1130), .Z(n1128));
+ AN2 U1063 ( .A(n949), .B(n717), .Z(n1130));
+ AN2 U1064 ( .A(n950), .B(n877), .Z(n1129));
+ IV2 U1065 ( .A(n727), .Z(n877));
+ OR2 U1066 ( .A(n1131), .B(n1132), .Z(n1127));
+ OR2 U1067 ( .A(n1133), .B(n1134), .Z(n1132));
+ AN2 U1068 ( .A(n1135), .B(n1016), .Z(n1134));
+ OR2 U1069 ( .A(n1136), .B(n957), .Z(n1135));
+ AN2 U1070 ( .A(n1137), .B(n979), .Z(n1136));
+ AN2 U1071 ( .A(n784), .B(pi06), .Z(n1137));
+ AN2 U1072 ( .A(n724), .B(n1138), .Z(n1133));
+ OR2 U1073 ( .A(n1139), .B(n1140), .Z(n1138));
+ AN2 U1074 ( .A(n965), .B(n1141), .Z(n1139));
+ AN2 U1075 ( .A(pi02), .B(pi06), .Z(n724));
+ AN2 U1076 ( .A(pi13), .B(n1142), .Z(n1131));
+ OR2 U1077 ( .A(n1143), .B(n1144), .Z(n1142));
+ AN2 U1078 ( .A(n971), .B(pi01), .Z(n1144));
+ AN2 U1079 ( .A(n1145), .B(n973), .Z(n1143));
+ AN2 U1080 ( .A(n1146), .B(n1147), .Z(n1145));
+ OR2 U1081 ( .A(n727), .B(n979), .Z(n1147));
+ IV2 U1082 ( .A(n1141), .Z(n979));
+ OR2 U1083 ( .A(n1148), .B(n1141), .Z(n1146));
+ OR2 U1084 ( .A(n1149), .B(n1150), .Z(n1141));
+ AN2 U1085 ( .A(n1151), .B(n1017), .Z(n1150));
+ AN2 U1086 ( .A(pi05), .B(n1152), .Z(n1149));
+ OR2 U1087 ( .A(n1151), .B(n1017), .Z(n1152));
+ AN2 U1088 ( .A(pi02), .B(n717), .Z(n1148));
+ AN2 U1089 ( .A(n944), .B(n727), .Z(n1124));
+ AN2 U1090 ( .A(n1016), .B(n717), .Z(n727));
+ IV2 U1091 ( .A(pi06), .Z(n717));
+ IV2 U1092 ( .A(pi02), .Z(n1016));
+ AN2 U1093 ( .A(n983), .B(pi02), .Z(n1120));
+ OR2 U1094 ( .A(n1153), .B(n1154), .Z(po1));
+ OR2 U1095 ( .A(n1155), .B(n1156), .Z(n1154));
+ OR2 U1096 ( .A(n1157), .B(n1158), .Z(n1156));
+ OR2 U1097 ( .A(n1159), .B(n1160), .Z(n1158));
+ AN2 U1098 ( .A(n793), .B(n1105), .Z(n1160));
+ AN2 U1099 ( .A(n794), .B(n1032), .Z(n1159));
+ OR2 U1100 ( .A(n1161), .B(n1162), .Z(n1157));
+ AN2 U1101 ( .A(n1163), .B(n1107), .Z(n1162));
+ IV2 U1102 ( .A(n1164), .Z(n1161));
+ OR2 U1103 ( .A(n1107), .B(n1163), .Z(n1164));
+ AN2 U1104 ( .A(n1165), .B(n1166), .Z(n1163));
+ OR2 U1105 ( .A(n1167), .B(n804), .Z(n1107));
+ AN2 U1106 ( .A(n1168), .B(n1169), .Z(n1167));
+ AN2 U1107 ( .A(n1170), .B(n1171), .Z(n1169));
+ OR2 U1108 ( .A(n817), .B(n1172), .Z(n1171));
+ OR2 U1109 ( .A(pi11), .B(n1173), .Z(n1172));
+ AN2 U1110 ( .A(n1010), .B(n1174), .Z(n1173));
+ OR2 U1111 ( .A(n1012), .B(n1013), .Z(n1174));
+ OR2 U1112 ( .A(n1175), .B(n1082), .Z(n1010));
+ AN2 U1113 ( .A(n1176), .B(n1177), .Z(n1170));
+ OR2 U1114 ( .A(pi10), .B(n1178), .Z(n1177));
+ OR2 U1115 ( .A(n1179), .B(n1180), .Z(n1178));
+ AN2 U1116 ( .A(n1181), .B(n1031), .Z(n1180));
+ IV2 U1117 ( .A(n1182), .Z(n1179));
+ OR2 U1118 ( .A(n1181), .B(n1031), .Z(n1182));
+ OR2 U1119 ( .A(n1183), .B(n1184), .Z(n1181));
+ AN2 U1120 ( .A(n1185), .B(n1082), .Z(n1184));
+ AN2 U1121 ( .A(n1012), .B(n1092), .Z(n1183));
+ OR2 U1122 ( .A(n825), .B(n1186), .Z(n1176));
+ OR2 U1123 ( .A(n1187), .B(n1188), .Z(n1186));
+ AN2 U1124 ( .A(n1189), .B(n1190), .Z(n1187));
+ IV2 U1125 ( .A(n725), .Z(n1190));
+ OR2 U1126 ( .A(n1066), .B(n738), .Z(n1189));
+ AN2 U1127 ( .A(n1191), .B(n1192), .Z(n1168));
+ AN2 U1128 ( .A(n1193), .B(n1194), .Z(n1192));
+ OR2 U1129 ( .A(n1195), .B(n1017), .Z(n1194));
+ AN2 U1130 ( .A(n1196), .B(n1197), .Z(n1195));
+ AN2 U1131 ( .A(n1198), .B(n1199), .Z(n1197));
+ OR2 U1132 ( .A(pi05), .B(n1200), .Z(n1199));
+ AN2 U1133 ( .A(n1201), .B(n1063), .Z(n1198));
+ OR2 U1134 ( .A(n1202), .B(n772), .Z(n1201));
+ AN2 U1135 ( .A(n1203), .B(n1204), .Z(n1202));
+ OR2 U1136 ( .A(n1074), .B(n1032), .Z(n1204));
+ OR2 U1137 ( .A(n1105), .B(n1205), .Z(n1203));
+ AN2 U1138 ( .A(n1206), .B(n1207), .Z(n1196));
+ OR2 U1139 ( .A(n1208), .B(n1054), .Z(n1207));
+ AN2 U1140 ( .A(n1209), .B(n1210), .Z(n1208));
+ OR2 U1141 ( .A(n1081), .B(n1082), .Z(n1210));
+ OR2 U1142 ( .A(n1012), .B(n1211), .Z(n1209));
+ IV2 U1143 ( .A(n1081), .Z(n1211));
+ OR2 U1144 ( .A(n817), .B(n1212), .Z(n1206));
+ OR2 U1145 ( .A(n713), .B(n738), .Z(n1212));
+ OR2 U1146 ( .A(pi01), .B(n1213), .Z(n1193));
+ AN2 U1147 ( .A(n1214), .B(n1215), .Z(n1213));
+ AN2 U1148 ( .A(n1216), .B(n1217), .Z(n1215));
+ OR2 U1149 ( .A(n1054), .B(n1218), .Z(n1216));
+ OR2 U1150 ( .A(n1012), .B(n1081), .Z(n1218));
+ AN2 U1151 ( .A(pi00), .B(n1175), .Z(n1081));
+ OR2 U1152 ( .A(pi08), .B(n1020), .Z(n1054));
+ AN2 U1153 ( .A(n1219), .B(n1220), .Z(n1214));
+ OR2 U1154 ( .A(n772), .B(n1221), .Z(n1220));
+ OR2 U1155 ( .A(n1222), .B(n1223), .Z(n1221));
+ AN2 U1156 ( .A(n1074), .B(n1032), .Z(n1223));
+ AN2 U1157 ( .A(n1105), .B(n1205), .Z(n1222));
+ OR2 U1158 ( .A(n1224), .B(n738), .Z(n772));
+ AN2 U1159 ( .A(n1225), .B(n829), .Z(n1224));
+ OR2 U1160 ( .A(n751), .B(n1023), .Z(n1225));
+ OR2 U1161 ( .A(n716), .B(n1200), .Z(n1219));
+ OR2 U1162 ( .A(n718), .B(n825), .Z(n1200));
+ IV2 U1163 ( .A(n761), .Z(n825));
+ AN2 U1164 ( .A(n1226), .B(n1227), .Z(n1191));
+ OR2 U1165 ( .A(n1228), .B(n1229), .Z(n1227));
+ OR2 U1166 ( .A(n1020), .B(n1230), .Z(n1229));
+ OR2 U1167 ( .A(n1231), .B(n1232), .Z(n1230));
+ AN2 U1168 ( .A(n1233), .B(n1234), .Z(n1232));
+ AN2 U1169 ( .A(n1235), .B(n1031), .Z(n1233));
+ OR2 U1170 ( .A(n1030), .B(n1032), .Z(n1235));
+ AN2 U1171 ( .A(n1092), .B(n1041), .Z(n1030));
+ IV2 U1172 ( .A(n1236), .Z(n1231));
+ OR2 U1173 ( .A(n1234), .B(n1031), .Z(n1236));
+ OR2 U1174 ( .A(n1237), .B(n1238), .Z(n1031));
+ AN2 U1175 ( .A(n868), .B(n725), .Z(n1238));
+ AN2 U1176 ( .A(n1012), .B(n869), .Z(n1237));
+ IV2 U1177 ( .A(n1082), .Z(n1012));
+ OR2 U1178 ( .A(n1239), .B(n1240), .Z(n1082));
+ AN2 U1179 ( .A(n901), .B(n1075), .Z(n1240));
+ OR2 U1180 ( .A(pi01), .B(n1032), .Z(n1075));
+ AN2 U1181 ( .A(n902), .B(n1241), .Z(n1239));
+ OR2 U1182 ( .A(n1242), .B(n1243), .Z(n1241));
+ OR2 U1183 ( .A(n1244), .B(n1245), .Z(n1243));
+ AN2 U1184 ( .A(n1105), .B(n892), .Z(n1245));
+ AN2 U1185 ( .A(n1073), .B(n751), .Z(n1244));
+ AN2 U1186 ( .A(n908), .B(n725), .Z(n1242));
+ OR2 U1187 ( .A(n1185), .B(n1246), .Z(n1234));
+ OR2 U1188 ( .A(n1247), .B(n1105), .Z(n1246));
+ IV2 U1189 ( .A(n1248), .Z(n1020));
+ OR2 U1190 ( .A(n1249), .B(n744), .Z(n1228));
+ AN2 U1191 ( .A(n716), .B(n1023), .Z(n1249));
+ AN2 U1192 ( .A(n1250), .B(n1251), .Z(n1226));
+ OR2 U1193 ( .A(n1105), .B(n1103), .Z(n1251));
+ IV2 U1194 ( .A(n1252), .Z(n1103));
+ OR2 U1195 ( .A(n1253), .B(n1254), .Z(n1252));
+ AN2 U1196 ( .A(n1106), .B(n1041), .Z(n1254));
+ OR2 U1197 ( .A(n1255), .B(n780), .Z(n1106));
+ AN2 U1198 ( .A(n973), .B(n738), .Z(n1255));
+ AN2 U1199 ( .A(n854), .B(n738), .Z(n1253));
+ IV2 U1200 ( .A(n1032), .Z(n1105));
+ OR2 U1201 ( .A(n1032), .B(n1256), .Z(n1250));
+ OR2 U1202 ( .A(n1040), .B(n1041), .Z(n1256));
+ IV2 U1203 ( .A(n1257), .Z(n1040));
+ OR2 U1204 ( .A(n1258), .B(n1259), .Z(n1155));
+ AN2 U1205 ( .A(n1260), .B(n716), .Z(n1259));
+ AN2 U1206 ( .A(n924), .B(n1261), .Z(n1260));
+ OR2 U1207 ( .A(n1262), .B(n927), .Z(n1261));
+ AN2 U1208 ( .A(pi11), .B(pi01), .Z(n1262));
+ AN2 U1209 ( .A(pi05), .B(n1263), .Z(n1258));
+ OR2 U1210 ( .A(n1264), .B(n930), .Z(n1263));
+ AN2 U1211 ( .A(n1265), .B(n804), .Z(n1264));
+ OR2 U1212 ( .A(n1266), .B(n1267), .Z(n1265));
+ AN2 U1213 ( .A(n854), .B(n1032), .Z(n1267));
+ AN2 U1214 ( .A(n934), .B(n1017), .Z(n1266));
+ AN2 U1215 ( .A(pi11), .B(n761), .Z(n934));
+ OR2 U1216 ( .A(n1268), .B(n1269), .Z(n1153));
+ OR2 U1217 ( .A(n937), .B(n1270), .Z(n1269));
+ AN2 U1218 ( .A(n939), .B(n1271), .Z(n1270));
+ OR2 U1219 ( .A(n1272), .B(n1273), .Z(n1271));
+ OR2 U1220 ( .A(n1073), .B(n1274), .Z(n1273));
+ AN2 U1221 ( .A(n725), .B(n982), .Z(n1274));
+ AN2 U1222 ( .A(n1032), .B(pi01), .Z(n1073));
+ OR2 U1223 ( .A(n1275), .B(n1276), .Z(n1032));
+ OR2 U1224 ( .A(n1277), .B(n1278), .Z(n1276));
+ AN2 U1225 ( .A(n949), .B(n716), .Z(n1278));
+ AN2 U1226 ( .A(n950), .B(n1066), .Z(n1277));
+ IV2 U1227 ( .A(n723), .Z(n1066));
+ OR2 U1228 ( .A(n1279), .B(n1280), .Z(n1275));
+ OR2 U1229 ( .A(n1281), .B(n1282), .Z(n1280));
+ AN2 U1230 ( .A(n1283), .B(n1017), .Z(n1282));
+ OR2 U1231 ( .A(n1284), .B(n957), .Z(n1283));
+ AN2 U1232 ( .A(n1285), .B(n784), .Z(n1284));
+ AN2 U1233 ( .A(pi05), .B(n1286), .Z(n1285));
+ AN2 U1234 ( .A(n725), .B(n1287), .Z(n1281));
+ OR2 U1235 ( .A(n1288), .B(n1140), .Z(n1287));
+ AN2 U1236 ( .A(n965), .B(n1151), .Z(n1288));
+ AN2 U1237 ( .A(n744), .B(n902), .Z(n965));
+ AN2 U1238 ( .A(pi01), .B(pi05), .Z(n725));
+ AN2 U1239 ( .A(pi13), .B(n1289), .Z(n1279));
+ OR2 U1240 ( .A(n1290), .B(n1291), .Z(n1289));
+ AN2 U1241 ( .A(n971), .B(pi00), .Z(n1291));
+ AN2 U1242 ( .A(n892), .B(n1292), .Z(n971));
+ AN2 U1243 ( .A(pi10), .B(pi11), .Z(n1292));
+ AN2 U1244 ( .A(n1293), .B(n973), .Z(n1290));
+ AN2 U1245 ( .A(n1294), .B(n1295), .Z(n1293));
+ OR2 U1246 ( .A(n723), .B(n1286), .Z(n1295));
+ IV2 U1247 ( .A(n1151), .Z(n1286));
+ OR2 U1248 ( .A(n1151), .B(n1296), .Z(n1294));
+ AN2 U1249 ( .A(pi01), .B(n716), .Z(n1296));
+ AN2 U1250 ( .A(n944), .B(n723), .Z(n1272));
+ AN2 U1251 ( .A(n1017), .B(n716), .Z(n723));
+ IV2 U1252 ( .A(pi05), .Z(n716));
+ IV2 U1253 ( .A(pi01), .Z(n1017));
+ AN2 U1254 ( .A(n983), .B(pi01), .Z(n1268));
+ AN2 U1255 ( .A(pi11), .B(n1297), .Z(n983));
+ OR2 U1256 ( .A(n1298), .B(n1299), .Z(po0));
+ OR2 U1257 ( .A(n1300), .B(n1301), .Z(n1299));
+ OR2 U1258 ( .A(n1302), .B(n1303), .Z(n1301));
+ OR2 U1259 ( .A(n1304), .B(n1305), .Z(n1303));
+ AN2 U1260 ( .A(n793), .B(n1247), .Z(n1305));
+ AN2 U1261 ( .A(n924), .B(n1306), .Z(n793));
+ IV2 U1262 ( .A(n1307), .Z(n1306));
+ OR2 U1263 ( .A(n854), .B(n1308), .Z(n1307));
+ AN2 U1264 ( .A(pi08), .B(n1063), .Z(n1308));
+ IV2 U1265 ( .A(n1309), .Z(n1063));
+ AN2 U1266 ( .A(n794), .B(n1041), .Z(n1304));
+ AN2 U1267 ( .A(n1310), .B(n924), .Z(n794));
+ OR2 U1268 ( .A(pi11), .B(n854), .Z(n1310));
+ AN2 U1269 ( .A(pi11), .B(n1311), .Z(n1302));
+ OR2 U1270 ( .A(n1312), .B(n1313), .Z(n1311));
+ OR2 U1271 ( .A(n1314), .B(n1315), .Z(n1313));
+ AN2 U1272 ( .A(n924), .B(n1316), .Z(n1315));
+ AN2 U1273 ( .A(n1317), .B(n761), .Z(n1314));
+ AN2 U1274 ( .A(n1023), .B(n908), .Z(n761));
+ AN2 U1275 ( .A(n1151), .B(n804), .Z(n1317));
+ AN2 U1276 ( .A(n1297), .B(pi00), .Z(n1312));
+ AN2 U1277 ( .A(n804), .B(n1318), .Z(n1297));
+ OR2 U1278 ( .A(pi10), .B(n892), .Z(n1318));
+ OR2 U1279 ( .A(n1319), .B(n1320), .Z(n1300));
+ AN2 U1280 ( .A(n1321), .B(n709), .Z(n1320));
+ AN2 U1281 ( .A(n927), .B(n924), .Z(n1321));
+ AN2 U1282 ( .A(pi04), .B(n1322), .Z(n1319));
+ OR2 U1283 ( .A(n1323), .B(n930), .Z(n1322));
+ AN2 U1284 ( .A(n939), .B(n1324), .Z(n930));
+ AN2 U1285 ( .A(n744), .B(pi11), .Z(n1324));
+ AN2 U1286 ( .A(n957), .B(n1041), .Z(n1323));
+ OR2 U1287 ( .A(n1325), .B(n1326), .Z(n1298));
+ OR2 U1288 ( .A(n937), .B(n1327), .Z(n1326));
+ AN2 U1289 ( .A(pi13), .B(n1328), .Z(n1327));
+ OR2 U1290 ( .A(n1329), .B(n1330), .Z(n1328));
+ AN2 U1291 ( .A(n1109), .B(n1166), .Z(n1330));
+ IV2 U1292 ( .A(pi12), .Z(n1166));
+ IV2 U1293 ( .A(n1165), .Z(n1109));
+ AN2 U1294 ( .A(pi12), .B(n1165), .Z(n1329));
+ OR2 U1295 ( .A(n1331), .B(n1332), .Z(n1165));
+ AN2 U1296 ( .A(pi13), .B(n1333), .Z(n1332));
+ OR2 U1297 ( .A(n1334), .B(n1335), .Z(n1333));
+ OR2 U1298 ( .A(n1336), .B(n1337), .Z(n1335));
+ AN2 U1299 ( .A(n1247), .B(n1257), .Z(n1337));
+ OR2 U1300 ( .A(n1338), .B(n780), .Z(n1257));
+ AN2 U1301 ( .A(n1023), .B(n751), .Z(n780));
+ AN2 U1302 ( .A(n944), .B(pi09), .Z(n1338));
+ AN2 U1303 ( .A(pi11), .B(n1339), .Z(n1336));
+ OR2 U1304 ( .A(n1340), .B(n1341), .Z(n1339));
+ OR2 U1305 ( .A(n1342), .B(n1343), .Z(n1341));
+ AN2 U1306 ( .A(n1344), .B(pi00), .Z(n1343));
+ AN2 U1307 ( .A(n1345), .B(n1247), .Z(n1344));
+ AN2 U1308 ( .A(pi10), .B(n1346), .Z(n1345));
+ AN2 U1309 ( .A(n1041), .B(n713), .Z(n1342));
+ IV2 U1310 ( .A(n1217), .Z(n1340));
+ OR2 U1311 ( .A(pi00), .B(n817), .Z(n1217));
+ OR2 U1312 ( .A(n1023), .B(n1346), .Z(n817));
+ OR2 U1313 ( .A(n1347), .B(n1348), .Z(n1334));
+ OR2 U1314 ( .A(n1349), .B(n1350), .Z(n1348));
+ AN2 U1315 ( .A(n1316), .B(n1023), .Z(n1350));
+ AN2 U1316 ( .A(n854), .B(n1351), .Z(n1349));
+ OR2 U1317 ( .A(n1352), .B(n1353), .Z(n1351));
+ AN2 U1318 ( .A(pi00), .B(n738), .Z(n1353));
+ AN2 U1319 ( .A(pi09), .B(n1041), .Z(n1352));
+ AN2 U1320 ( .A(n1248), .B(n1354), .Z(n1347));
+ OR2 U1321 ( .A(n1355), .B(n1356), .Z(n1354));
+ OR2 U1322 ( .A(n1357), .B(n1358), .Z(n1356));
+ AN2 U1323 ( .A(n1185), .B(n1041), .Z(n1358));
+ IV2 U1324 ( .A(n1092), .Z(n1185));
+ AN2 U1325 ( .A(n1247), .B(n1092), .Z(n1357));
+ OR2 U1326 ( .A(n1359), .B(n1360), .Z(n1092));
+ AN2 U1327 ( .A(n868), .B(n718), .Z(n1360));
+ AN2 U1328 ( .A(n1023), .B(n901), .Z(n868));
+ AN2 U1329 ( .A(n973), .B(pi11), .Z(n901));
+ AN2 U1330 ( .A(n869), .B(n1013), .Z(n1359));
+ AN2 U1331 ( .A(n1361), .B(n927), .Z(n869));
+ AN2 U1332 ( .A(n963), .B(pi08), .Z(n927));
+ IV2 U1333 ( .A(n1041), .Z(n1247));
+ AN2 U1334 ( .A(n1175), .B(n713), .Z(n1355));
+ IV2 U1335 ( .A(n1013), .Z(n1175));
+ AN2 U1336 ( .A(n1361), .B(n738), .Z(n1248));
+ AN2 U1337 ( .A(n1362), .B(n751), .Z(n1331));
+ AN2 U1338 ( .A(n902), .B(n1013), .Z(n1362));
+ OR2 U1339 ( .A(n1363), .B(n1364), .Z(n1013));
+ IV2 U1340 ( .A(n902), .Z(n1364));
+ AN2 U1341 ( .A(n1365), .B(n1366), .Z(n1363));
+ OR2 U1342 ( .A(n1188), .B(n857), .Z(n1366));
+ IV2 U1343 ( .A(n908), .Z(n857));
+ IV2 U1344 ( .A(n718), .Z(n1188));
+ AN2 U1345 ( .A(n1367), .B(n1368), .Z(n1365));
+ OR2 U1346 ( .A(n1346), .B(n1205), .Z(n1368));
+ IV2 U1347 ( .A(n1074), .Z(n1205));
+ IV2 U1348 ( .A(n751), .Z(n1346));
+ OR2 U1349 ( .A(n829), .B(n1041), .Z(n1367));
+ IV2 U1350 ( .A(n892), .Z(n829));
+ AN2 U1351 ( .A(n1309), .B(n1369), .Z(n937));
+ AN2 U1352 ( .A(pi13), .B(n751), .Z(n1369));
+ AN2 U1353 ( .A(n939), .B(n1370), .Z(n1325));
+ OR2 U1354 ( .A(n1371), .B(n1372), .Z(n1370));
+ OR2 U1355 ( .A(n1074), .B(n1373), .Z(n1372));
+ AN2 U1356 ( .A(n1374), .B(n944), .Z(n1373));
+ AN2 U1357 ( .A(n713), .B(n709), .Z(n1374));
+ AN2 U1358 ( .A(n1041), .B(pi00), .Z(n1074));
+ OR2 U1359 ( .A(n1375), .B(n1376), .Z(n1041));
+ OR2 U1360 ( .A(n1377), .B(n1378), .Z(n1376));
+ OR2 U1361 ( .A(n1379), .B(n1380), .Z(n1378));
+ AN2 U1362 ( .A(n949), .B(n709), .Z(n1380));
+ OR2 U1363 ( .A(n1381), .B(n1382), .Z(n949));
+ OR2 U1364 ( .A(n1383), .B(n1384), .Z(n1382));
+ AN2 U1365 ( .A(n751), .B(n963), .Z(n1384));
+ AN2 U1366 ( .A(n1385), .B(n860), .Z(n1383));
+ IV2 U1367 ( .A(n963), .Z(n860));
+ AN2 U1368 ( .A(n1386), .B(n924), .Z(n1381));
+ AN2 U1369 ( .A(n804), .B(n1361), .Z(n924));
+ AN2 U1370 ( .A(pi08), .B(pi10), .Z(n1386));
+ AN2 U1371 ( .A(n718), .B(n1140), .Z(n1379));
+ OR2 U1372 ( .A(n1387), .B(n981), .Z(n1140));
+ AN2 U1373 ( .A(pi11), .B(n1388), .Z(n981));
+ AN2 U1374 ( .A(n1023), .B(n1389), .Z(n1388));
+ OR2 U1375 ( .A(n751), .B(n892), .Z(n1389));
+ AN2 U1376 ( .A(n744), .B(n1361), .Z(n892));
+ AN2 U1377 ( .A(pi09), .B(pi08), .Z(n751));
+ AN2 U1378 ( .A(n944), .B(n1361), .Z(n1387));
+ AN2 U1379 ( .A(n744), .B(n963), .Z(n944));
+ AN2 U1380 ( .A(n784), .B(n1151), .Z(n1377));
+ AN2 U1381 ( .A(n713), .B(pi04), .Z(n1151));
+ AN2 U1382 ( .A(n973), .B(n902), .Z(n784));
+ AN2 U1383 ( .A(n963), .B(pi13), .Z(n902));
+ AN2 U1384 ( .A(n738), .B(pi10), .Z(n963));
+ OR2 U1385 ( .A(n1390), .B(n1391), .Z(n1375));
+ OR2 U1386 ( .A(n1392), .B(n1393), .Z(n1391));
+ AN2 U1387 ( .A(n950), .B(n1394), .Z(n1393));
+ OR2 U1388 ( .A(pi00), .B(pi04), .Z(n1394));
+ AN2 U1389 ( .A(n1395), .B(n908), .Z(n950));
+ AN2 U1390 ( .A(n1361), .B(pi08), .Z(n908));
+ IV2 U1391 ( .A(pi09), .Z(n1361));
+ OR2 U1392 ( .A(pi13), .B(n1309), .Z(n1395));
+ AN2 U1393 ( .A(n1023), .B(n738), .Z(n1309));
+ IV2 U1394 ( .A(pi11), .Z(n738));
+ AN2 U1395 ( .A(n1385), .B(n1316), .Z(n1392));
+ AN2 U1396 ( .A(n709), .B(pi00), .Z(n1316));
+ IV2 U1397 ( .A(pi04), .Z(n709));
+ AN2 U1398 ( .A(n973), .B(pi13), .Z(n1385));
+ AN2 U1399 ( .A(n744), .B(pi09), .Z(n973));
+ AN2 U1400 ( .A(n957), .B(n713), .Z(n1390));
+ IV2 U1401 ( .A(pi00), .Z(n713));
+ AN2 U1402 ( .A(n804), .B(n854), .Z(n957));
+ AN2 U1403 ( .A(n744), .B(n1023), .Z(n854));
+ IV2 U1404 ( .A(pi10), .Z(n1023));
+ AN2 U1405 ( .A(n718), .B(n982), .Z(n1371));
+ OR2 U1406 ( .A(n1396), .B(pi11), .Z(n982));
+ AN2 U1407 ( .A(pi10), .B(n744), .Z(n1396));
+ IV2 U1408 ( .A(pi08), .Z(n744));
+ AN2 U1409 ( .A(pi00), .B(pi04), .Z(n718));
+ AN2 U1410 ( .A(n804), .B(pi09), .Z(n939));
+ IV2 U1411 ( .A(pi13), .Z(n804));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/alu4.ys b/examples/smtbmc/glift/alu4.ys
new file mode 100644
index 000000000..8e8d14225
--- /dev/null
+++ b/examples/smtbmc/glift/alu4.ys
@@ -0,0 +1,41 @@
+read_verilog alu4.v
+techmap
+flatten
+select alu4_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename alu4_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog alu4.v
+techmap
+flatten
+select alu4_lev2
+glift -create-precise-model
+techmap
+opt
+rename alu4_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution alu4.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file alu4.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/mux2.ys b/examples/smtbmc/glift/mux2.ys
new file mode 100644
index 000000000..a8e99912b
--- /dev/null
+++ b/examples/smtbmc/glift/mux2.ys
@@ -0,0 +1,40 @@
+logger -expect log "SAT proof finished - no model found: SUCCESS!" 1
+logger -expect log "Number of cells:.*[\t ]12" 1
+logger -expect log "Number of cells:.*[\t ]20" 1
+logger -expect log "Problem is satisfiable with \\gate.__glift_weight = 11." 1
+logger -expect log "Problem is NOT satisfiable with \\gate.__glift_weight <= 10." 1
+logger -expect log "Wire \\gate.__glift_weight is minimized at 11." 1
+logger -expect log "Specializing .* from file with .* = 1." 2
+logger -expect log "Specializing .* from file with .* = 0." 4
+read_verilog <<EOT
+module mux2(a, b, s, y);
+ input a, b, s;
+ output y;
+
+ wire s_n = ~s;
+ wire t0 = s & a;
+ wire t1 = s_n & b;
+ assign y = t0 | t1;
+endmodule
+EOT
+techmap
+copy mux2 spec
+copy mux2 uut
+copy mux2 solved
+delete mux2
+glift -create-precise-model spec
+glift -create-instrumented-model uut
+glift -create-instrumented-model -no-cost-model solved
+design -push-copy
+miter -equiv spec uut qbfmiter
+flatten
+delete spec uut solved
+qbfsat -assume-outputs -assume-negative-polarity -write-solution mux2.soln qbfmiter
+design -pop
+qbfsat -specialize-from-file mux2.soln solved
+opt
+miter -equiv spec solved proofmiter
+flatten proofmiter
+sat -prove trigger 0 proofmiter
+delete proofmiter
+stat solved spec
diff --git a/examples/smtbmc/glift/t481.v b/examples/smtbmc/glift/t481.v
new file mode 100755
index 000000000..b23c8b211
--- /dev/null
+++ b/examples/smtbmc/glift/t481.v
@@ -0,0 +1,83 @@
+module t481_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, po0);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15;
+
+output po0;
+
+wire n46, n47, n48, n49, n50, n51, n52, n53, n54, n55,
+ n56, n57, n58, n59, n60, n61, n62, n63, n64, n65,
+ n66, n67, n68, n69, n70, n71, n72, n73, n74, n75,
+ n76, n77, n78, n79, n80, n81, n82, n83, n84, n85,
+ n86, n87, n88, n89, n90;
+
+ OR2 U47 ( .A(n46), .B(n47), .Z(po0));
+ OR2 U48 ( .A(n48), .B(n49), .Z(n47));
+ AN2 U49 ( .A(n50), .B(n51), .Z(n49));
+ OR2 U50 ( .A(n52), .B(n53), .Z(n51));
+ AN2 U51 ( .A(n54), .B(n55), .Z(n53));
+ AN2 U52 ( .A(n56), .B(n57), .Z(n54));
+ AN2 U53 ( .A(n58), .B(n59), .Z(n52));
+ AN2 U54 ( .A(n60), .B(n61), .Z(n48));
+ IV2 U55 ( .A(n50), .Z(n61));
+ AN2 U56 ( .A(n62), .B(pi15), .Z(n50));
+ IV2 U57 ( .A(pi14), .Z(n62));
+ OR2 U58 ( .A(n63), .B(n64), .Z(n60));
+ AN2 U59 ( .A(n65), .B(n55), .Z(n64));
+ IV2 U60 ( .A(n59), .Z(n55));
+ AN2 U61 ( .A(n57), .B(n58), .Z(n65));
+ IV2 U62 ( .A(n56), .Z(n58));
+ AN2 U63 ( .A(n56), .B(n59), .Z(n63));
+ AN2 U64 ( .A(n66), .B(pi00), .Z(n56));
+ IV2 U65 ( .A(pi01), .Z(n66));
+ AN2 U66 ( .A(n67), .B(n59), .Z(n46));
+ OR2 U67 ( .A(n68), .B(n69), .Z(n59));
+ OR2 U68 ( .A(n70), .B(n71), .Z(n69));
+ AN2 U69 ( .A(n72), .B(n73), .Z(n71));
+ IV2 U70 ( .A(n74), .Z(n70));
+ OR2 U71 ( .A(n73), .B(n72), .Z(n74));
+ AN2 U72 ( .A(n75), .B(pi12), .Z(n72));
+ IV2 U73 ( .A(pi13), .Z(n75));
+ OR2 U74 ( .A(pi10), .B(n76), .Z(n73));
+ IV2 U75 ( .A(pi11), .Z(n76));
+ AN2 U76 ( .A(n77), .B(n78), .Z(n68));
+ OR2 U77 ( .A(n79), .B(n80), .Z(n78));
+ IV2 U78 ( .A(n81), .Z(n77));
+ AN2 U79 ( .A(n80), .B(n79), .Z(n81));
+ AN2 U80 ( .A(n82), .B(pi08), .Z(n79));
+ IV2 U81 ( .A(pi09), .Z(n82));
+ OR2 U82 ( .A(pi06), .B(n83), .Z(n80));
+ IV2 U83 ( .A(pi07), .Z(n83));
+ IV2 U84 ( .A(n57), .Z(n67));
+ OR2 U85 ( .A(n84), .B(n85), .Z(n57));
+ AN2 U86 ( .A(n86), .B(n87), .Z(n85));
+ IV2 U87 ( .A(n88), .Z(n84));
+ OR2 U88 ( .A(n87), .B(n86), .Z(n88));
+ AN2 U89 ( .A(n89), .B(pi04), .Z(n86));
+ IV2 U90 ( .A(pi05), .Z(n89));
+ OR2 U91 ( .A(pi02), .B(n90), .Z(n87));
+ IV2 U92 ( .A(pi03), .Z(n90));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/t481.ys b/examples/smtbmc/glift/t481.ys
new file mode 100644
index 000000000..0e4afffda
--- /dev/null
+++ b/examples/smtbmc/glift/t481.ys
@@ -0,0 +1,41 @@
+read_verilog t481.v
+techmap
+flatten
+select t481_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename t481_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog t481.v
+techmap
+flatten
+select t481_lev2
+glift -create-precise-model
+techmap
+opt
+rename t481_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution t481.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file t481.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/too_large.v b/examples/smtbmc/glift/too_large.v
new file mode 100755
index 000000000..67605cc34
--- /dev/null
+++ b/examples/smtbmc/glift/too_large.v
@@ -0,0 +1,345 @@
+module too_large_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, po0, po1,
+ po2);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37;
+
+output po0, po1, po2;
+
+wire n280, n281, n282, n283, n284, n285, n286, n287, n288, n289,
+ n290, n291, n292, n293, n294, n295, n296, n297, n298, n299,
+ n300, n301, n302, n303, n304, n305, n306, n307, n308, n309,
+ n310, n311, n312, n313, n314, n315, n316, n317, n318, n319,
+ n320, n321, n322, n323, n324, n325, n326, n327, n328, n329,
+ n330, n331, n332, n333, n334, n335, n336, n337, n338, n339,
+ n340, n341, n342, n343, n344, n345, n346, n347, n348, n349,
+ n350, n351, n352, n353, n354, n355, n356, n357, n358, n359,
+ n360, n361, n362, n363, n364, n365, n366, n367, n368, n369,
+ n370, n371, n372, n373, n374, n375, n376, n377, n378, n379,
+ n380, n381, n382, n383, n384, n385, n386, n387, n388, n389,
+ n390, n391, n392, n393, n394, n395, n396, n397, n398, n399,
+ n400, n401, n402, n403, n404, n405, n406, n407, n408, n409,
+ n410, n411, n412, n413, n414, n415, n416, n417, n418, n419,
+ n420, n421, n422, n423, n424, n425, n426, n427, n428, n429,
+ n430, n431, n432, n433, n434, n435, n436, n437, n438, n439,
+ n440, n441, n442, n443, n444, n445, n446, n447, n448, n449,
+ n450, n451, n452, n453, n454, n455, n456, n457, n458, n459,
+ n460, n461, n462, n463, n464, n465, n466, n467, n468, n469,
+ n470, n471, n472, n473, n474, n475, n476, n477, n478, n479,
+ n480, n481, n482, n483, n484, n485, n486, n487, n488, n489,
+ n490, n491, n492, n493, n494, n495, n496, n497, n498, n499,
+ n500, n501, n502, n503, n504, n505, n506, n507, n508, n509,
+ n510, n511, n512, n513, n514, n515, n516, n517, n518, n519,
+ n520, n521, n522, n523, n524, n525, n526, n527, n528, n529,
+ n530, n531, n532, n533, n534, n535, n536, n537, n538, n539,
+ n540, n541, n542, n543, n544, n545, n546, n547, n548, n549,
+ n550, n551, n552, n553, n554, n555, n556;
+
+ AN2 U283 ( .A(n280), .B(n281), .Z(po2));
+ OR2 U284 ( .A(n282), .B(n283), .Z(n280));
+ OR2 U285 ( .A(n284), .B(n285), .Z(n283));
+ AN2 U286 ( .A(n286), .B(n287), .Z(n285));
+ OR2 U287 ( .A(n288), .B(n289), .Z(n287));
+ OR2 U288 ( .A(n290), .B(n291), .Z(n289));
+ AN2 U289 ( .A(pi29), .B(n292), .Z(n291));
+ AN2 U290 ( .A(n293), .B(pi35), .Z(n290));
+ AN2 U291 ( .A(n294), .B(n295), .Z(n293));
+ OR2 U292 ( .A(pi29), .B(n296), .Z(n294));
+ AN2 U293 ( .A(n297), .B(pi18), .Z(n284));
+ AN2 U294 ( .A(n298), .B(n299), .Z(n297));
+ IV2 U295 ( .A(n300), .Z(n299));
+ OR2 U296 ( .A(n301), .B(n302), .Z(n298));
+ AN2 U297 ( .A(n303), .B(n304), .Z(n302));
+ OR2 U298 ( .A(n305), .B(n306), .Z(n304));
+ AN2 U299 ( .A(n307), .B(n308), .Z(n306));
+ AN2 U300 ( .A(n309), .B(n310), .Z(n305));
+ OR2 U301 ( .A(n311), .B(n312), .Z(n310));
+ AN2 U302 ( .A(n308), .B(n313), .Z(n312));
+ OR2 U303 ( .A(n314), .B(n315), .Z(n308));
+ AN2 U304 ( .A(n316), .B(n317), .Z(n311));
+ AN2 U305 ( .A(n318), .B(n319), .Z(n317));
+ AN2 U306 ( .A(pi15), .B(n315), .Z(n316));
+ OR2 U307 ( .A(n320), .B(n321), .Z(n315));
+ AN2 U308 ( .A(n322), .B(n323), .Z(n309));
+ OR2 U309 ( .A(n324), .B(n325), .Z(n322));
+ AN2 U310 ( .A(n326), .B(n327), .Z(n301));
+ OR2 U311 ( .A(n328), .B(n307), .Z(n327));
+ AN2 U312 ( .A(n329), .B(n323), .Z(n328));
+ OR2 U313 ( .A(n330), .B(n331), .Z(n329));
+ AN2 U314 ( .A(n332), .B(n313), .Z(n331));
+ OR2 U315 ( .A(n333), .B(n325), .Z(n332));
+ AN2 U316 ( .A(n324), .B(n334), .Z(n333));
+ IV2 U317 ( .A(n335), .Z(n334));
+ AN2 U318 ( .A(n336), .B(pi08), .Z(n335));
+ OR2 U319 ( .A(n320), .B(n314), .Z(n336));
+ AN2 U320 ( .A(n337), .B(n338), .Z(n314));
+ OR2 U321 ( .A(pi20), .B(n339), .Z(n337));
+ AN2 U322 ( .A(n340), .B(n341), .Z(n330));
+ AN2 U323 ( .A(n342), .B(n319), .Z(n341));
+ OR2 U324 ( .A(n343), .B(n325), .Z(n342));
+ AN2 U325 ( .A(n324), .B(n344), .Z(n343));
+ IV2 U326 ( .A(n345), .Z(n344));
+ AN2 U327 ( .A(n346), .B(n295), .Z(n324));
+ AN2 U328 ( .A(pi15), .B(n318), .Z(n340));
+ OR2 U329 ( .A(n347), .B(n348), .Z(n318));
+ AN2 U330 ( .A(n349), .B(n350), .Z(n347));
+ AN2 U331 ( .A(n351), .B(n352), .Z(n326));
+ OR2 U332 ( .A(n353), .B(n354), .Z(n282));
+ AN2 U333 ( .A(n355), .B(n356), .Z(n354));
+ AN2 U334 ( .A(n357), .B(n358), .Z(n355));
+ OR2 U335 ( .A(pi26), .B(pi27), .Z(n357));
+ AN2 U336 ( .A(n359), .B(n360), .Z(n353));
+ OR2 U337 ( .A(n361), .B(n362), .Z(n360));
+ AN2 U338 ( .A(n288), .B(n363), .Z(n362));
+ OR2 U339 ( .A(n364), .B(n365), .Z(n288));
+ AN2 U340 ( .A(n292), .B(n296), .Z(n364));
+ OR2 U341 ( .A(n366), .B(n367), .Z(n296));
+ IV2 U342 ( .A(n368), .Z(n367));
+ AN2 U343 ( .A(n369), .B(n370), .Z(n368));
+ OR2 U344 ( .A(pi33), .B(pi22), .Z(n366));
+ AN2 U345 ( .A(pi29), .B(n371), .Z(n361));
+ OR2 U346 ( .A(n372), .B(n373), .Z(n371));
+ AN2 U347 ( .A(n374), .B(n292), .Z(n372));
+ IV2 U348 ( .A(n356), .Z(n359));
+ AN2 U349 ( .A(n295), .B(pi35), .Z(n356));
+ IV2 U350 ( .A(pi28), .Z(n295));
+ OR2 U351 ( .A(n375), .B(n376), .Z(po1));
+ OR2 U352 ( .A(n377), .B(n378), .Z(n376));
+ AN2 U353 ( .A(n379), .B(n380), .Z(n378));
+ AN2 U354 ( .A(n381), .B(n382), .Z(n380));
+ IV2 U355 ( .A(n365), .Z(n382));
+ AN2 U356 ( .A(n383), .B(pi05), .Z(n379));
+ AN2 U357 ( .A(n384), .B(n385), .Z(n377));
+ OR2 U358 ( .A(n386), .B(n387), .Z(n385));
+ AN2 U359 ( .A(n388), .B(n369), .Z(n387));
+ OR2 U360 ( .A(n389), .B(n390), .Z(n388));
+ AN2 U361 ( .A(n391), .B(n370), .Z(n390));
+ OR2 U362 ( .A(n392), .B(n393), .Z(n391));
+ OR2 U363 ( .A(n394), .B(n395), .Z(n393));
+ AN2 U364 ( .A(n396), .B(pi35), .Z(n395));
+ AN2 U365 ( .A(n397), .B(n358), .Z(n396));
+ AN2 U366 ( .A(n398), .B(n399), .Z(n394));
+ IV2 U367 ( .A(n400), .Z(n399));
+ AN2 U368 ( .A(n286), .B(pi08), .Z(n398));
+ AN2 U369 ( .A(n401), .B(n402), .Z(n392));
+ OR2 U370 ( .A(n403), .B(n286), .Z(n402));
+ AN2 U371 ( .A(n400), .B(n363), .Z(n403));
+ OR2 U372 ( .A(n404), .B(n300), .Z(n401));
+ AN2 U373 ( .A(pi37), .B(pi13), .Z(n404));
+ AN2 U374 ( .A(n405), .B(n406), .Z(n389));
+ AN2 U375 ( .A(n407), .B(n352), .Z(n406));
+ AN2 U376 ( .A(pi05), .B(n408), .Z(n405));
+ OR2 U377 ( .A(n409), .B(n410), .Z(n408));
+ AN2 U378 ( .A(n411), .B(n351), .Z(n410));
+ AN2 U379 ( .A(n412), .B(n413), .Z(n409));
+ OR2 U380 ( .A(n414), .B(n415), .Z(n412));
+ AN2 U381 ( .A(n416), .B(n351), .Z(n415));
+ OR2 U382 ( .A(n417), .B(n418), .Z(n416));
+ AN2 U383 ( .A(n286), .B(n319), .Z(n417));
+ AN2 U384 ( .A(n419), .B(n420), .Z(n414));
+ AN2 U385 ( .A(pi02), .B(n421), .Z(n419));
+ AN2 U386 ( .A(n422), .B(n423), .Z(n386));
+ AN2 U387 ( .A(n424), .B(n425), .Z(n423));
+ OR2 U388 ( .A(n426), .B(n427), .Z(n425));
+ AN2 U389 ( .A(n428), .B(n429), .Z(n427));
+ AN2 U390 ( .A(n430), .B(n407), .Z(n426));
+ IV2 U391 ( .A(n431), .Z(n407));
+ AN2 U392 ( .A(n432), .B(pi21), .Z(n431));
+ OR2 U393 ( .A(pi01), .B(pi20), .Z(n432));
+ OR2 U394 ( .A(n433), .B(n434), .Z(n430));
+ AN2 U395 ( .A(n429), .B(n339), .Z(n433));
+ OR2 U396 ( .A(n435), .B(n411), .Z(n424));
+ AN2 U397 ( .A(n436), .B(n437), .Z(n411));
+ AN2 U398 ( .A(n438), .B(n286), .Z(n437));
+ IV2 U399 ( .A(n439), .Z(n436));
+ OR2 U400 ( .A(pi26), .B(pi06), .Z(n439));
+ AN2 U401 ( .A(pi05), .B(n303), .Z(n422));
+ AN2 U402 ( .A(n440), .B(n441), .Z(n375));
+ OR2 U403 ( .A(n442), .B(n443), .Z(n441));
+ AN2 U404 ( .A(pi35), .B(n397), .Z(n443));
+ OR2 U405 ( .A(pi27), .B(pi28), .Z(n397));
+ AN2 U406 ( .A(n300), .B(n400), .Z(n442));
+ OR2 U407 ( .A(pi26), .B(n413), .Z(n400));
+ OR2 U408 ( .A(n444), .B(n445), .Z(po0));
+ OR2 U409 ( .A(n446), .B(n447), .Z(n445));
+ AN2 U410 ( .A(n448), .B(pi04), .Z(n447));
+ AN2 U411 ( .A(n383), .B(n381), .Z(n448));
+ OR2 U412 ( .A(n449), .B(n450), .Z(n381));
+ AN2 U413 ( .A(n420), .B(n451), .Z(n450));
+ AN2 U414 ( .A(n452), .B(n453), .Z(n449));
+ OR2 U415 ( .A(n454), .B(n374), .Z(n452));
+ AN2 U416 ( .A(n373), .B(n455), .Z(n454));
+ AN2 U417 ( .A(n456), .B(n457), .Z(n383));
+ AN2 U418 ( .A(n413), .B(n281), .Z(n457));
+ AN2 U419 ( .A(n384), .B(n458), .Z(n446));
+ OR2 U420 ( .A(n459), .B(n460), .Z(n458));
+ OR2 U421 ( .A(n461), .B(n462), .Z(n460));
+ AN2 U422 ( .A(n463), .B(n369), .Z(n462));
+ OR2 U423 ( .A(n464), .B(n465), .Z(n463));
+ AN2 U424 ( .A(n466), .B(n467), .Z(n465));
+ OR2 U425 ( .A(n468), .B(n469), .Z(n467));
+ OR2 U426 ( .A(n470), .B(n471), .Z(n469));
+ AN2 U427 ( .A(n365), .B(n350), .Z(n471));
+ AN2 U428 ( .A(n472), .B(pi37), .Z(n470));
+ AN2 U429 ( .A(pi13), .B(n473), .Z(n472));
+ OR2 U430 ( .A(n474), .B(n475), .Z(n473));
+ AN2 U431 ( .A(n370), .B(n338), .Z(n475));
+ AN2 U432 ( .A(pi16), .B(n476), .Z(n474));
+ OR2 U433 ( .A(n477), .B(n428), .Z(n476));
+ AN2 U434 ( .A(n478), .B(n350), .Z(n477));
+ AN2 U435 ( .A(n300), .B(n479), .Z(n468));
+ OR2 U436 ( .A(n480), .B(n286), .Z(n466));
+ AN2 U437 ( .A(n481), .B(n363), .Z(n480));
+ AN2 U438 ( .A(n482), .B(n483), .Z(n464));
+ AN2 U439 ( .A(n370), .B(n358), .Z(n482));
+ AN2 U440 ( .A(n484), .B(n485), .Z(n461));
+ AN2 U441 ( .A(n286), .B(n486), .Z(n484));
+ OR2 U442 ( .A(n487), .B(n488), .Z(n486));
+ AN2 U443 ( .A(n489), .B(n370), .Z(n488));
+ OR2 U444 ( .A(n490), .B(n345), .Z(n489));
+ AN2 U445 ( .A(n320), .B(pi08), .Z(n345));
+ AN2 U446 ( .A(pi06), .B(n369), .Z(n490));
+ AN2 U447 ( .A(n491), .B(n429), .Z(n487));
+ AN2 U448 ( .A(pi08), .B(n492), .Z(n491));
+ AN2 U449 ( .A(pi04), .B(n493), .Z(n459));
+ OR2 U450 ( .A(n494), .B(n495), .Z(n493));
+ AN2 U451 ( .A(n303), .B(n496), .Z(n495));
+ OR2 U452 ( .A(n497), .B(n498), .Z(n496));
+ AN2 U453 ( .A(n499), .B(n500), .Z(n498));
+ OR2 U454 ( .A(n501), .B(n307), .Z(n500));
+ AN2 U455 ( .A(n374), .B(n502), .Z(n307));
+ AN2 U456 ( .A(n413), .B(n453), .Z(n502));
+ AN2 U457 ( .A(n503), .B(n313), .Z(n501));
+ OR2 U458 ( .A(n504), .B(n505), .Z(n503));
+ AN2 U459 ( .A(n325), .B(n323), .Z(n504));
+ AN2 U460 ( .A(n413), .B(n506), .Z(n325));
+ AN2 U461 ( .A(n434), .B(n370), .Z(n499));
+ OR2 U462 ( .A(n507), .B(n320), .Z(n434));
+ AN2 U463 ( .A(n321), .B(n508), .Z(n507));
+ IV2 U464 ( .A(pi07), .Z(n321));
+ AN2 U465 ( .A(n509), .B(n429), .Z(n497));
+ AN2 U466 ( .A(n508), .B(n338), .Z(n429));
+ IV2 U467 ( .A(pi15), .Z(n338));
+ AN2 U468 ( .A(n510), .B(n492), .Z(n509));
+ OR2 U469 ( .A(n511), .B(n428), .Z(n492));
+ AN2 U470 ( .A(n479), .B(pi20), .Z(n428));
+ AN2 U471 ( .A(n339), .B(n350), .Z(n511));
+ OR2 U472 ( .A(n478), .B(n348), .Z(n339));
+ IV2 U473 ( .A(pi16), .Z(n348));
+ IV2 U474 ( .A(n349), .Z(n478));
+ AN2 U475 ( .A(n512), .B(n513), .Z(n349));
+ OR2 U476 ( .A(pi25), .B(pi17), .Z(n513));
+ OR2 U477 ( .A(n514), .B(pi24), .Z(n512));
+ IV2 U478 ( .A(pi09), .Z(n514));
+ OR2 U479 ( .A(n515), .B(n435), .Z(n510));
+ AN2 U480 ( .A(n516), .B(n413), .Z(n435));
+ OR2 U481 ( .A(n517), .B(n418), .Z(n516));
+ AN2 U482 ( .A(n363), .B(n453), .Z(n418));
+ OR2 U483 ( .A(n373), .B(n374), .Z(n363));
+ AN2 U484 ( .A(n323), .B(pi02), .Z(n373));
+ AN2 U485 ( .A(n505), .B(n438), .Z(n515));
+ OR2 U486 ( .A(n453), .B(n319), .Z(n438));
+ IV2 U487 ( .A(n518), .Z(n303));
+ OR2 U488 ( .A(n519), .B(n520), .Z(n518));
+ OR2 U489 ( .A(pi08), .B(n521), .Z(n520));
+ OR2 U490 ( .A(pi10), .B(n522), .Z(n519));
+ OR2 U491 ( .A(pi12), .B(pi11), .Z(n522));
+ AN2 U492 ( .A(n523), .B(n524), .Z(n494));
+ OR2 U493 ( .A(n525), .B(n526), .Z(n524));
+ AN2 U494 ( .A(n527), .B(n528), .Z(n526));
+ OR2 U495 ( .A(n529), .B(n530), .Z(n528));
+ AN2 U496 ( .A(n531), .B(n351), .Z(n530));
+ AN2 U497 ( .A(n358), .B(n453), .Z(n531));
+ OR2 U498 ( .A(n532), .B(n374), .Z(n358));
+ AN2 U499 ( .A(n506), .B(n323), .Z(n532));
+ AN2 U500 ( .A(n517), .B(n533), .Z(n529));
+ AN2 U501 ( .A(n421), .B(n534), .Z(n533));
+ IV2 U502 ( .A(pi14), .Z(n421));
+ AN2 U503 ( .A(n420), .B(n506), .Z(n517));
+ OR2 U504 ( .A(pi02), .B(n346), .Z(n506));
+ AN2 U505 ( .A(n323), .B(n319), .Z(n420));
+ AN2 U506 ( .A(n369), .B(n413), .Z(n527));
+ OR2 U507 ( .A(n320), .B(n508), .Z(n369));
+ AN2 U508 ( .A(n535), .B(n536), .Z(n525));
+ AN2 U509 ( .A(n313), .B(n351), .Z(n536));
+ IV2 U510 ( .A(n521), .Z(n351));
+ AN2 U511 ( .A(pi00), .B(pi14), .Z(n521));
+ OR2 U512 ( .A(n537), .B(n453), .Z(n313));
+ IV2 U513 ( .A(pi13), .Z(n453));
+ AN2 U514 ( .A(n319), .B(n534), .Z(n537));
+ IV2 U515 ( .A(pi37), .Z(n534));
+ IV2 U516 ( .A(pi03), .Z(n319));
+ AN2 U517 ( .A(n505), .B(n538), .Z(n535));
+ OR2 U518 ( .A(n539), .B(n320), .Z(n538));
+ IV2 U519 ( .A(pi19), .Z(n320));
+ AN2 U520 ( .A(n540), .B(n508), .Z(n539));
+ IV2 U521 ( .A(pi23), .Z(n508));
+ IV2 U522 ( .A(pi08), .Z(n540));
+ AN2 U523 ( .A(n541), .B(n286), .Z(n505));
+ AN2 U524 ( .A(n346), .B(n323), .Z(n286));
+ IV2 U525 ( .A(pi27), .Z(n541));
+ AN2 U526 ( .A(n370), .B(n352), .Z(n523));
+ IV2 U527 ( .A(pi36), .Z(n352));
+ OR2 U528 ( .A(n350), .B(n479), .Z(n370));
+ IV2 U529 ( .A(pi21), .Z(n479));
+ IV2 U530 ( .A(pi20), .Z(n350));
+ IV2 U531 ( .A(n542), .Z(n384));
+ OR2 U532 ( .A(n543), .B(n544), .Z(n542));
+ OR2 U533 ( .A(pi29), .B(pi22), .Z(n544));
+ OR2 U534 ( .A(pi34), .B(pi33), .Z(n543));
+ AN2 U535 ( .A(n440), .B(n545), .Z(n444));
+ OR2 U536 ( .A(n546), .B(n483), .Z(n545));
+ OR2 U537 ( .A(n547), .B(n548), .Z(n483));
+ AN2 U538 ( .A(pi28), .B(pi35), .Z(n548));
+ AN2 U539 ( .A(pi26), .B(n485), .Z(n547));
+ IV2 U540 ( .A(n481), .Z(n485));
+ AN2 U541 ( .A(n549), .B(n481), .Z(n546));
+ OR2 U542 ( .A(pi27), .B(n413), .Z(n481));
+ IV2 U543 ( .A(pi35), .Z(n413));
+ OR2 U544 ( .A(n365), .B(n300), .Z(n549));
+ AN2 U545 ( .A(pi01), .B(pi31), .Z(n300));
+ AN2 U546 ( .A(pi01), .B(pi21), .Z(n365));
+ AN2 U547 ( .A(n456), .B(n550), .Z(n440));
+ AN2 U548 ( .A(n281), .B(n551), .Z(n550));
+ OR2 U549 ( .A(n374), .B(n552), .Z(n551));
+ AN2 U550 ( .A(n323), .B(n451), .Z(n552));
+ OR2 U551 ( .A(n553), .B(n554), .Z(n451));
+ AN2 U552 ( .A(n555), .B(n346), .Z(n554));
+ IV2 U553 ( .A(pi32), .Z(n346));
+ AN2 U554 ( .A(pi02), .B(n455), .Z(n553));
+ IV2 U555 ( .A(pi29), .Z(n455));
+ IV2 U556 ( .A(pi30), .Z(n323));
+ AN2 U557 ( .A(n555), .B(pi03), .Z(n374));
+ IV2 U558 ( .A(pi02), .Z(n555));
+ IV2 U559 ( .A(pi34), .Z(n281));
+ IV2 U560 ( .A(n292), .Z(n456));
+ OR2 U561 ( .A(pi00), .B(n556), .Z(n292));
+ OR2 U562 ( .A(pi37), .B(pi36), .Z(n556));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/too_large.ys b/examples/smtbmc/glift/too_large.ys
new file mode 100644
index 000000000..77be61e17
--- /dev/null
+++ b/examples/smtbmc/glift/too_large.ys
@@ -0,0 +1,41 @@
+read_verilog too_large.v
+techmap
+flatten
+select too_large_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename too_large_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog too_large.v
+techmap
+flatten
+select too_large_lev2
+glift -create-precise-model
+techmap
+opt
+rename too_large_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution too_large.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file too_large.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/ttt2.v b/examples/smtbmc/glift/ttt2.v
new file mode 100755
index 000000000..47ca7684a
--- /dev/null
+++ b/examples/smtbmc/glift/ttt2.v
@@ -0,0 +1,220 @@
+module ttt2_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, po00, po01, po02, po03, po04, po05,
+ po06, po07, po08, po09, po10, po11, po12, po13, po14, po15,
+ po16, po17, po18, po19, po20);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23;
+
+output po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20;
+
+wire n148, n149, n150, n151, n152, n153, n154, n155, n156, n157,
+ n158, n159, n160, n161, n162, n163, n164, n165, n166, n167,
+ n168, n169, n170, n171, n172, n173, n174, n175, n176, n177,
+ n178, n179, n180, n181, n182, n183, n184, n185, n186, n187,
+ n188, n189, n190, n191, n192, n193, n194, n195, n196, n197,
+ n198, n199, n200, n201, n202, n203, n204, n205, n206, n207,
+ n208, n209, n210, n211, n212, n213, n214, n215, n216, n217,
+ n218, n219, n220, n221, n222, n223, n224, n225, n226, n227,
+ n228, n229, n230, n231, n232, n233, n234, n235, n236, n237,
+ n238, n239, n240, n241, n242, n243, n244, n245, n246, n247,
+ n248, n249, n250, n251, n252, n253, n254, n255, n256, n257,
+ n258, n259, n260, n261, n262, n263, n264, n265, n266, n267,
+ n268, n269, n270, n271, n272, n273, n274, n275, n276, n277,
+ n278, n279, n280, n281, n282, n283, n284, n285, n286, n287,
+ n288, n289, n290, n291, n292, n293;
+
+ AN2 U168 ( .A(n148), .B(n149), .Z(po20));
+ OR2 U169 ( .A(n150), .B(n151), .Z(n148));
+ AN2 U170 ( .A(pi02), .B(n152), .Z(n151));
+ IV2 U171 ( .A(n153), .Z(n150));
+ OR2 U172 ( .A(n152), .B(pi02), .Z(n153));
+ IV2 U173 ( .A(pi23), .Z(n152));
+ AN2 U174 ( .A(n154), .B(n149), .Z(po19));
+ OR2 U175 ( .A(n155), .B(n156), .Z(n154));
+ AN2 U176 ( .A(pi01), .B(n157), .Z(n156));
+ AN2 U177 ( .A(pi22), .B(n158), .Z(n155));
+ IV2 U178 ( .A(pi01), .Z(n158));
+ AN2 U179 ( .A(n159), .B(n149), .Z(po18));
+ OR2 U180 ( .A(n160), .B(n161), .Z(po17));
+ AN2 U181 ( .A(pi20), .B(n162), .Z(n161));
+ OR2 U182 ( .A(n163), .B(n164), .Z(n162));
+ OR2 U183 ( .A(n165), .B(n166), .Z(n164));
+ AN2 U184 ( .A(n167), .B(pi18), .Z(n166));
+ AN2 U185 ( .A(n149), .B(n168), .Z(n167));
+ AN2 U186 ( .A(n169), .B(n170), .Z(n160));
+ AN2 U187 ( .A(n171), .B(n172), .Z(n169));
+ OR2 U188 ( .A(n165), .B(n173), .Z(po16));
+ OR2 U189 ( .A(n174), .B(n175), .Z(n173));
+ AN2 U190 ( .A(n176), .B(n168), .Z(n175));
+ AN2 U191 ( .A(n170), .B(n171), .Z(n176));
+ AN2 U192 ( .A(pi19), .B(n163), .Z(n174));
+ AN2 U193 ( .A(pi19), .B(n177), .Z(n165));
+ AN2 U194 ( .A(n178), .B(n149), .Z(n177));
+ OR2 U195 ( .A(n179), .B(n180), .Z(po15));
+ AN2 U196 ( .A(n181), .B(n178), .Z(n180));
+ AN2 U197 ( .A(n182), .B(n170), .Z(n181));
+ AN2 U198 ( .A(pi17), .B(n183), .Z(n182));
+ OR2 U199 ( .A(pi19), .B(n184), .Z(n183));
+ AN2 U200 ( .A(pi18), .B(n163), .Z(n179));
+ OR2 U201 ( .A(n185), .B(n186), .Z(n163));
+ AN2 U202 ( .A(n149), .B(n187), .Z(n185));
+ OR2 U203 ( .A(n188), .B(n189), .Z(po14));
+ AN2 U204 ( .A(pi17), .B(n186), .Z(n189));
+ OR2 U205 ( .A(n190), .B(n191), .Z(n186));
+ AN2 U206 ( .A(n192), .B(n149), .Z(n190));
+ OR2 U207 ( .A(pi14), .B(n193), .Z(n192));
+ AN2 U208 ( .A(n170), .B(n187), .Z(n188));
+ AN2 U209 ( .A(n194), .B(n195), .Z(n170));
+ AN2 U210 ( .A(n196), .B(n197), .Z(n195));
+ OR2 U211 ( .A(n198), .B(n199), .Z(po13));
+ AN2 U212 ( .A(pi16), .B(n200), .Z(n199));
+ OR2 U213 ( .A(n201), .B(n191), .Z(n200));
+ AN2 U214 ( .A(n202), .B(pi14), .Z(n198));
+ AN2 U215 ( .A(n203), .B(n149), .Z(n202));
+ OR2 U216 ( .A(n204), .B(n197), .Z(n203));
+ IV2 U217 ( .A(n193), .Z(n197));
+ AN2 U218 ( .A(n205), .B(n206), .Z(n204));
+ AN2 U219 ( .A(n207), .B(n208), .Z(n206));
+ AN2 U220 ( .A(pi15), .B(pi13), .Z(n205));
+ OR2 U221 ( .A(n201), .B(n209), .Z(po12));
+ OR2 U222 ( .A(n210), .B(n211), .Z(n209));
+ AN2 U223 ( .A(n212), .B(n213), .Z(n211));
+ AN2 U224 ( .A(pi14), .B(n194), .Z(n212));
+ AN2 U225 ( .A(pi15), .B(n191), .Z(n210));
+ AN2 U226 ( .A(pi15), .B(n214), .Z(n201));
+ AN2 U227 ( .A(n196), .B(n149), .Z(n214));
+ OR2 U228 ( .A(n215), .B(n216), .Z(po11));
+ AN2 U229 ( .A(n217), .B(n196), .Z(n216));
+ IV2 U230 ( .A(pi14), .Z(n196));
+ AN2 U231 ( .A(n194), .B(n193), .Z(n217));
+ OR2 U232 ( .A(pi15), .B(n208), .Z(n193));
+ IV2 U233 ( .A(pi16), .Z(n208));
+ AN2 U234 ( .A(pi13), .B(n218), .Z(n194));
+ AN2 U235 ( .A(pi14), .B(n191), .Z(n215));
+ OR2 U236 ( .A(n219), .B(n220), .Z(n191));
+ AN2 U237 ( .A(n149), .B(n221), .Z(n220));
+ OR2 U238 ( .A(n222), .B(n223), .Z(po10));
+ AN2 U239 ( .A(n219), .B(pi13), .Z(n223));
+ AN2 U240 ( .A(n224), .B(n157), .Z(n219));
+ IV2 U241 ( .A(pi22), .Z(n157));
+ OR2 U242 ( .A(n225), .B(n226), .Z(n224));
+ OR2 U243 ( .A(po06), .B(n227), .Z(n226));
+ AN2 U244 ( .A(n218), .B(n221), .Z(n222));
+ IV2 U245 ( .A(pi13), .Z(n221));
+ AN2 U246 ( .A(n207), .B(n149), .Z(n218));
+ OR2 U247 ( .A(n228), .B(pi22), .Z(n207));
+ AN2 U248 ( .A(n229), .B(pi09), .Z(n228));
+ AN2 U249 ( .A(n230), .B(n231), .Z(n229));
+ OR2 U250 ( .A(n232), .B(n233), .Z(po09));
+ AN2 U251 ( .A(pi12), .B(n234), .Z(n233));
+ OR2 U252 ( .A(n235), .B(po06), .Z(n234));
+ AN2 U253 ( .A(n227), .B(n236), .Z(n232));
+ OR2 U254 ( .A(n237), .B(n230), .Z(n236));
+ AN2 U255 ( .A(n238), .B(pi11), .Z(n237));
+ AN2 U256 ( .A(pi09), .B(n239), .Z(n238));
+ IV2 U257 ( .A(pi12), .Z(n239));
+ OR2 U258 ( .A(n235), .B(n240), .Z(po08));
+ OR2 U259 ( .A(n241), .B(n242), .Z(n240));
+ AN2 U260 ( .A(po06), .B(pi11), .Z(n242));
+ AN2 U261 ( .A(n243), .B(n244), .Z(n241));
+ AN2 U262 ( .A(n227), .B(pi09), .Z(n243));
+ AN2 U263 ( .A(n149), .B(pi10), .Z(n227));
+ AN2 U264 ( .A(pi11), .B(n245), .Z(n235));
+ AN2 U265 ( .A(n231), .B(n149), .Z(n245));
+ OR2 U266 ( .A(n246), .B(n247), .Z(po07));
+ AN2 U267 ( .A(po06), .B(pi10), .Z(n247));
+ AN2 U268 ( .A(n248), .B(n231), .Z(n246));
+ IV2 U269 ( .A(pi10), .Z(n231));
+ AN2 U270 ( .A(n225), .B(pi09), .Z(n248));
+ AN2 U271 ( .A(n249), .B(n149), .Z(n225));
+ IV2 U272 ( .A(n230), .Z(n249));
+ AN2 U273 ( .A(n244), .B(pi12), .Z(n230));
+ IV2 U274 ( .A(pi11), .Z(n244));
+ AN2 U275 ( .A(n250), .B(n149), .Z(po06));
+ IV2 U276 ( .A(pi00), .Z(n149));
+ IV2 U277 ( .A(pi09), .Z(n250));
+ AN2 U278 ( .A(n251), .B(n252), .Z(po05));
+ OR2 U279 ( .A(n253), .B(n254), .Z(n251));
+ OR2 U280 ( .A(n255), .B(n256), .Z(n254));
+ AN2 U281 ( .A(n257), .B(n187), .Z(n255));
+ AN2 U282 ( .A(pi08), .B(n258), .Z(n253));
+ OR2 U283 ( .A(n259), .B(n260), .Z(po04));
+ AN2 U284 ( .A(pi07), .B(n261), .Z(n260));
+ AN2 U285 ( .A(n262), .B(n257), .Z(n259));
+ AN2 U286 ( .A(n171), .B(n252), .Z(n262));
+ AN2 U287 ( .A(pi17), .B(pi18), .Z(n171));
+ OR2 U288 ( .A(n263), .B(n264), .Z(po03));
+ OR2 U289 ( .A(n265), .B(n266), .Z(n264));
+ AN2 U290 ( .A(pi06), .B(n261), .Z(n266));
+ AN2 U291 ( .A(n267), .B(n213), .Z(n265));
+ OR2 U292 ( .A(n172), .B(pi21), .Z(n267));
+ OR2 U293 ( .A(n268), .B(n269), .Z(n263));
+ OR2 U294 ( .A(n270), .B(n269), .Z(po02));
+ IV2 U295 ( .A(n271), .Z(n269));
+ OR2 U296 ( .A(n272), .B(n273), .Z(n271));
+ AN2 U297 ( .A(n274), .B(n275), .Z(n272));
+ OR2 U298 ( .A(n187), .B(n276), .Z(n275));
+ OR2 U299 ( .A(pi21), .B(n277), .Z(n274));
+ AN2 U300 ( .A(pi05), .B(n261), .Z(n270));
+ OR2 U301 ( .A(n278), .B(n279), .Z(po01));
+ OR2 U302 ( .A(n268), .B(n280), .Z(n279));
+ AN2 U303 ( .A(pi04), .B(n261), .Z(n280));
+ AN2 U304 ( .A(n252), .B(n258), .Z(n261));
+ IV2 U305 ( .A(n281), .Z(n268));
+ OR2 U306 ( .A(n282), .B(n283), .Z(n281));
+ OR2 U307 ( .A(n184), .B(n284), .Z(n283));
+ OR2 U308 ( .A(pi21), .B(pi17), .Z(n282));
+ AN2 U309 ( .A(n159), .B(n213), .Z(n278));
+ IV2 U310 ( .A(pi15), .Z(n213));
+ OR2 U311 ( .A(n285), .B(n286), .Z(n159));
+ AN2 U312 ( .A(pi21), .B(n287), .Z(n286));
+ OR2 U313 ( .A(n276), .B(n288), .Z(n287));
+ OR2 U314 ( .A(n273), .B(n187), .Z(n288));
+ OR2 U315 ( .A(pi23), .B(pi18), .Z(n276));
+ AN2 U316 ( .A(n172), .B(n277), .Z(n285));
+ AN2 U317 ( .A(pi23), .B(n289), .Z(n277));
+ AN2 U318 ( .A(n178), .B(n187), .Z(n289));
+ IV2 U319 ( .A(pi17), .Z(n187));
+ IV2 U320 ( .A(pi18), .Z(n178));
+ IV2 U321 ( .A(n273), .Z(n172));
+ OR2 U322 ( .A(pi20), .B(n168), .Z(n273));
+ AN2 U323 ( .A(n290), .B(n252), .Z(po00));
+ IV2 U324 ( .A(pi21), .Z(n252));
+ OR2 U325 ( .A(n256), .B(n291), .Z(n290));
+ OR2 U326 ( .A(n257), .B(n292), .Z(n291));
+ AN2 U327 ( .A(pi03), .B(n258), .Z(n292));
+ AN2 U328 ( .A(n284), .B(pi20), .Z(n258));
+ AN2 U329 ( .A(n184), .B(n168), .Z(n257));
+ IV2 U330 ( .A(pi19), .Z(n168));
+ IV2 U331 ( .A(pi20), .Z(n184));
+ AN2 U332 ( .A(n293), .B(pi17), .Z(n256));
+ IV2 U333 ( .A(n284), .Z(n293));
+ OR2 U334 ( .A(pi18), .B(pi19), .Z(n284));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/ttt2.ys b/examples/smtbmc/glift/ttt2.ys
new file mode 100644
index 000000000..1314d4975
--- /dev/null
+++ b/examples/smtbmc/glift/ttt2.ys
@@ -0,0 +1,41 @@
+read_verilog ttt2.v
+techmap
+flatten
+select ttt2_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename ttt2_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog ttt2.v
+techmap
+flatten
+select ttt2_lev2
+glift -create-precise-model
+techmap
+opt
+rename ttt2_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution ttt2.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file ttt2.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/x1.v b/examples/smtbmc/glift/x1.v
new file mode 100755
index 000000000..39b5284d3
--- /dev/null
+++ b/examples/smtbmc/glift/x1.v
@@ -0,0 +1,380 @@
+module x1_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50, po00, po01, po02, po03, po04, po05, po06, po07, po08,
+ po09, po10, po11, po12, po13, po14, po15, po16, po17, po18,
+ po19, po20, po21, po22, po23, po24, po25, po26, po27, po28,
+ po29, po30, po31, po32, po33, po34);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50;
+
+output po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20, po21, po22, po23, po24, po25, po26, po27, po28, po29,
+ po30, po31, po32, po33, po34;
+
+wire po05, po16, po18, po24, po25, po28, po29, n270, n271, n272,
+ n273, n274, n275, n276, n277, n278, n279, n280, n281, n282,
+ n283, n284, n285, n286, n287, n288, n289, n290, n291, n292,
+ n293, n294, n295, n296, n297, n298, n299, n300, n301, n302,
+ n303, n304, n305, n306, n307, n308, n309, n310, n311, n312,
+ n313, n314, n315, n316, n317, n318, n319, n320, n321, n322,
+ n323, n324, n325, n326, n327, n328, n329, n330, n331, n332,
+ n333, n334, n335, n336, n337, n338, n339, n340, n341, n342,
+ n343, n344, n345, n346, n347, n348, n349, n350, n351, n352,
+ n353, n354, n355, n356, n357, n358, n359, n360, n361, n362,
+ n363, n364, n365, n366, n367, n368, n369, n370, n371, n372,
+ n373, n374, n375, n376, n377, n378, n379, n380, n381, n382,
+ n383, n384, n385, n386, n387, n388, n389, n390, n391, n392,
+ n393, n394, n395, n396, n397, n398, n399, n400, n401, n402,
+ n403, n404, n405, n406, n407, n408, n409, n410, n411, n412,
+ n413, n414, n415, n416, n417, n418, n419, n420, n421, n422,
+ n423, n424, n425, n426, n427, n428, n429, n430, n431, n432,
+ n433, n434, n435, n436, n437, n438, n439, n440, n441, n442,
+ n443, n444, n445, n446, n447, n448, n449, n450, n451, n452,
+ n453, n454, n455, n456, n457, n458, n459, n460, n461, n462,
+ n463, n464, n465, n466, n467, n468, n469, n470, n471, n472,
+ n473, n474, n475, n476, n477, n478, n479, n480, n481, n482,
+ n483, n484, n485, n486, n487, n488, n489, n490, n491, n492,
+ n493, n494, n495, n496, n497, n498, n499, n500, n501, n502,
+ n503, n504, n505, n506, n507, n508, n509, n510, n511, n512,
+ n513, n514, n515, n516, n517, n518, n519, n520, n521, n522,
+ n523, n524, n525, n526, n527, n528, n529, n530, n531, n532,
+ n533;
+
+assign po05 = pi32;
+
+assign po16 = pi37;
+
+assign po18 = pi38;
+
+assign po24 = pi23;
+
+assign po25 = pi24;
+
+assign po28 = pi48;
+
+assign po29 = pi49;
+
+ IV2 U294 ( .A(po32), .Z(po33));
+ OR2 U295 ( .A(n270), .B(n271), .Z(po32));
+ OR2 U296 ( .A(po25), .B(po05), .Z(n271));
+ AN2 U297 ( .A(n272), .B(n273), .Z(n270));
+ OR2 U298 ( .A(pi31), .B(po01), .Z(n273));
+ AN2 U299 ( .A(n274), .B(pi18), .Z(po31));
+ AN2 U300 ( .A(pi17), .B(n275), .Z(n274));
+ AN2 U301 ( .A(n276), .B(n272), .Z(po30));
+ OR2 U302 ( .A(n277), .B(n278), .Z(n276));
+ AN2 U303 ( .A(n279), .B(n280), .Z(n278));
+ OR2 U304 ( .A(n281), .B(pi31), .Z(n280));
+ AN2 U305 ( .A(pi35), .B(n282), .Z(n281));
+ AN2 U306 ( .A(n283), .B(n284), .Z(n277));
+ OR2 U307 ( .A(n285), .B(n286), .Z(n284));
+ AN2 U308 ( .A(pi31), .B(n287), .Z(n286));
+ IV2 U309 ( .A(pi05), .Z(n287));
+ AN2 U310 ( .A(n288), .B(pi35), .Z(n285));
+ AN2 U311 ( .A(pi21), .B(pi13), .Z(n288));
+ AN2 U312 ( .A(pi07), .B(n289), .Z(po27));
+ OR2 U313 ( .A(n290), .B(n291), .Z(po26));
+ OR2 U314 ( .A(n292), .B(n293), .Z(n291));
+ AN2 U315 ( .A(n294), .B(n295), .Z(n293));
+ AN2 U316 ( .A(n296), .B(n297), .Z(n295));
+ AN2 U317 ( .A(pi33), .B(n298), .Z(n294));
+ IV2 U318 ( .A(n299), .Z(n298));
+ AN2 U319 ( .A(pi19), .B(pi00), .Z(n299));
+ AN2 U320 ( .A(n300), .B(n301), .Z(n292));
+ AN2 U321 ( .A(n302), .B(n303), .Z(n301));
+ OR2 U322 ( .A(n304), .B(pi35), .Z(n303));
+ AN2 U323 ( .A(n305), .B(pi25), .Z(n304));
+ AN2 U324 ( .A(pi11), .B(n306), .Z(n305));
+ AN2 U325 ( .A(n272), .B(n307), .Z(n302));
+ AN2 U326 ( .A(n308), .B(pi01), .Z(n300));
+ AN2 U327 ( .A(n279), .B(pi17), .Z(n308));
+ AN2 U328 ( .A(pi34), .B(n309), .Z(n290));
+ OR2 U329 ( .A(n310), .B(n311), .Z(po23));
+ AN2 U330 ( .A(n312), .B(n313), .Z(n310));
+ OR2 U331 ( .A(n314), .B(n315), .Z(po22));
+ AN2 U332 ( .A(n316), .B(n317), .Z(n315));
+ AN2 U333 ( .A(n318), .B(n319), .Z(n317));
+ OR2 U334 ( .A(n320), .B(n272), .Z(n319));
+ AN2 U335 ( .A(n321), .B(n322), .Z(n320));
+ IV2 U336 ( .A(pi02), .Z(n322));
+ AN2 U337 ( .A(n296), .B(n323), .Z(n321));
+ OR2 U338 ( .A(pi09), .B(n324), .Z(n318));
+ AN2 U339 ( .A(pi05), .B(pi21), .Z(n324));
+ AN2 U340 ( .A(pi31), .B(n309), .Z(n316));
+ AN2 U341 ( .A(n325), .B(n326), .Z(n314));
+ AN2 U342 ( .A(n283), .B(n327), .Z(n325));
+ OR2 U343 ( .A(n328), .B(n329), .Z(n327));
+ OR2 U344 ( .A(n330), .B(n331), .Z(n329));
+ OR2 U345 ( .A(n332), .B(n333), .Z(n331));
+ AN2 U346 ( .A(po05), .B(n272), .Z(n333));
+ AN2 U347 ( .A(pi43), .B(n296), .Z(n332));
+ AN2 U348 ( .A(pi47), .B(pi39), .Z(n330));
+ OR2 U349 ( .A(n334), .B(n335), .Z(n328));
+ OR2 U350 ( .A(n336), .B(n337), .Z(n335));
+ AN2 U351 ( .A(n338), .B(pi40), .Z(n337));
+ AN2 U352 ( .A(n339), .B(n340), .Z(n338));
+ AN2 U353 ( .A(n341), .B(n342), .Z(n336));
+ AN2 U354 ( .A(n343), .B(n344), .Z(n342));
+ AN2 U355 ( .A(n345), .B(pi41), .Z(n341));
+ AN2 U356 ( .A(pi29), .B(n346), .Z(n334));
+ OR2 U357 ( .A(n347), .B(n348), .Z(po21));
+ AN2 U358 ( .A(pi09), .B(po05), .Z(n348));
+ AN2 U359 ( .A(n349), .B(n350), .Z(n347));
+ AN2 U360 ( .A(n346), .B(n279), .Z(n350));
+ AN2 U361 ( .A(n351), .B(n326), .Z(n349));
+ OR2 U362 ( .A(n352), .B(n353), .Z(po20));
+ OR2 U363 ( .A(n354), .B(n355), .Z(n353));
+ AN2 U364 ( .A(pi22), .B(po05), .Z(n355));
+ AN2 U365 ( .A(n356), .B(n357), .Z(n354));
+ OR2 U366 ( .A(n358), .B(n359), .Z(n356));
+ OR2 U367 ( .A(po05), .B(n360), .Z(n359));
+ AN2 U368 ( .A(n361), .B(n362), .Z(n360));
+ OR2 U369 ( .A(n363), .B(n364), .Z(n362));
+ AN2 U370 ( .A(n346), .B(n365), .Z(n364));
+ AN2 U371 ( .A(n366), .B(pi14), .Z(n346));
+ AN2 U372 ( .A(n367), .B(n343), .Z(n363));
+ OR2 U373 ( .A(n368), .B(n365), .Z(n367));
+ OR2 U374 ( .A(n351), .B(pi29), .Z(n365));
+ AN2 U375 ( .A(pi28), .B(n345), .Z(n368));
+ AN2 U376 ( .A(n309), .B(n369), .Z(n361));
+ AN2 U377 ( .A(pi07), .B(n370), .Z(n358));
+ OR2 U378 ( .A(pi28), .B(pi29), .Z(n370));
+ OR2 U379 ( .A(n371), .B(n372), .Z(n352));
+ AN2 U380 ( .A(pi01), .B(n373), .Z(n372));
+ OR2 U381 ( .A(n374), .B(pi30), .Z(n373));
+ AN2 U382 ( .A(pi10), .B(pi25), .Z(n374));
+ AN2 U383 ( .A(n375), .B(n376), .Z(n371));
+ OR2 U384 ( .A(pi40), .B(pi41), .Z(n376));
+ OR2 U385 ( .A(n377), .B(n378), .Z(po19));
+ OR2 U386 ( .A(n379), .B(n380), .Z(n378));
+ AN2 U387 ( .A(pi42), .B(pi01), .Z(n380));
+ AN2 U388 ( .A(pi12), .B(n381), .Z(n379));
+ OR2 U389 ( .A(n382), .B(n383), .Z(n381));
+ OR2 U390 ( .A(n384), .B(n385), .Z(n383));
+ AN2 U391 ( .A(n386), .B(n369), .Z(n384));
+ OR2 U392 ( .A(po34), .B(n387), .Z(n386));
+ OR2 U393 ( .A(pi40), .B(pi26), .Z(n387));
+ OR2 U394 ( .A(pi27), .B(pi28), .Z(po34));
+ OR2 U395 ( .A(pi31), .B(pi29), .Z(n382));
+ OR2 U396 ( .A(n388), .B(n389), .Z(n377));
+ OR2 U397 ( .A(n390), .B(n391), .Z(n389));
+ AN2 U398 ( .A(n392), .B(pi18), .Z(n391));
+ AN2 U399 ( .A(pi17), .B(n393), .Z(n392));
+ OR2 U400 ( .A(pi36), .B(pi40), .Z(n393));
+ AN2 U401 ( .A(n394), .B(pi22), .Z(n390));
+ AN2 U402 ( .A(n351), .B(n369), .Z(n394));
+ AN2 U403 ( .A(pi00), .B(n395), .Z(n388));
+ OR2 U404 ( .A(n396), .B(n397), .Z(n395));
+ OR2 U405 ( .A(n385), .B(n398), .Z(n397));
+ OR2 U406 ( .A(n399), .B(n400), .Z(n398));
+ AN2 U407 ( .A(pi31), .B(n272), .Z(n399));
+ OR2 U408 ( .A(n401), .B(n402), .Z(n385));
+ OR2 U409 ( .A(pi41), .B(pi35), .Z(n402));
+ OR2 U410 ( .A(po05), .B(pi43), .Z(n401));
+ OR2 U411 ( .A(n403), .B(n404), .Z(n396));
+ OR2 U412 ( .A(pi25), .B(n289), .Z(n404));
+ OR2 U413 ( .A(pi34), .B(pi28), .Z(n403));
+ IV2 U414 ( .A(po17), .Z(po15));
+ OR2 U415 ( .A(n405), .B(n406), .Z(po17));
+ OR2 U416 ( .A(n407), .B(n408), .Z(n406));
+ OR2 U417 ( .A(n409), .B(n410), .Z(n408));
+ AN2 U418 ( .A(pi28), .B(n411), .Z(n410));
+ OR2 U419 ( .A(pi03), .B(n296), .Z(n411));
+ AN2 U420 ( .A(n412), .B(n413), .Z(n409));
+ OR2 U421 ( .A(n414), .B(n415), .Z(n413));
+ AN2 U422 ( .A(pi02), .B(pi31), .Z(n415));
+ AN2 U423 ( .A(n416), .B(n417), .Z(n414));
+ AN2 U424 ( .A(n418), .B(n309), .Z(n416));
+ OR2 U425 ( .A(pi25), .B(n272), .Z(n418));
+ OR2 U426 ( .A(pi09), .B(n419), .Z(n412));
+ AN2 U427 ( .A(n420), .B(n421), .Z(n419));
+ AN2 U428 ( .A(n275), .B(n309), .Z(n421));
+ OR2 U429 ( .A(pi25), .B(pi35), .Z(n275));
+ AN2 U430 ( .A(n417), .B(pi21), .Z(n420));
+ OR2 U431 ( .A(pi26), .B(n313), .Z(n407));
+ AN2 U432 ( .A(pi33), .B(pi08), .Z(n313));
+ OR2 U433 ( .A(n422), .B(n423), .Z(n405));
+ OR2 U434 ( .A(po05), .B(pi27), .Z(n423));
+ AN2 U435 ( .A(n424), .B(n425), .Z(po14));
+ AN2 U436 ( .A(n426), .B(n309), .Z(n425));
+ OR2 U437 ( .A(n427), .B(n428), .Z(n426));
+ OR2 U438 ( .A(n429), .B(n430), .Z(n428));
+ AN2 U439 ( .A(pi29), .B(n431), .Z(n430));
+ OR2 U440 ( .A(pi43), .B(pi40), .Z(n427));
+ AN2 U441 ( .A(n326), .B(pi07), .Z(n424));
+ OR2 U442 ( .A(n432), .B(n433), .Z(po12));
+ OR2 U443 ( .A(n434), .B(n435), .Z(n433));
+ AN2 U444 ( .A(pi28), .B(n436), .Z(n435));
+ OR2 U445 ( .A(n437), .B(pi21), .Z(n436));
+ AN2 U446 ( .A(n438), .B(pi14), .Z(n437));
+ AN2 U447 ( .A(n439), .B(n323), .Z(n438));
+ OR2 U448 ( .A(n440), .B(n441), .Z(n439));
+ IV2 U449 ( .A(n442), .Z(n441));
+ AN2 U450 ( .A(n443), .B(pi15), .Z(n440));
+ AN2 U451 ( .A(n444), .B(n445), .Z(n434));
+ AN2 U452 ( .A(n446), .B(n312), .Z(n445));
+ AN2 U453 ( .A(n447), .B(n448), .Z(n446));
+ OR2 U454 ( .A(n282), .B(n307), .Z(n447));
+ IV2 U455 ( .A(pi18), .Z(n307));
+ AN2 U456 ( .A(n449), .B(pi40), .Z(n444));
+ AN2 U457 ( .A(n450), .B(n451), .Z(n449));
+ OR2 U458 ( .A(n339), .B(n297), .Z(n451));
+ IV2 U459 ( .A(n452), .Z(n450));
+ AN2 U460 ( .A(n453), .B(n339), .Z(n452));
+ OR2 U461 ( .A(n340), .B(pi12), .Z(n453));
+ AN2 U462 ( .A(pi02), .B(pi03), .Z(n340));
+ AN2 U463 ( .A(pi46), .B(pi39), .Z(n432));
+ IV2 U464 ( .A(po13), .Z(po11));
+ OR2 U465 ( .A(n454), .B(n455), .Z(po13));
+ OR2 U466 ( .A(n456), .B(n457), .Z(n455));
+ AN2 U467 ( .A(pi25), .B(n458), .Z(n457));
+ OR2 U468 ( .A(n459), .B(n460), .Z(n458));
+ OR2 U469 ( .A(n461), .B(n462), .Z(n460));
+ AN2 U470 ( .A(n463), .B(n464), .Z(n461));
+ OR2 U471 ( .A(n282), .B(n465), .Z(n464));
+ OR2 U472 ( .A(pi12), .B(pi09), .Z(n465));
+ IV2 U473 ( .A(pi50), .Z(n463));
+ AN2 U474 ( .A(pi07), .B(n466), .Z(n456));
+ OR2 U475 ( .A(n467), .B(n468), .Z(n466));
+ OR2 U476 ( .A(n469), .B(n429), .Z(n468));
+ AN2 U477 ( .A(pi28), .B(n470), .Z(n429));
+ AN2 U478 ( .A(n400), .B(n471), .Z(n469));
+ OR2 U479 ( .A(pi40), .B(n431), .Z(n471));
+ OR2 U480 ( .A(pi43), .B(n289), .Z(n467));
+ AN2 U481 ( .A(pi19), .B(pi33), .Z(n289));
+ OR2 U482 ( .A(po01), .B(n472), .Z(n454));
+ OR2 U483 ( .A(po28), .B(po16), .Z(n472));
+ OR2 U484 ( .A(n473), .B(n474), .Z(po10));
+ AN2 U485 ( .A(n475), .B(pi41), .Z(n474));
+ AN2 U486 ( .A(n476), .B(n477), .Z(n475));
+ OR2 U487 ( .A(n297), .B(n343), .Z(n476));
+ AN2 U488 ( .A(n478), .B(n479), .Z(n473));
+ AN2 U489 ( .A(n283), .B(n296), .Z(n479));
+ AN2 U490 ( .A(pi29), .B(n345), .Z(n478));
+ IV2 U491 ( .A(n480), .Z(n345));
+ IV2 U492 ( .A(po07), .Z(po09));
+ OR2 U493 ( .A(n481), .B(n482), .Z(po08));
+ AN2 U494 ( .A(pi45), .B(pi39), .Z(n482));
+ AN2 U495 ( .A(n483), .B(n484), .Z(n481));
+ OR2 U496 ( .A(n485), .B(n486), .Z(n484));
+ AN2 U497 ( .A(pi29), .B(n312), .Z(n486));
+ AN2 U498 ( .A(n296), .B(n309), .Z(n312));
+ AN2 U499 ( .A(n351), .B(n487), .Z(n485));
+ OR2 U500 ( .A(n488), .B(n326), .Z(n487));
+ AN2 U501 ( .A(pi06), .B(n357), .Z(n488));
+ AN2 U502 ( .A(pi03), .B(pi28), .Z(n351));
+ AN2 U503 ( .A(n323), .B(n431), .Z(n483));
+ OR2 U504 ( .A(n489), .B(n490), .Z(po07));
+ OR2 U505 ( .A(pi33), .B(n311), .Z(n490));
+ IV2 U506 ( .A(n491), .Z(n311));
+ OR2 U507 ( .A(n492), .B(n493), .Z(n491));
+ OR2 U508 ( .A(n494), .B(n297), .Z(n493));
+ IV2 U509 ( .A(pi08), .Z(n297));
+ AN2 U510 ( .A(n375), .B(n369), .Z(n494));
+ IV2 U511 ( .A(n448), .Z(n375));
+ OR2 U512 ( .A(n477), .B(n366), .Z(n448));
+ OR2 U513 ( .A(n431), .B(n344), .Z(n477));
+ IV2 U514 ( .A(pi16), .Z(n344));
+ OR2 U515 ( .A(n495), .B(n496), .Z(n492));
+ OR2 U516 ( .A(pi00), .B(n339), .Z(n496));
+ AN2 U517 ( .A(n369), .B(n343), .Z(n339));
+ IV2 U518 ( .A(n497), .Z(n495));
+ OR2 U519 ( .A(n498), .B(pi40), .Z(n497));
+ AN2 U520 ( .A(n369), .B(pi41), .Z(n498));
+ OR2 U521 ( .A(po05), .B(n422), .Z(n489));
+ OR2 U522 ( .A(po25), .B(po24), .Z(n422));
+ OR2 U523 ( .A(n499), .B(n500), .Z(po06));
+ AN2 U524 ( .A(pi27), .B(n501), .Z(n500));
+ AN2 U525 ( .A(n502), .B(n503), .Z(n499));
+ AN2 U526 ( .A(n504), .B(n480), .Z(n503));
+ OR2 U527 ( .A(n431), .B(n366), .Z(n480));
+ IV2 U528 ( .A(pi14), .Z(n431));
+ AN2 U529 ( .A(n470), .B(n296), .Z(n504));
+ IV2 U530 ( .A(pi07), .Z(n296));
+ IV2 U531 ( .A(pi03), .Z(n470));
+ AN2 U532 ( .A(pi28), .B(n279), .Z(n502));
+ AN2 U533 ( .A(pi26), .B(n501), .Z(po04));
+ OR2 U534 ( .A(pi21), .B(n323), .Z(n501));
+ AN2 U535 ( .A(n505), .B(n506), .Z(po03));
+ AN2 U536 ( .A(n507), .B(n279), .Z(n506));
+ AN2 U537 ( .A(n369), .B(n283), .Z(n279));
+ IV2 U538 ( .A(pi21), .Z(n369));
+ AN2 U539 ( .A(n442), .B(n400), .Z(n507));
+ OR2 U540 ( .A(pi29), .B(pi40), .Z(n400));
+ OR2 U541 ( .A(n366), .B(n343), .Z(n442));
+ IV2 U542 ( .A(pi06), .Z(n343));
+ IV2 U543 ( .A(pi15), .Z(n366));
+ AN2 U544 ( .A(n326), .B(pi14), .Z(n505));
+ AN2 U545 ( .A(n508), .B(n443), .Z(n326));
+ IV2 U546 ( .A(n357), .Z(n443));
+ OR2 U547 ( .A(pi04), .B(pi20), .Z(n357));
+ OR2 U548 ( .A(n509), .B(n510), .Z(po02));
+ OR2 U549 ( .A(n511), .B(n512), .Z(n510));
+ AN2 U550 ( .A(pi44), .B(pi39), .Z(n512));
+ AN2 U551 ( .A(n513), .B(n514), .Z(n511));
+ AN2 U552 ( .A(n515), .B(n516), .Z(n514));
+ AN2 U553 ( .A(n309), .B(n306), .Z(n515));
+ IV2 U554 ( .A(pi10), .Z(n306));
+ AN2 U555 ( .A(n417), .B(pi25), .Z(n513));
+ IV2 U556 ( .A(n517), .Z(n417));
+ OR2 U557 ( .A(n518), .B(n519), .Z(n509));
+ AN2 U558 ( .A(n520), .B(pi09), .Z(n519));
+ AN2 U559 ( .A(n521), .B(pi02), .Z(n520));
+ AN2 U560 ( .A(pi31), .B(n508), .Z(n521));
+ IV2 U561 ( .A(pi22), .Z(n508));
+ AN2 U562 ( .A(n522), .B(n272), .Z(n518));
+ IV2 U563 ( .A(pi09), .Z(n272));
+ AN2 U564 ( .A(n523), .B(n524), .Z(n522));
+ AN2 U565 ( .A(n525), .B(pi35), .Z(n524));
+ AN2 U566 ( .A(pi21), .B(n526), .Z(n525));
+ IV2 U567 ( .A(pi13), .Z(n526));
+ AN2 U568 ( .A(pi01), .B(n283), .Z(n523));
+ AN2 U569 ( .A(n323), .B(n309), .Z(n283));
+ IV2 U570 ( .A(pi00), .Z(n309));
+ IV2 U571 ( .A(pi12), .Z(n323));
+ OR2 U572 ( .A(n527), .B(n528), .Z(po00));
+ AN2 U573 ( .A(po01), .B(n459), .Z(n528));
+ OR2 U574 ( .A(pi30), .B(pi42), .Z(po01));
+ AN2 U575 ( .A(pi25), .B(n529), .Z(n527));
+ OR2 U576 ( .A(n530), .B(n517), .Z(n529));
+ OR2 U577 ( .A(n531), .B(n532), .Z(n517));
+ OR2 U578 ( .A(n462), .B(n459), .Z(n532));
+ IV2 U579 ( .A(pi01), .Z(n459));
+ IV2 U580 ( .A(pi11), .Z(n462));
+ OR2 U581 ( .A(pi13), .B(pi12), .Z(n531));
+ AN2 U582 ( .A(n533), .B(n282), .Z(n530));
+ IV2 U583 ( .A(pi17), .Z(n282));
+ IV2 U584 ( .A(n516), .Z(n533));
+ OR2 U585 ( .A(pi09), .B(pi21), .Z(n516));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/x1.ys b/examples/smtbmc/glift/x1.ys
new file mode 100644
index 000000000..b588dea92
--- /dev/null
+++ b/examples/smtbmc/glift/x1.ys
@@ -0,0 +1,41 @@
+read_verilog x1.v
+techmap
+flatten
+select x1_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename x1_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog x1.v
+techmap
+flatten
+select x1_lev2
+glift -create-precise-model
+techmap
+opt
+rename x1_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution x1.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file x1.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 7be8ab565..6097f02f5 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -344,7 +344,7 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
}
if (!multirange_swapped.empty()) {
fprintf(f, " multirange_swapped=[");
- for (auto v : multirange_swapped)
+ for (bool v : multirange_swapped)
fprintf(f, " %d", v);
fprintf(f, " ]");
}
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 48ec9a063..80497c131 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -268,6 +268,7 @@ namespace AST
struct varinfo_t {
RTLIL::Const val;
int offset;
+ bool range_swapped;
bool is_signed;
AstNode *arg = nullptr;
bool explicitly_sized;
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 4c25287ad..020b4e5e8 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -877,7 +877,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
if (children.size() > 1)
range = children[1];
- } else if (id_ast->type == AST_STRUCT_ITEM) {
+ } else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT) {
AstNode *tmp_range = make_struct_member_range(this, id_ast);
this_width = tmp_range->range_left - tmp_range->range_right + 1;
delete tmp_range;
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 18b1e1e11..565025d3a 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -307,6 +307,10 @@ static int size_packed_struct(AstNode *snode, int base_offset)
if (node->type == AST_STRUCT || node->type == AST_UNION) {
// embedded struct or union
width = size_packed_struct(node, base_offset + offset);
+ // set range of struct
+ node->range_right = base_offset + offset;
+ node->range_left = base_offset + offset + width - 1;
+ node->range_valid = true;
}
else {
log_assert(node->type == AST_STRUCT_ITEM);
@@ -493,14 +497,12 @@ static void add_members_to_scope(AstNode *snode, std::string name)
// in case later referenced in assignments
log_assert(snode->type==AST_STRUCT || snode->type==AST_UNION);
for (auto *node : snode->children) {
+ auto member_name = name + "." + node->str;
+ current_scope[member_name] = node;
if (node->type != AST_STRUCT_ITEM) {
// embedded struct or union
add_members_to_scope(node, name + "." + node->str);
}
- else {
- auto member_name = name + "." + node->str;
- current_scope[member_name] = node;
- }
}
}
@@ -1341,6 +1343,16 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
case AST_PARAMETER:
case AST_LOCALPARAM:
+ // if parameter is implicit type which is the typename of a struct or union,
+ // save information about struct in wiretype attribute
+ if (children[0]->type == AST_IDENTIFIER && current_scope.count(children[0]->str) > 0) {
+ auto item_node = current_scope[children[0]->str];
+ if (item_node->type == AST_STRUCT || item_node->type == AST_UNION) {
+ attributes[ID::wiretype] = item_node->clone();
+ size_packed_struct(attributes[ID::wiretype], 0);
+ add_members_to_scope(attributes[ID::wiretype], str);
+ }
+ }
while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true)
did_something = true;
children[0]->detectSignWidth(width_hint, sign_hint);
@@ -2018,7 +2030,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (name_has_dot(str, sname)) {
if (current_scope.count(str) > 0) {
auto item_node = current_scope[str];
- if (item_node->type == AST_STRUCT_ITEM) {
+ if (item_node->type == AST_STRUCT_ITEM || item_node->type == AST_STRUCT) {
// structure member, rewrite this node to reference the packed struct wire
auto range = make_struct_member_range(this, item_node);
newNode = new AstNode(AST_IDENTIFIER, range);
@@ -2704,6 +2716,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
current_ast_mod->children.push_back(wire_data);
+ int shamt_width_hint = -1;
+ bool shamt_sign_hint = true;
+ shift_expr->detectSignWidth(shamt_width_hint, shamt_sign_hint);
+
+ AstNode *wire_sel = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(shamt_width_hint-1, true), mkconst_int(0, true)));
+ wire_sel->str = stringf("$bitselwrite$sel$%s:%d$%d", filename.c_str(), location.first_line, autoidx++);
+ wire_sel->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
+ wire_sel->is_logic = true;
+ wire_sel->is_signed = shamt_sign_hint;
+ while (wire_sel->simplify(true, false, false, 1, -1, false, false)) { }
+ current_ast_mod->children.push_back(wire_sel);
+
did_something = true;
newNode = new AstNode(AST_BLOCK);
@@ -2720,39 +2744,44 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
ref_data->id2ast = wire_data;
ref_data->was_checked = true;
+ AstNode *ref_sel = new AstNode(AST_IDENTIFIER);
+ ref_sel->str = wire_sel->str;
+ ref_sel->id2ast = wire_sel;
+ ref_sel->was_checked = true;
+
AstNode *old_data = lvalue->clone();
if (type == AST_ASSIGN_LE)
old_data->lookahead = true;
- AstNode *shamt = shift_expr;
+ AstNode *s = new AstNode(AST_ASSIGN_EQ, ref_sel->clone(), shift_expr);
+ newNode->children.push_back(s);
- int shamt_width_hint = 0;
- bool shamt_sign_hint = true;
- shamt->detectSignWidth(shamt_width_hint, shamt_sign_hint);
+ AstNode *shamt = ref_sel;
+
+ // convert to signed while preserving the sign and value
+ shamt = new AstNode(AST_CAST_SIZE, mkconst_int(shamt_width_hint + 1, true), shamt);
+ shamt = new AstNode(AST_TO_SIGNED, shamt);
+ // offset the shift amount by the lower bound of the dimension
int start_bit = children[0]->id2ast->range_right;
- bool use_shift = shamt_sign_hint;
+ shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true));
- if (start_bit != 0) {
- shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true));
- use_shift = true;
- }
+ // reflect the shift amount if the dimension is swapped
+ if (children[0]->id2ast->range_swapped)
+ shamt = new AstNode(AST_SUB, mkconst_int(source_width - result_width, true), shamt);
+
+ // AST_SHIFT uses negative amounts for shifting left
+ shamt = new AstNode(AST_NEG, shamt);
AstNode *t;
t = mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false);
- if (use_shift)
- t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt->clone()));
- else
- t = new AstNode(AST_SHIFT_LEFT, t, shamt->clone());
+ t = new AstNode(AST_SHIFT, t, shamt->clone());
t = new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), t);
newNode->children.push_back(t);
t = new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone());
- if (use_shift)
- t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt));
- else
- t = new AstNode(AST_SHIFT_LEFT, t, shamt);
+ t = new AstNode(AST_SHIFT, t, shamt);
t = new AstNode(AST_ASSIGN_EQ, ref_data->clone(), t);
newNode->children.push_back(t);
@@ -5134,6 +5163,8 @@ bool AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia
width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);
}
offset -= variables.at(str).offset;
+ if (variables.at(str).range_swapped)
+ offset = -offset;
std::vector<RTLIL::State> &var_bits = variables.at(str).val.bits;
std::vector<RTLIL::State> new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width);
AstNode *newNode = mkconst_bits(new_bits, variables.at(str).is_signed);
@@ -5191,7 +5222,8 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
log_file_error(filename, location.first_line, "Incompatible re-declaration of constant function wire %s.\n", stmt->str.c_str());
}
variable.val = RTLIL::Const(RTLIL::State::Sx, width);
- variable.offset = min(stmt->range_left, stmt->range_right);
+ variable.offset = stmt->range_swapped ? stmt->range_left : stmt->range_right;
+ variable.range_swapped = stmt->range_swapped;
variable.is_signed = stmt->is_signed;
variable.explicitly_sized = stmt->children.size() &&
stmt->children.back()->type == AST_RANGE;
@@ -5276,8 +5308,12 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
int width = std::abs(range->range_left - range->range_right) + 1;
varinfo_t &v = variables[stmt->children.at(0)->str];
RTLIL::Const r = stmt->children.at(1)->bitsAsConst(v.val.bits.size());
- for (int i = 0; i < width; i++)
- v.val.bits.at(i+offset-v.offset) = r.bits.at(i);
+ for (int i = 0; i < width; i++) {
+ int index = i + offset - v.offset;
+ if (v.range_swapped)
+ index = -index;
+ v.val.bits.at(index) = r.bits.at(i);
+ }
}
delete block->children.front();
diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc
index 50c25abda..1aab81015 100644
--- a/frontends/json/jsonparse.cc
+++ b/frontends/json/jsonparse.cc
@@ -60,10 +60,38 @@ struct JsonNode
break;
if (ch == '\\') {
- int ch = f.get();
+ ch = f.get();
- if (ch == EOF)
- log_error("Unexpected EOF in JSON string.\n");
+ switch (ch) {
+ case EOF: log_error("Unexpected EOF in JSON string.\n"); break;
+ case '"':
+ case '/':
+ case '\\': break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'u':
+ int val = 0;
+ for (int i = 0; i < 4; i++) {
+ ch = f.get();
+ val <<= 4;
+ if (ch >= '0' && '9' >= ch) {
+ val += ch - '0';
+ } else if (ch >= 'A' && 'F' >= ch) {
+ val += 10 + ch - 'A';
+ } else if (ch >= 'a' && 'f' >= ch) {
+ val += 10 + ch - 'a';
+ } else
+ log_error("Unexpected non-digit character in \\uXXXX sequence: %c.\n", ch);
+ }
+ if (val < 128)
+ ch = val;
+ else
+ log_error("Unsupported \\uXXXX sequence in JSON string: %04X.\n", val);
+ break;
+ }
}
data_string += ch;
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index d5574f95a..8c2f7f0da 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -169,7 +169,10 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
FOREACH_ATTRIBUTE(obj, mi, attr) {
if (attr->Key()[0] == ' ' || attr->Value() == nullptr)
continue;
- attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(std::string(attr->Value()));
+ std::string val = std::string(attr->Value());
+ if (val.size()>1 && val[0]=='\"' && val.back()=='\"')
+ val = val.substr(1,val.size()-2);
+ attributes[RTLIL::escape_id(attr->Key())] = RTLIL::Const(val);
}
if (nl) {
@@ -798,28 +801,14 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
}
if (inst->Type() == OPER_NTO1MUX) {
- cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
+ cell = module->addBmux(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_NTO1MUX)
{
- SigSpec data = IN2, out = OUT;
-
- int wordsize_bits = ceil_log2(GetSize(out));
- int wordsize = 1 << wordsize_bits;
-
- SigSpec sel = {IN1, SigSpec(State::S0, wordsize_bits)};
-
- SigSpec padded_data;
- for (int i = 0; i < GetSize(data); i += GetSize(out)) {
- SigSpec d = data.extract(i, GetSize(out));
- d.extend_u0(wordsize);
- padded_data.append(d);
- }
-
- cell = module->addShr(inst_name, padded_data, sel, out);
+ cell = module->addBmux(inst_name, IN2, IN1, OUT);
import_attributes(cell->attributes, inst);
return true;
}
@@ -2310,9 +2299,11 @@ struct VerificPass : public Pass {
log("\n");
log("\n");
#endif
- log(" verific {-f|-F} <command-file>\n");
+ log(" verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal] <command-file>\n");
log("\n");
log("Load and execute the specified command file.\n");
+ log("Override verilog parsing mode can be set.\n");
+ log("The macros YOSYS, SYNTHESIS/FORMAL, and VERIFIC are defined implicitly.\n");
log("\n");
log("Command file parser supports following commands:\n");
log(" +define - defines macro\n");
@@ -2678,11 +2669,51 @@ struct VerificPass : public Pass {
if (GetSize(args) > argidx && (args[argidx] == "-f" || args[argidx] == "-F"))
{
unsigned verilog_mode = veri_file::VERILOG_95; // default recommended by Verific
+ bool is_formal = false;
+ const char* filename = nullptr;
Verific::veri_file::f_file_flags flags = (args[argidx] == "-f") ? veri_file::F_FILE_NONE : veri_file::F_FILE_CAPITAL;
- Array *file_names = veri_file::ProcessFFile(args[++argidx].c_str(), flags, verilog_mode);
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ if (args[argidx] == "-vlog95") {
+ verilog_mode = veri_file::VERILOG_95;
+ continue;
+ } else if (args[argidx] == "-vlog2k") {
+ verilog_mode = veri_file::VERILOG_2K;
+ continue;
+ } else if (args[argidx] == "-sv2005") {
+ verilog_mode = veri_file::SYSTEM_VERILOG_2005;
+ continue;
+ } else if (args[argidx] == "-sv2009") {
+ verilog_mode = veri_file::SYSTEM_VERILOG_2009;
+ continue;
+ } else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal") {
+ verilog_mode = veri_file::SYSTEM_VERILOG;
+ if (args[argidx] == "-formal") is_formal = true;
+ continue;
+ } else if (args[argidx].compare(0, 1, "-") == 0) {
+ cmd_error(args, argidx, "unknown option");
+ goto check_error;
+ }
+
+ if (!filename) {
+ filename = args[argidx].c_str();
+ continue;
+ } else {
+ log_cmd_error("Only one filename can be specified.\n");
+ }
+ }
+ if (!filename)
+ log_cmd_error("Filname must be specified.\n");
+
+ unsigned analysis_mode = verilog_mode; // keep default as provided by user if not defined in file
+ Array *file_names = veri_file::ProcessFFile(filename, flags, analysis_mode);
+ if (analysis_mode != verilog_mode)
+ log_warning("Provided verilog mode differs from one specified in file.\n");
+
+ veri_file::DefineMacro("YOSYS");
veri_file::DefineMacro("VERIFIC");
+ veri_file::DefineMacro(is_formal ? "FORMAL" : "SYNTHESIS");
if (!veri_file::AnalyzeMultipleFiles(file_names, verilog_mode, work.c_str(), veri_file::MFCU)) {
verific_error_msg.clear();
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index 89c1aa895..958809319 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -128,6 +128,11 @@ static bool isUserType(std::string &s)
%x IMPORT_DPI
%x BASED_CONST
+UNSIGNED_NUMBER [0-9][0-9_]*
+FIXED_POINT_NUMBER_DEC [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)?
+FIXED_POINT_NUMBER_NO_DEC [0-9][0-9_]*[eE][-+]?[0-9_]+
+TIME_SCALE_SUFFIX [munpf]?s
+
%%
// Initialise comment_caller to something to avoid a "maybe undefined"
// warning from GCC.
@@ -297,7 +302,7 @@ static bool isUserType(std::string &s)
"union" { SV_KEYWORD(TOK_UNION); }
"packed" { SV_KEYWORD(TOK_PACKED); }
-[0-9][0-9_]* {
+{UNSIGNED_NUMBER} {
yylval->string = new std::string(yytext);
return TOK_CONSTVAL;
}
@@ -319,12 +324,12 @@ static bool isUserType(std::string &s)
return TOK_BASED_CONSTVAL;
}
-[0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? {
+{FIXED_POINT_NUMBER_DEC} {
yylval->string = new std::string(yytext);
return TOK_REALVAL;
}
-[0-9][0-9_]*[eE][-+]?[0-9_]+ {
+{FIXED_POINT_NUMBER_NO_DEC} {
yylval->string = new std::string(yytext);
return TOK_REALVAL;
}
@@ -574,6 +579,10 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
return TOK_SPECIFY_AND;
}
+{UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
+{FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
+{FIXED_POINT_NUMBER_NO_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
+
<INITIAL,BASED_CONST>"/*" { comment_caller=YY_START; BEGIN(COMMENT); }
<COMMENT>. /* ignore comment body */
<COMMENT>\n /* ignore comment body */
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 171e098a5..c533b0c40 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -369,7 +369,7 @@ static void rewriteGenForDeclInit(AstNode *loop)
%token TOK_BIT_OR_ASSIGN TOK_BIT_AND_ASSIGN TOK_BIT_XOR_ASSIGN TOK_ADD_ASSIGN
%token TOK_SUB_ASSIGN TOK_DIV_ASSIGN TOK_MOD_ASSIGN TOK_MUL_ASSIGN
%token TOK_SHL_ASSIGN TOK_SHR_ASSIGN TOK_SSHL_ASSIGN TOK_SSHR_ASSIGN
-%token TOK_BIND
+%token TOK_BIND TOK_TIME_SCALE
%type <ast> range range_or_multirange non_opt_range non_opt_multirange
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
@@ -779,6 +779,9 @@ non_opt_delay:
'#' TOK_ID { delete $2; } |
'#' TOK_CONSTVAL { delete $2; } |
'#' TOK_REALVAL { delete $2; } |
+ // our `expr` doesn't have time_scale, so we need the parenthesized variant
+ '#' TOK_TIME_SCALE |
+ '#' '(' TOK_TIME_SCALE ')' |
'#' '(' mintypmax_expr ')' |
'#' '(' mintypmax_expr ',' mintypmax_expr ')' |
'#' '(' mintypmax_expr ',' mintypmax_expr ',' mintypmax_expr ')';
diff --git a/guidelines/Windows b/guidelines/Windows
index 16ba57c9d..2af0620fa 100644
--- a/guidelines/Windows
+++ b/guidelines/Windows
@@ -37,6 +37,29 @@ Creating the Visual Studio Template Project
4. Zip YosysVS as YosysVS-Tpl-v1.zip
+Compiling with Visual Studio
+============================
+
+Visual Studio builds are not directly supported by build scripts, but they are still possible.
+
+1. Easy way
+
+ - Go to https://github.com/YosysHQ/yosys/actions/workflows/vs.yml?query=branch%3Amaster
+ - Click on the most recent completed run
+ - In Artifacts region find vcxsrc and click on it to download
+ - Unpack downloaded ZIP file
+ - Open YosysVS.sln with Visual Studio
+
+2. Using WSL or MSYS2
+
+ - Make sure to have make, python3 and git available
+ - Git clone yosys repository
+ - Execute ```make vcxsrc YOSYS_VER=latest```
+ - File yosys-win32-vcxsrc-latest.zip will be created
+ - Transfer that file to location visible by Windows application
+ - Unpack ZIP
+ - Open YosysVS.sln with Visual Studio
+
Cross-Building for Windows with MXE
===================================
diff --git a/kernel/calc.cc b/kernel/calc.cc
index 1e6410f7d..0865db526 100644
--- a/kernel/calc.cc
+++ b/kernel/calc.cc
@@ -609,5 +609,56 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo
return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len);
}
+RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+{
+ std::vector<RTLIL::State> t = arg1.bits;
+
+ for (int i = GetSize(arg2)-1; i >= 0; i--)
+ {
+ RTLIL::State sel = arg2.bits.at(i);
+ std::vector<RTLIL::State> new_t;
+ if (sel == State::S0)
+ new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
+ else if (sel == State::S1)
+ new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
+ else
+ for (int j = 0; j < GetSize(t)/2; j++)
+ new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx);
+ t.swap(new_t);
+ }
+
+ return t;
+}
+
+RTLIL::Const RTLIL::const_demux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+{
+ int width = GetSize(arg1);
+ int s_width = GetSize(arg2);
+ std::vector<RTLIL::State> res;
+ for (int i = 0; i < (1 << s_width); i++)
+ {
+ bool ne = false;
+ bool x = false;
+ for (int j = 0; j < s_width; j++) {
+ bool bit = i & 1 << j;
+ if (arg2[j] == (bit ? RTLIL::S0 : RTLIL::S1))
+ ne = true;
+ else if (arg2[j] != RTLIL::S0 && arg2[j] != RTLIL::S1)
+ x = true;
+ }
+ if (ne) {
+ for (int j = 0; j < width; j++)
+ res.push_back(State::S0);
+ } else if (x) {
+ for (int j = 0; j < width; j++)
+ res.push_back(arg1.bits[j] == State::S0 ? State::S0 : State::Sx);
+ } else {
+ for (int j = 0; j < width; j++)
+ res.push_back(arg1.bits[j]);
+ }
+ }
+ return res;
+}
+
YOSYS_NAMESPACE_END
diff --git a/kernel/celledges.cc b/kernel/celledges.cc
index af07d26b3..c43ba8db3 100644
--- a/kernel/celledges.cc
+++ b/kernel/celledges.cc
@@ -142,6 +142,36 @@ void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
}
}
+void bmux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
+{
+ int width = GetSize(cell->getPort(ID::Y));
+ int a_width = GetSize(cell->getPort(ID::A));
+ int s_width = GetSize(cell->getPort(ID::S));
+
+ for (int i = 0; i < width; i++)
+ {
+ for (int k = i; k < a_width; k += width)
+ db->add_edge(cell, ID::A, k, ID::Y, i, -1);
+
+ for (int k = 0; k < s_width; k++)
+ db->add_edge(cell, ID::S, k, ID::Y, i, -1);
+ }
+}
+
+void demux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
+{
+ int width = GetSize(cell->getPort(ID::Y));
+ int a_width = GetSize(cell->getPort(ID::A));
+ int s_width = GetSize(cell->getPort(ID::S));
+
+ for (int i = 0; i < width; i++)
+ {
+ db->add_edge(cell, ID::A, i % a_width, ID::Y, i, -1);
+ for (int k = 0; k < s_width; k++)
+ db->add_edge(cell, ID::S, k, ID::Y, i, -1);
+ }
+}
+
PRIVATE_NAMESPACE_END
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
@@ -187,6 +217,16 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
return true;
}
+ if (cell->type == ID($bmux)) {
+ bmux_op(this, cell);
+ return true;
+ }
+
+ if (cell->type == ID($demux)) {
+ demux_op(this, cell);
+ return true;
+ }
+
// FIXME: $mul $div $mod $divfloor $modfloor $slice $concat
// FIXME: $lut $sop $alu $lcu $macc $fa
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 879ac0edc..7e9cfb38d 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -127,6 +127,9 @@ struct CellTypes
for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux)}))
setup_type(type, {ID::A, ID::B, ID::S}, {ID::Y}, true);
+ for (auto type : std::vector<RTLIL::IdString>({ID($bmux), ID($demux)}))
+ setup_type(type, {ID::A, ID::S}, {ID::Y}, true);
+
setup_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO}, true);
setup_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO}, true);
setup_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y}, true);
@@ -411,6 +414,16 @@ struct CellTypes
return ret;
}
+ if (cell->type == ID($bmux))
+ {
+ return const_bmux(arg1, arg2);
+ }
+
+ if (cell->type == ID($demux))
+ {
+ return const_demux(arg1, arg2);
+ }
+
if (cell->type == ID($lut))
{
int width = cell->parameters.at(ID::WIDTH).as_int();
@@ -420,21 +433,7 @@ struct CellTypes
t.push_back(State::S0);
t.resize(1 << width);
- for (int i = width-1; i >= 0; i--) {
- RTLIL::State sel = arg1.bits.at(i);
- std::vector<RTLIL::State> new_t;
- if (sel == State::S0)
- new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
- else if (sel == State::S1)
- new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
- else
- for (int j = 0; j < GetSize(t)/2; j++)
- new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx);
- t.swap(new_t);
- }
-
- log_assert(GetSize(t) == 1);
- return t;
+ return const_bmux(t, arg1);
}
if (cell->type == ID($sop))
diff --git a/kernel/consteval.h b/kernel/consteval.h
index 3edfc490c..642eb42b2 100644
--- a/kernel/consteval.h
+++ b/kernel/consteval.h
@@ -135,8 +135,6 @@ struct ConstEval
if (cell->hasPort(ID::S)) {
sig_s = cell->getPort(ID::S);
- if (!eval(sig_s, undef, cell))
- return false;
}
if (cell->hasPort(ID::A))
@@ -151,6 +149,9 @@ struct ConstEval
int count_maybe_set_s_bits = 0;
int count_set_s_bits = 0;
+ if (!eval(sig_s, undef, cell))
+ return false;
+
for (int i = 0; i < sig_s.size(); i++)
{
RTLIL::State s_bit = sig_s.extract(i, 1).as_const().bits.at(0);
@@ -198,6 +199,36 @@ struct ConstEval
else
set(sig_y, y_values.front());
}
+ else if (cell->type == ID($bmux))
+ {
+ if (!eval(sig_s, undef, cell))
+ return false;
+
+ if (sig_s.is_fully_def()) {
+ int sel = sig_s.as_int();
+ int width = GetSize(sig_y);
+ SigSpec res = sig_a.extract(sel * width, width);
+ if (!eval(res, undef, cell))
+ return false;
+ set(sig_y, res.as_const());
+ } else {
+ if (!eval(sig_a, undef, cell))
+ return false;
+ set(sig_y, const_bmux(sig_a.as_const(), sig_s.as_const()));
+ }
+ }
+ else if (cell->type == ID($demux))
+ {
+ if (!eval(sig_a, undef, cell))
+ return false;
+ if (sig_a.is_fully_zero()) {
+ set(sig_y, Const(0, GetSize(sig_y)));
+ } else {
+ if (!eval(sig_s, undef, cell))
+ return false;
+ set(sig_y, const_demux(sig_a.as_const(), sig_s.as_const()));
+ }
+ }
else if (cell->type == ID($fa))
{
RTLIL::SigSpec sig_c = cell->getPort(ID::C);
diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc
new file mode 100644
index 000000000..6cf28625c
--- /dev/null
+++ b/kernel/fstdata.cc
@@ -0,0 +1,219 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Miodrag Milanovic <micko@yosyshq.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/fstdata.h"
+
+USING_YOSYS_NAMESPACE
+
+
+static std::string file_base_name(std::string const & path)
+{
+ return path.substr(path.find_last_of("/\\") + 1);
+}
+
+FstData::FstData(std::string filename) : ctx(nullptr)
+{
+ #if !defined(YOSYS_DISABLE_SPAWN)
+ std::string filename_trim = file_base_name(filename);
+ if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".vcd") == 0) {
+ filename_trim.erase(filename_trim.size()-4);
+ tmp_file = stringf("/tmp/converted_%s.fst", filename_trim.c_str());
+ std::string cmd = stringf("vcd2fst %s %s", filename.c_str(), tmp_file.c_str());
+ log("Exec: %s\n", cmd.c_str());
+ if (run_command(cmd) != 0)
+ log_cmd_error("Shell command failed!\n");
+ filename = tmp_file;
+ }
+ #endif
+ const std::vector<std::string> g_units = { "s", "ms", "us", "ns", "ps", "fs", "as", "zs" };
+ ctx = (fstReaderContext *)fstReaderOpen(filename.c_str());
+ if (!ctx)
+ log_error("Error opening '%s' as FST file\n", filename.c_str());
+ int scale = (int)fstReaderGetTimescale(ctx);
+ timescale = pow(10.0, scale);
+ timescale_str = "";
+ int unit = 0;
+ int zeros = 0;
+ if (scale > 0) {
+ zeros = scale;
+ } else {
+ if ((scale % 3) == 0) {
+ zeros = (-scale % 3);
+ unit = (-scale / 3);
+ } else {
+ zeros = 3 - (-scale % 3);
+ unit = (-scale / 3) + 1;
+ }
+ }
+ for (int i=0;i<zeros; i++) timescale_str += "0";
+ timescale_str += g_units[unit];
+ extractVarNames();
+}
+
+FstData::~FstData()
+{
+ if (ctx)
+ fstReaderClose(ctx);
+ if (!tmp_file.empty())
+ remove(tmp_file.c_str());
+}
+
+uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx); }
+
+uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx); }
+
+fstHandle FstData::getHandle(std::string name) {
+ if (name_to_handle.find(name) != name_to_handle.end())
+ return name_to_handle[name];
+ else
+ return 0;
+};
+
+static std::string remove_spaces(std::string str)
+{
+ str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
+ return str;
+}
+
+void FstData::extractVarNames()
+{
+ struct fstHier *h;
+ intptr_t snum = 0;
+
+ while ((h = fstReaderIterateHier(ctx))) {
+ switch (h->htyp) {
+ case FST_HT_SCOPE: {
+ snum++;
+ std::string fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, (void *)(snum));
+ if (h->u.scope.typ == FST_ST_VCD_MODULE)
+ scopes.push_back(fst_scope_name);
+ break;
+ }
+ case FST_HT_UPSCOPE: {
+ fstReaderPopScope(ctx);
+ snum = fstReaderGetCurrentScopeLen(ctx) ? (intptr_t)fstReaderGetCurrentScopeUserInfo(ctx) : 0;
+ break;
+ }
+ case FST_HT_VAR: {
+ FstVar var;
+ var.id = h->u.var.handle;
+ var.is_alias = h->u.var.is_alias;
+ var.is_reg = (fstVarType)h->u.var.typ == FST_VT_VCD_REG;
+ var.name = remove_spaces(h->u.var.name);
+ var.scope = scopes.back();
+ var.width = h->u.var.length;
+ vars.push_back(var);
+ if (!var.is_alias)
+ handle_to_var[h->u.var.handle] = var;
+ std::string clean_name;
+ for(size_t i=0;i<strlen(h->u.var.name);i++)
+ {
+ char c = h->u.var.name[i];
+ if(c==' ') break;
+ clean_name += c;
+ }
+ if (clean_name[0]=='\\')
+ clean_name = clean_name.substr(1);
+
+ name_to_handle[var.scope+"."+clean_name] = h->u.var.handle;
+ break;
+ }
+ }
+ }
+}
+
+
+static void reconstruct_clb_varlen_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
+{
+ FstData *ptr = (FstData*)user_data;
+ ptr->reconstruct_callback_attimes(pnt_time, pnt_facidx, pnt_value, plen);
+}
+
+static void reconstruct_clb_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value)
+{
+ FstData *ptr = (FstData*)user_data;
+ uint32_t plen = (pnt_value) ? strlen((const char *)pnt_value) : 0;
+ ptr->reconstruct_callback_attimes(pnt_time, pnt_facidx, pnt_value, plen);
+}
+
+void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
+{
+ if (pnt_time > end_time) return;
+ // if we are past the timestamp
+ bool is_clock = false;
+ if (!all_samples) {
+ for(auto &s : clk_signals) {
+ if (s==pnt_facidx) {
+ is_clock=true;
+ break;
+ }
+ }
+ }
+
+ if (pnt_time > past_time) {
+ past_data = last_data;
+ past_time = pnt_time;
+ }
+
+ if (pnt_time > last_time) {
+ if (all_samples) {
+ callback(last_time);
+ last_time = pnt_time;
+ } else {
+ if (is_clock) {
+ std::string val = std::string((const char *)pnt_value);
+ std::string prev = past_data[pnt_facidx];
+ if ((prev!="1" && val=="1") || (prev!="0" && val=="0")) {
+ callback(last_time);
+ last_time = pnt_time;
+ }
+ }
+ }
+ }
+ // always update last_data
+ last_data[pnt_facidx] = std::string((const char *)pnt_value);
+}
+
+void FstData::reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t start, uint64_t end, CallbackFunction cb)
+{
+ clk_signals = signal;
+ callback = cb;
+ start_time = start;
+ end_time = end;
+ last_data.clear();
+ last_time = start_time;
+ past_data.clear();
+ past_time = start_time;
+ all_samples = clk_signals.empty();
+
+ fstReaderSetUnlimitedTimeRange(ctx);
+ fstReaderSetFacProcessMaskAll(ctx);
+ fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
+ past_data = last_data;
+ callback(last_time);
+ if (last_time!=end_time)
+ callback(end_time);
+}
+
+std::string FstData::valueOf(fstHandle signal)
+{
+ if (past_data.find(signal) == past_data.end())
+ log_error("Signal id %d not found\n", (int)signal);
+ return past_data[signal];
+}
diff --git a/kernel/fstdata.h b/kernel/fstdata.h
new file mode 100644
index 000000000..0e9d27e2c
--- /dev/null
+++ b/kernel/fstdata.h
@@ -0,0 +1,83 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Miodrag Milanovic <micko@yosyshq.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.
+ *
+ */
+
+#ifndef FSTDATA_H
+#define FSTDATA_H
+
+#include "kernel/yosys.h"
+#include "libs/fst/fstapi.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+typedef std::function<void(uint64_t)> CallbackFunction;
+struct fst_end_of_data_exception { };
+
+struct FstVar
+{
+ fstHandle id;
+ std::string name;
+ bool is_alias;
+ bool is_reg;
+ std::string scope;
+ int width;
+};
+
+class FstData
+{
+ public:
+ FstData(std::string filename);
+ ~FstData();
+
+ uint64_t getStartTime();
+ uint64_t getEndTime();
+
+ std::vector<FstVar>& getVars() { return vars; };
+
+ void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
+ void reconstructAllAtTimes(std::vector<fstHandle> &signal, uint64_t start_time, uint64_t end_time, CallbackFunction cb);
+
+ std::string valueOf(fstHandle signal);
+ fstHandle getHandle(std::string name);
+ double getTimescale() { return timescale; }
+ const char *getTimescaleString() { return timescale_str.c_str(); }
+private:
+ void extractVarNames();
+
+ struct fstReaderContext *ctx;
+ std::vector<std::string> scopes;
+ std::vector<FstVar> vars;
+ std::map<fstHandle, FstVar> handle_to_var;
+ std::map<std::string, fstHandle> name_to_handle;
+ std::map<fstHandle, std::string> last_data;
+ uint64_t last_time;
+ std::map<fstHandle, std::string> past_data;
+ uint64_t past_time;
+ double timescale;
+ std::string timescale_str;
+ uint64_t start_time;
+ uint64_t end_time;
+ CallbackFunction callback;
+ std::vector<fstHandle> clk_signals;
+ bool all_samples;
+ std::string tmp_file;
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/kernel/mem.cc b/kernel/mem.cc
index 96168ff76..059f8f934 100644
--- a/kernel/mem.cc
+++ b/kernel/mem.cc
@@ -1352,3 +1352,315 @@ void Mem::widen_wr_port(int idx, int wide_log2) {
port.wide_log2 = wide_log2;
}
}
+
+void Mem::emulate_rden(int idx, FfInitVals *initvals) {
+ auto &port = rd_ports[idx];
+ log_assert(port.clk_enable);
+ emulate_rd_ce_over_srst(idx);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ Wire *prev_data = module->addWire(NEW_ID, GetSize(port.data));
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ FfData ff_data(module, initvals, NEW_ID);
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = port.en;
+ ff_sel.sig_q = sel;
+ ff_data.width = GetSize(port.data);
+ ff_data.has_clk = true;
+ ff_data.sig_clk = port.clk;
+ ff_data.pol_clk = port.clk_polarity;
+ ff_data.sig_d = port.data;
+ ff_data.sig_q = prev_data;
+ if (!port.init_value.is_fully_undef()) {
+ ff_sel.val_init = State::S0;
+ ff_data.val_init = port.init_value;
+ port.init_value = Const(State::Sx, GetSize(port.data));
+ } else {
+ ff_sel.val_init = State::Sx;
+ ff_data.val_init = Const(State::Sx, GetSize(port.data));
+ }
+ if (port.arst != State::S0) {
+ ff_sel.has_arst = true;
+ ff_sel.val_arst = State::S0;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ ff_data.has_arst = true;
+ ff_data.val_arst = port.arst_value;
+ ff_data.sig_arst = port.arst;
+ ff_data.pol_arst = true;
+ port.arst = State::S0;
+ }
+ if (port.srst != State::S0) {
+ log_assert(!port.ce_over_srst);
+ ff_sel.has_srst = true;
+ ff_sel.val_srst = State::S0;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ ff_sel.ce_over_srst = false;
+ ff_data.has_srst = true;
+ ff_data.val_srst = port.srst_value;
+ ff_data.sig_srst = port.srst;
+ ff_data.pol_srst = true;
+ ff_data.ce_over_srst = false;
+ port.srst = State::S0;
+ }
+ ff_sel.emit();
+ ff_data.emit();
+ module->addMux(NEW_ID, prev_data, new_data, sel, port.data);
+ port.data = new_data;
+ port.en = State::S1;
+}
+
+void Mem::emulate_reset(int idx, bool emu_init, bool emu_arst, bool emu_srst, FfInitVals *initvals) {
+ auto &port = rd_ports[idx];
+ if (emu_init && !port.init_value.is_fully_undef()) {
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = State::S1;
+ ff_sel.sig_q = sel;
+ ff_sel.val_init = State::S0;
+ if (port.en != State::S1) {
+ ff_sel.has_ce = true;
+ ff_sel.sig_ce = port.en;
+ ff_sel.pol_ce = true;
+ ff_sel.ce_over_srst = port.ce_over_srst;
+ }
+ if (port.arst != State::S0) {
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ if (emu_arst && port.arst_value == port.init_value) {
+ // If we're going to emulate async reset anyway, and the reset
+ // value is the same as init value, reuse the same mux.
+ ff_sel.val_arst = State::S0;
+ port.arst = State::S0;
+ } else {
+ ff_sel.val_arst = State::S1;
+ }
+ }
+ if (port.srst != State::S0) {
+ ff_sel.has_srst = true;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ if (emu_srst && port.srst_value == port.init_value) {
+ ff_sel.val_srst = State::S0;
+ port.srst = State::S0;
+ } else {
+ ff_sel.val_srst = State::S1;
+ }
+ }
+ ff_sel.emit();
+ module->addMux(NEW_ID, port.init_value, new_data, sel, port.data);
+ port.data = new_data;
+ port.init_value = Const(State::Sx, GetSize(port.data));
+ }
+ if (emu_arst && port.arst != State::S0) {
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = State::S1;
+ ff_sel.sig_q = sel;
+ if (port.init_value.is_fully_undef())
+ ff_sel.val_init = State::Sx;
+ else
+ ff_sel.val_init = State::S1;
+ if (port.en != State::S1) {
+ ff_sel.has_ce = true;
+ ff_sel.sig_ce = port.en;
+ ff_sel.pol_ce = true;
+ ff_sel.ce_over_srst = port.ce_over_srst;
+ }
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ ff_sel.val_arst = State::S0;
+ if (port.srst != State::S0) {
+ ff_sel.has_srst = true;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ if (emu_srst && port.srst_value == port.arst_value) {
+ ff_sel.val_srst = State::S0;
+ port.srst = State::S0;
+ } else {
+ ff_sel.val_srst = State::S1;
+ }
+ }
+ ff_sel.emit();
+ module->addMux(NEW_ID, port.arst_value, new_data, sel, port.data);
+ port.data = new_data;
+ port.arst = State::S0;
+ }
+ if (emu_srst && port.srst != State::S0) {
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = State::S1;
+ ff_sel.sig_q = sel;
+ if (port.init_value.is_fully_undef())
+ ff_sel.val_init = State::Sx;
+ else
+ ff_sel.val_init = State::S1;
+ if (port.en != State::S1) {
+ ff_sel.has_ce = true;
+ ff_sel.sig_ce = port.en;
+ ff_sel.pol_ce = true;
+ ff_sel.ce_over_srst = port.ce_over_srst;
+ }
+ ff_sel.has_srst = true;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ ff_sel.val_srst = State::S0;
+ if (port.arst != State::S0) {
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ ff_sel.val_arst = State::S1;
+ }
+ ff_sel.emit();
+ module->addMux(NEW_ID, port.srst_value, new_data, sel, port.data);
+ port.data = new_data;
+ port.srst = State::S0;
+ }
+}
+
+void Mem::emulate_rd_ce_over_srst(int idx) {
+ auto &port = rd_ports[idx];
+ log_assert(port.clk_enable);
+ if (port.en == State::S1 || port.srst == State::S0 || !port.ce_over_srst) {
+ port.ce_over_srst = false;
+ return;
+ }
+ port.ce_over_srst = false;
+ port.srst = module->And(NEW_ID, port.en, port.srst);
+}
+
+void Mem::emulate_rd_srst_over_ce(int idx) {
+ auto &port = rd_ports[idx];
+ log_assert(port.clk_enable);
+ if (port.en == State::S1 || port.srst == State::S0 || port.ce_over_srst) {
+ port.ce_over_srst = true;
+ return;
+ }
+ port.ce_over_srst = true;
+ port.en = module->Or(NEW_ID, port.en, port.srst);
+}
+
+bool Mem::emulate_read_first_ok() {
+ if (wr_ports.empty())
+ return false;
+ SigSpec clk = wr_ports[0].clk;
+ bool clk_polarity = wr_ports[0].clk_polarity;
+ for (auto &port: wr_ports) {
+ if (!port.clk_enable)
+ return false;
+ if (port.clk != clk)
+ return false;
+ if (port.clk_polarity != clk_polarity)
+ return false;
+ }
+ bool found_read_first = false;
+ for (auto &port: rd_ports) {
+ if (!port.clk_enable)
+ return false;
+ if (port.clk != clk)
+ return false;
+ if (port.clk_polarity != clk_polarity)
+ return false;
+ // No point doing this operation if there is no read-first relationship
+ // in the first place.
+ for (int j = 0; j < GetSize(wr_ports); j++)
+ if (!port.transparency_mask[j] && !port.collision_x_mask[j])
+ found_read_first = true;
+ }
+ return found_read_first;
+}
+
+void Mem::emulate_read_first(FfInitVals *initvals) {
+ log_assert(emulate_read_first_ok());
+ for (int i = 0; i < GetSize(rd_ports); i++)
+ for (int j = 0; j < GetSize(wr_ports); j++)
+ if (rd_ports[i].transparency_mask[j])
+ emulate_transparency(j, i, initvals);
+ for (int i = 0; i < GetSize(rd_ports); i++)
+ for (int j = 0; j < GetSize(wr_ports); j++) {
+ log_assert(!rd_ports[i].transparency_mask[j]);
+ rd_ports[i].collision_x_mask[j] = false;
+ rd_ports[i].transparency_mask[j] = true;
+ }
+ for (auto &port: wr_ports) {
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ Wire *new_addr = module->addWire(NEW_ID, GetSize(port.addr));
+ auto compressed = port.compress_en();
+ Wire *new_en = module->addWire(NEW_ID, GetSize(compressed.first));
+ FfData ff_data(module, initvals, NEW_ID);
+ FfData ff_addr(module, initvals, NEW_ID);
+ FfData ff_en(module, initvals, NEW_ID);
+ ff_data.width = GetSize(port.data);
+ ff_data.has_clk = true;
+ ff_data.sig_clk = port.clk;
+ ff_data.pol_clk = port.clk_polarity;
+ ff_data.sig_d = port.data;
+ ff_data.sig_q = new_data;;
+ ff_data.val_init = Const(State::Sx, ff_data.width);
+ ff_data.emit();
+ ff_addr.width = GetSize(port.addr);
+ ff_addr.has_clk = true;
+ ff_addr.sig_clk = port.clk;
+ ff_addr.pol_clk = port.clk_polarity;
+ ff_addr.sig_d = port.addr;
+ ff_addr.sig_q = new_addr;;
+ ff_addr.val_init = Const(State::Sx, ff_addr.width);
+ ff_addr.emit();
+ ff_en.width = GetSize(compressed.first);
+ ff_en.has_clk = true;
+ ff_en.sig_clk = port.clk;
+ ff_en.pol_clk = port.clk_polarity;
+ ff_en.sig_d = compressed.first;
+ ff_en.sig_q = new_en;;
+ ff_en.val_init = Const(State::S0, ff_en.width);
+ ff_en.emit();
+ port.data = new_data;
+ port.addr = new_addr;
+ port.en = port.decompress_en(compressed.second, new_en);
+ }
+}
+
+std::pair<SigSpec, std::vector<int>> MemWr::compress_en() {
+ SigSpec sig = en[0];
+ std::vector<int> swizzle;
+ SigBit prev_bit = en[0];
+ int idx = 0;
+ for (auto &bit: en) {
+ if (bit != prev_bit) {
+ sig.append(bit);
+ prev_bit = bit;
+ idx++;
+ }
+ swizzle.push_back(idx);
+ }
+ log_assert(idx + 1 == GetSize(sig));
+ return {sig, swizzle};
+}
+
+SigSpec MemWr::decompress_en(const std::vector<int> &swizzle, SigSpec sig) {
+ SigSpec res;
+ for (int i: swizzle)
+ res.append(sig[i]);
+ return res;
+}
diff --git a/kernel/mem.h b/kernel/mem.h
index 87a148beb..ae87b1285 100644
--- a/kernel/mem.h
+++ b/kernel/mem.h
@@ -74,6 +74,9 @@ struct MemWr : RTLIL::AttrObject {
res[i] = State(sub >> i & 1);
return res;
}
+
+ std::pair<SigSpec, std::vector<int>> compress_en();
+ SigSpec decompress_en(const std::vector<int> &swizzle, SigSpec sig);
};
struct MemInit : RTLIL::AttrObject {
@@ -191,6 +194,33 @@ struct Mem : RTLIL::AttrObject {
// original address.
void widen_wr_port(int idx, int wide_log2);
+ // Emulates a sync read port's enable functionality in soft logic,
+ // changing the actual read port's enable to be always-on.
+ void emulate_rden(int idx, FfInitVals *initvals);
+
+ // Emulates a sync read port's initial/reset value functionality in
+ // soft logic, removing it from the actual read port.
+ void emulate_reset(int idx, bool emu_init, bool emu_arst, bool emu_srst, FfInitVals *initvals);
+
+ // Given a read port with ce_over_srst set, converts it to a port
+ // with ce_over_srst unset without changing its behavior by adding
+ // emulation logic.
+ void emulate_rd_ce_over_srst(int idx);
+
+ // Given a read port with ce_over_srst unset, converts it to a port
+ // with ce_over_srst set without changing its behavior by adding
+ // emulation logic.
+ void emulate_rd_srst_over_ce(int idx);
+
+ // Returns true iff emulate_read_first makes sense to call.
+ bool emulate_read_first_ok();
+
+ // Emulates all read-first read-write port relationships in terms of
+ // all-transparent ports, by delaying all write ports by one cycle.
+ // This can only be used when all read ports and all write ports are
+ // in the same clock domain.
+ void emulate_read_first(FfInitVals *initvals);
+
Mem(Module *module, IdString memid, int width, int start_offset, int size) : module(module), memid(memid), packed(false), mem(nullptr), cell(nullptr), width(width), start_offset(start_offset), size(size) {}
};
diff --git a/kernel/qcsat.cc b/kernel/qcsat.cc
index b7da958db..aaee984fb 100644
--- a/kernel/qcsat.cc
+++ b/kernel/qcsat.cc
@@ -84,7 +84,7 @@ int QuickConeSat::cell_complexity(RTLIL::Cell *cell)
ID($reduce_xnor), ID($reduce_bool),
ID($logic_not), ID($logic_and), ID($logic_or),
ID($eq), ID($ne), ID($eqx), ID($nex), ID($fa),
- ID($mux), ID($pmux), ID($lut), ID($sop),
+ ID($mux), ID($pmux), ID($bmux), ID($demux), ID($lut), ID($sop),
ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_),
ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
ID($_MUX_), ID($_NMUX_), ID($_MUX4_), ID($_MUX8_), ID($_MUX16_),
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index cd0f5ab12..72dcb89af 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -207,6 +207,7 @@ RTLIL::Const::Const()
RTLIL::Const::Const(std::string str)
{
flags = RTLIL::CONST_FLAG_STRING;
+ bits.reserve(str.size() * 8);
for (int i = str.size()-1; i >= 0; i--) {
unsigned char ch = str[i];
for (int j = 0; j < 8; j++) {
@@ -219,6 +220,7 @@ RTLIL::Const::Const(std::string str)
RTLIL::Const::Const(int val, int width)
{
flags = RTLIL::CONST_FLAG_NONE;
+ bits.reserve(width);
for (int i = 0; i < width; i++) {
bits.push_back((val & 1) != 0 ? State::S1 : State::S0);
val = val >> 1;
@@ -228,6 +230,7 @@ RTLIL::Const::Const(int val, int width)
RTLIL::Const::Const(RTLIL::State bit, int width)
{
flags = RTLIL::CONST_FLAG_NONE;
+ bits.reserve(width);
for (int i = 0; i < width; i++)
bits.push_back(bit);
}
@@ -235,6 +238,7 @@ RTLIL::Const::Const(RTLIL::State bit, int width)
RTLIL::Const::Const(const std::vector<bool> &bits)
{
flags = RTLIL::CONST_FLAG_NONE;
+ this->bits.reserve(bits.size());
for (const auto &b : bits)
this->bits.emplace_back(b ? State::S1 : State::S0);
}
@@ -242,6 +246,7 @@ RTLIL::Const::Const(const std::vector<bool> &bits)
RTLIL::Const::Const(const RTLIL::Const &c)
{
flags = c.flags;
+ this->bits.reserve(c.size());
for (const auto &b : c.bits)
this->bits.push_back(b);
}
@@ -1251,6 +1256,22 @@ namespace {
return;
}
+ if (cell->type == ID($bmux)) {
+ port(ID::A, param(ID::WIDTH) << param(ID::S_WIDTH));
+ port(ID::S, param(ID::S_WIDTH));
+ port(ID::Y, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
+ if (cell->type == ID($demux)) {
+ port(ID::A, param(ID::WIDTH));
+ port(ID::S, param(ID::S_WIDTH));
+ port(ID::Y, param(ID::WIDTH) << param(ID::S_WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($lut)) {
param(ID::LUT);
port(ID::A, param(ID::WIDTH));
@@ -2444,6 +2465,26 @@ DEF_METHOD(Mux, ID($mux), 0)
DEF_METHOD(Pmux, ID($pmux), 1)
#undef DEF_METHOD
+#define DEF_METHOD(_func, _type, _demux) \
+ RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \
+ RTLIL::Cell *cell = addCell(name, _type); \
+ cell->parameters[ID::WIDTH] = _demux ? sig_a.size() : sig_y.size(); \
+ cell->parameters[ID::S_WIDTH] = sig_s.size(); \
+ cell->setPort(ID::A, sig_a); \
+ cell->setPort(ID::S, sig_s); \
+ cell->setPort(ID::Y, sig_y); \
+ cell->set_src_attribute(src); \
+ return cell; \
+ } \
+ RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \
+ RTLIL::SigSpec sig_y = addWire(NEW_ID, _demux ? sig_a.size() << sig_s.size() : sig_a.size() >> sig_s.size()); \
+ add ## _func(name, sig_a, sig_s, sig_y, src); \
+ return sig_y; \
+ }
+DEF_METHOD(Bmux, ID($bmux), 0)
+DEF_METHOD(Demux, ID($demux), 1)
+#undef DEF_METHOD
+
#define DEF_METHOD_2(_func, _type, _P1, _P2) \
RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \
RTLIL::Cell *cell = addCell(name, _type); \
@@ -3358,14 +3399,21 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:"))
return;
- if (type == ID($mux) || type == ID($pmux)) {
+ if (type == ID($mux) || type == ID($pmux) || type == ID($bmux)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::Y]);
- if (type == ID($pmux))
+ if (type != ID($mux))
parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
check();
return;
}
+ if (type == ID($demux)) {
+ parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
+ parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
+ check();
+ return;
+ }
+
if (type == ID($lut) || type == ID($sop)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
return;
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index a562d253c..d8300f159 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -485,6 +485,9 @@ namespace RTLIL
RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
+ RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
+ RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
+
// This iterator-range-pair is used for Design::modules(), Module::wires() and Module::cells().
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
@@ -1296,6 +1299,8 @@ public:
RTLIL::Cell* addMux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
RTLIL::Cell* addPmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
+ RTLIL::Cell* addBmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
+ RTLIL::Cell* addDemux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
RTLIL::Cell* addSlice (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src = "");
RTLIL::Cell* addConcat (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = "");
@@ -1421,6 +1426,8 @@ public:
RTLIL::SigSpec Mux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
RTLIL::SigSpec Pmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
+ RTLIL::SigSpec Bmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src = "");
+ RTLIL::SigSpec Demux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src = "");
RTLIL::SigBit BufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = "");
RTLIL::SigBit NotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = "");
diff --git a/kernel/satgen.cc b/kernel/satgen.cc
index 214826f5a..9c40ec66d 100644
--- a/kernel/satgen.cc
+++ b/kernel/satgen.cc
@@ -252,6 +252,106 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
return true;
}
+ if (cell->type == ID($bmux))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> s = importDefSigSpec(cell->getPort(ID::S), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> undef_a, undef_s, undef_y;
+
+ if (model_undef)
+ {
+ undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
+ undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ }
+
+ if (GetSize(s) == 0) {
+ ez->vec_set(a, y);
+ if (model_undef)
+ ez->vec_set(undef_a, undef_y);
+ } else {
+ for (int i = GetSize(s)-1; i >= 0; i--)
+ {
+ std::vector<int> out = (i == 0) ? y : ez->vec_var(a.size() / 2);
+ std::vector<int> yy = model_undef ? ez->vec_var(out.size()) : out;
+
+ std::vector<int> a0(a.begin(), a.begin() + a.size() / 2);
+ std::vector<int> a1(a.begin() + a.size() / 2, a.end());
+ ez->assume(ez->vec_eq(ez->vec_ite(s.at(i), a1, a0), yy));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_out = (i == 0) ? undef_y : ez->vec_var(a.size() / 2);
+ std::vector<int> undef_a0(undef_a.begin(), undef_a.begin() + a.size() / 2);
+ std::vector<int> undef_a1(undef_a.begin() + a.size() / 2, undef_a.end());
+ std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a0, a1));
+ std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a0, undef_a1));
+ std::vector<int> yX = ez->vec_ite(undef_s.at(i), undef_ab, ez->vec_ite(s.at(i), undef_a1, undef_a0));
+ ez->assume(ez->vec_eq(yX, undef_out));
+ undefGating(out, yy, undef_out);
+
+ undef_a = undef_out;
+ }
+
+ a = out;
+ }
+ }
+ return true;
+ }
+
+ if (cell->type == ID($demux))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> s = importDefSigSpec(cell->getPort(ID::S), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ std::vector<int> undef_a, undef_s, undef_y;
+
+ if (model_undef)
+ {
+ undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
+ undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ }
+
+ if (GetSize(s) == 0) {
+ ez->vec_set(a, y);
+ if (model_undef)
+ ez->vec_set(undef_a, undef_y);
+ } else {
+ for (int i = 0; i < (1 << GetSize(s)); i++)
+ {
+ std::vector<int> ss;
+ for (int j = 0; j < GetSize(s); j++) {
+ if (i & 1 << j)
+ ss.push_back(s[j]);
+ else
+ ss.push_back(ez->NOT(s[j]));
+ }
+ int sss = ez->expression(ezSAT::OpAnd, ss);
+
+ for (int j = 0; j < GetSize(a); j++) {
+ ez->SET(ez->AND(sss, a[j]), yy.at(i * GetSize(a) + j));
+ }
+
+ if (model_undef)
+ {
+ int s0 = ez->expression(ezSAT::OpOr, ez->vec_and(ez->vec_not(ss), ez->vec_not(undef_s)));
+ int us = ez->AND(ez->NOT(s0), ez->expression(ezSAT::OpOr, undef_s));
+ for (int j = 0; j < GetSize(a); j++) {
+ int a0 = ez->AND(ez->NOT(a[j]), ez->NOT(undef_a[j]));
+ int yX = ez->AND(ez->OR(us, undef_a[j]), ez->NOT(ez->OR(s0, a0)));
+ ez->SET(yX, undef_y.at(i * GetSize(a) + j));
+ }
+ }
+ }
+ if (model_undef)
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
if (cell->type == ID($pmux))
{
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 102f9e737..09909696b 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -618,6 +618,23 @@ RTLIL::IdString new_id(std::string file, int line, std::string func)
return stringf("$auto$%s:%d:%s$%d", file.c_str(), line, func.c_str(), autoidx++);
}
+RTLIL::IdString new_id_suffix(std::string file, int line, std::string func, std::string suffix)
+{
+#ifdef _WIN32
+ size_t pos = file.find_last_of("/\\");
+#else
+ size_t pos = file.find_last_of('/');
+#endif
+ if (pos != std::string::npos)
+ file = file.substr(pos+1);
+
+ pos = func.find_last_of(':');
+ if (pos != std::string::npos)
+ func = func.substr(pos+1);
+
+ return stringf("$auto$%s:%d:%s$%s$%d", file.c_str(), line, func.c_str(), suffix.c_str(), autoidx++);
+}
+
RTLIL::Design *yosys_get_design()
{
return yosys_design;
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 091e2282f..93e7ff23e 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -322,9 +322,12 @@ Tcl_Interp *yosys_get_tcl_interp();
extern RTLIL::Design *yosys_design;
RTLIL::IdString new_id(std::string file, int line, std::string func);
+RTLIL::IdString new_id_suffix(std::string file, int line, std::string func, std::string suffix);
#define NEW_ID \
YOSYS_NAMESPACE_PREFIX new_id(__FILE__, __LINE__, __FUNCTION__)
+#define NEW_ID_SUFFIX(suffix) \
+ YOSYS_NAMESPACE_PREFIX new_id_suffix(__FILE__, __LINE__, __FUNCTION__, suffix)
// Create a statically allocated IdString object, using for example ID::A or ID($add).
//
diff --git a/libs/fst/block_format.txt b/libs/fst/block_format.txt
new file mode 100644
index 000000000..e6fe1661b
--- /dev/null
+++ b/libs/fst/block_format.txt
@@ -0,0 +1,130 @@
+See fstapi.h for the values for the FST_BL_XXX enums.
+
+===========================================================================
+
+compressed wrapper (typically over whole file)
+
+uint8_t FST_BL_ZWRAPPER
+uint64_t section length
+uint64_t length of uncompressed data
+[zlib compressed data]
+
+===========================================================================
+
+header block
+
+uint8_t FST_BL_HDR
+uint64_t section length
+uint64_t start time
+uint64_t end time
+double endian test for "e"
+uint64_t memory used by writer
+uint64_t scope creation count
+uint64_t var creation count
+uint64_t max var idcode
+uint64_t vc section count
+int8_t timescale exponent
+[128 bytes] version
+[128 bytes] date
+
+===========================================================================
+
+geometry block
+
+uint8_t FST_BL_GEOM
+uint64_t section length
+uint64_t length of uncompressed geometry data
+uint64_t maxhandle
+[compressed data]
+
+(length of compressed data is section length - 24)
+
+===========================================================================
+
+hierarchy block
+
+uint8_t FST_BL_HIER
+uint64_t section length
+uint64_t length of uncompressed hier data
+[zlib compressed data]
+
+or
+
+uint8_t FST_BL_HIER_LZ4
+uint64_t section length
+uint64_t length of uncompressed hier data
+[lz4 compressed data]
+
+uint8_t FST_BL_HIER_LZ4DUO
+uint64_t section length
+uint64_t length of uncompressed hier data
+varint length of hier data compressed once with lz4
+[lz4 double compressed data]
+
+
+===========================================================================
+
+dumpon/off block
+
+uint8_t FST_BL_BLACKOUT
+uint64_t section length
+varint num blackouts (section below is repeated this # times)
+[
+uint8_t on/off (nonzero = on)
+varint delta time
+]
+
+===========================================================================
+
+1..n value change blocks:
+
+// header
+
+uint8_t FST_BL_VCDATA (or FST_BL_VCDATA_DYN_ALIAS)
+uint64_t section length
+uint64_t begin time of section
+uint64_t end time of section
+uint64_t amount of buffer memory required in reader for full vc traversal
+varint maxvalpos (length of uncompressed data)
+varint length of compressed data
+varint maxhandle associated with this checkpoint data
+[compressed data]
+
+---
+
+// value changes
+
+varint maxhandle associated with the value change data
+uint8_t pack type ('F' is fastlz, '4' is lz4,
+ others ['Z'/'!'] are zlib)
+
+varint chain 0 compressed data length (0 = uncompressed)
+[compressed data]
+...
+varint chain n compressed data length (0 = uncompressed)
+[compressed data]
+
+---
+
+// index: chain pointer table (from 0..maxhandle-1)
+
+varint if &1 == 1, this is <<1 literal delta
+ if &1 == 0, this is <<1 RLE count of zeros
+ if == 0, next varint is handle of prev chain to use,
+ bit only if FST_BL_VCDATA_DYN_ALIAS or
+ later VCDATA format
+
+---
+
+uint64_t index length (subtract from here to get index position)
+
+---
+
+[compressed data for time section]
+uint64_t uncompressed data length in bytes
+uint64_t compressed data length in bytes
+uint64_t number of time items
+
+// end of section
+
+===========================================================================
diff --git a/libs/fst/config.h b/libs/fst/config.h
new file mode 100644
index 000000000..0598fb8c5
--- /dev/null
+++ b/libs/fst/config.h
@@ -0,0 +1,27 @@
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#define HAVE_LIBPTHREAD 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+#if defined(__MINGW32__)
+#undef HAVE_ALLOCA_H
+#undef HAVE_REALPATH
+#endif
+#if defined(_MSC_VER)
+#undef HAVE_ALLOCA_H
+#undef HAVE_REALPATH
+#undef HAVE_LIBPTHREAD
+#undef HAVE_FSEEKO
+#endif
+
+# ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+# endif
diff --git a/libs/fst/fastlz.cc b/libs/fst/fastlz.cc
new file mode 100644
index 000000000..68bda3346
--- /dev/null
+++ b/libs/fst/fastlz.cc
@@ -0,0 +1,528 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ SPDX-License-Identifier: MIT
+*/
+
+#include "fastlz.h"
+
+#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+
+/*
+ * Always check for bound when decompressing.
+ * Generally it is best to leave it defined.
+ */
+#define FASTLZ_SAFE
+
+/*
+ * Give hints to the compiler for branch prediction optimization.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#else
+#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#endif
+
+/*
+ * Use inlined functions for supported systems.
+ */
+#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
+#define FASTLZ_INLINE inline
+#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
+#define FASTLZ_INLINE __inline
+#else
+#define FASTLZ_INLINE
+#endif
+
+/*
+ * Prevent accessing more than 8-bit at once, except on x86 architectures.
+ */
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_STRICT_ALIGN
+#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__amd64) /* GNU C */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_M_IX86) /* Intel, MSVC */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__386)
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_X86_) /* MinGW */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__I86__) /* Digital Mars */
+#undef FASTLZ_STRICT_ALIGN
+#endif
+#endif
+
+/* prototypes */
+int fastlz_compress(const void *input, int length, void *output);
+int fastlz_compress_level(int level, const void *input, int length, void *output);
+int fastlz_decompress(const void *input, int length, void *output, int maxout);
+
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_DISTANCE 8192
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_READU16(p) *((const flzuint16 *)(p))
+#else
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1] << 8)
+#endif
+
+#define HASH_LOG 13
+#define HASH_SIZE (1 << HASH_LOG)
+#define HASH_MASK (HASH_SIZE - 1)
+#define HASH_FUNCTION(v, p) \
+ { \
+ v = FASTLZ_READU16(p); \
+ v ^= FASTLZ_READU16(p + 1) ^ (v >> (16 - HASH_LOG)); \
+ v &= HASH_MASK; \
+ }
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 1
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz1_compress
+#define FASTLZ_DECOMPRESSOR fastlz1_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout);
+#include "fastlz.cc"
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 2
+
+#undef MAX_DISTANCE
+#define MAX_DISTANCE 8191
+#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1)
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz2_compress
+#define FASTLZ_DECOMPRESSOR fastlz2_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout);
+#include "fastlz.cc"
+
+int fastlz_compress(const void *input, int length, void *output)
+{
+ /* for short block, choose fastlz1 */
+ if (length < 65536)
+ return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void *input, int length, void *output, int maxout)
+{
+ /* magic identifier for compression level */
+ int level = ((*(const flzuint8 *)input) >> 5) + 1;
+
+ if (level == 1)
+ return fastlz1_decompress(input, length, output, maxout);
+ if (level == 2)
+ return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void *input, int length, void *output)
+{
+ if (level == 1)
+ return fastlz1_compress(input, length, output);
+ if (level == 2)
+ return fastlz2_compress(input, length, output);
+
+ return 0;
+}
+
+#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output)
+{
+ const flzuint8 *ip = (const flzuint8 *)input;
+ const flzuint8 *ip_bound = ip + length - 2;
+ const flzuint8 *ip_limit = ip + length - 12;
+ flzuint8 *op = (flzuint8 *)output;
+
+ const flzuint8 *htab[HASH_SIZE];
+ const flzuint8 **hslot;
+ flzuint32 hval;
+
+ flzuint32 copy;
+
+ /* sanity check */
+ if (FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) {
+ if (length) {
+ /* create literal copy only */
+ *op++ = length - 1;
+ ip_bound++;
+ while (ip <= ip_bound)
+ *op++ = *ip++;
+ return length + 1;
+ } else
+ return 0;
+ }
+
+ /* initializes hash table */
+ for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
+ *hslot = ip;
+
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY - 1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) {
+ const flzuint8 *ref;
+ flzuint32 distance;
+
+ /* minimum match length */
+ flzuint32 len = 3;
+
+ /* comparison starting-point */
+ const flzuint8 *anchor = ip;
+
+ /* check for a run */
+#if FASTLZ_LEVEL == 2
+ if (ip[0] == ip[-1] && FASTLZ_READU16(ip - 1) == FASTLZ_READU16(ip + 1)) {
+ distance = 1;
+ /* ip += 3; */ /* scan-build, never used */
+ ref = anchor - 1 + 3;
+ goto match;
+ }
+#endif
+
+ /* find potential match */
+ HASH_FUNCTION(hval, ip);
+ hslot = htab + hval;
+ ref = htab[hval];
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* update hash table */
+ *hslot = anchor;
+
+ /* is this a match? check the first 3 bytes */
+ if (distance == 0 ||
+#if FASTLZ_LEVEL == 1
+ (distance >= MAX_DISTANCE) ||
+#else
+ (distance >= MAX_FARDISTANCE) ||
+#endif
+ *ref++ != *ip++ || *ref++ != *ip++ || *ref++ != *ip++)
+ goto literal;
+
+#if FASTLZ_LEVEL == 2
+ /* far, needs at least 5-byte match */
+ if (distance >= MAX_DISTANCE) {
+ if (*ip++ != *ref++ || *ip++ != *ref++)
+ goto literal;
+ len += 2;
+ }
+
+ match:
+#endif
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if (!distance) {
+ /* zero distance means a run */
+ flzuint8 x = ip[-1];
+ while (ip < ip_bound)
+ if (*ref++ != x)
+ break;
+ else
+ ip++;
+ } else
+ for (;;) {
+ /* safe because the outer check against ip limit */
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ while (ip < ip_bound)
+ if (*ref++ != *ip++)
+ break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if (copy)
+ /* copy is biased, '0' means 1 byte copy */
+ *(op - copy - 1) = copy - 1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+#if FASTLZ_LEVEL == 2
+ if (distance < MAX_DISTANCE) {
+ if (len < 7) {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ } else {
+ *op++ = (7 << 5) + (distance >> 8);
+ for (len -= 7; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = (distance & 255);
+ }
+ } else {
+ /* far away, but not yet in the another galaxy... */
+ if (len < 7) {
+ distance -= MAX_DISTANCE;
+ *op++ = (len << 5) + 31;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ } else {
+ distance -= MAX_DISTANCE;
+ *op++ = (7 << 5) + 31;
+ for (len -= 7; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ }
+#else
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN - 2))
+ while (len > MAX_LEN - 2) {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 - 2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN - 2;
+ }
+
+ if (len < 7) {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ } else {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+#endif
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY - 1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while (ip <= ip_bound) {
+ *op++ = *ip++;
+ copy++;
+ if (copy == MAX_COPY) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if (copy)
+ *(op - copy - 1) = copy - 1;
+ else
+ op--;
+
+#if FASTLZ_LEVEL == 2
+ /* marker for fastlz2 */
+ *(flzuint8 *)output |= (1 << 5);
+#endif
+
+ return op - (flzuint8 *)output;
+}
+
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout)
+{
+ const flzuint8 *ip = (const flzuint8 *)input;
+ const flzuint8 *ip_limit = ip + length;
+ flzuint8 *op = (flzuint8 *)output;
+ flzuint8 *op_limit = op + maxout;
+ flzuint32 ctrl = (*ip++) & 31;
+ int loop = 1;
+
+ do {
+ const flzuint8 *ref = op;
+ flzuint32 len = ctrl >> 5;
+ flzuint32 ofs = (ctrl & 31) << 8;
+
+ if (ctrl >= 32) {
+#if FASTLZ_LEVEL == 2
+ flzuint8 code;
+#endif
+ len--;
+ ref -= ofs;
+ if (len == 7 - 1)
+#if FASTLZ_LEVEL == 1
+ len += *ip++;
+ ref -= *ip++;
+#else
+ do {
+ code = *ip++;
+ len += code;
+ } while (code == 255);
+ code = *ip++;
+ ref -= code;
+
+ /* match from 16-bit distance */
+ if (FASTLZ_UNEXPECT_CONDITIONAL(code == 255))
+ if (FASTLZ_EXPECT_CONDITIONAL(ofs == (31 << 8))) {
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_DISTANCE;
+ }
+#endif
+
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
+ return 0;
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ref - 1 < (flzuint8 *)output))
+ return 0;
+#endif
+
+ if (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ ctrl = *ip++;
+ else
+ loop = 0;
+
+ if (ref == op) {
+ /* optimize copy for a run */
+ flzuint8 b = ref[-1];
+ *op++ = b;
+ *op++ = b;
+ *op++ = b;
+ for (; len; --len)
+ *op++ = b;
+ } else {
+#if !defined(FASTLZ_STRICT_ALIGN)
+ const flzuint16 *p;
+ flzuint16 *q;
+#endif
+ /* copy from reference */
+ ref--;
+ *op++ = *ref++;
+ *op++ = *ref++;
+ *op++ = *ref++;
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+ /* copy a byte, so that now it's word aligned */
+ if (len & 1) {
+ *op++ = *ref++;
+ len--;
+ }
+
+ /* copy 16-bit at once */
+ q = (flzuint16 *)op;
+ op += len;
+ p = (const flzuint16 *)ref;
+ for (len >>= 1; len > 4; len -= 4) {
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ }
+ for (; len; --len)
+ *q++ = *p++;
+#else
+ for (; len; --len)
+ *op++ = *ref++;
+#endif
+ }
+ } else {
+ ctrl++;
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
+ return 0;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
+ return 0;
+#endif
+
+ *op++ = *ip++;
+ for (--ctrl; ctrl; ctrl--)
+ *op++ = *ip++;
+
+ loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
+ if (loop)
+ ctrl = *ip++;
+ }
+ } while (FASTLZ_EXPECT_CONDITIONAL(loop));
+
+ return op - (flzuint8 *)output;
+}
+
+#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
diff --git a/libs/fst/fastlz.h b/libs/fst/fastlz.h
new file mode 100644
index 000000000..1ce44a32a
--- /dev/null
+++ b/libs/fst/fastlz.h
@@ -0,0 +1,109 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ SPDX-License-Identifier: MIT
+*/
+
+#ifndef FASTLZ_H
+#define FASTLZ_H
+
+#include <inttypes.h>
+
+#define flzuint8 uint8_t
+#define flzuint16 uint16_t
+#define flzuint32 uint32_t
+
+
+#define FASTLZ_VERSION 0x000100
+
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 0
+#define FASTLZ_VERSION_REVISION 0
+
+#define FASTLZ_VERSION_STRING "0.1.0"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+*/
+
+int fastlz_compress(const void* input, int length, void* output);
+
+/**
+ Decompress a block of compressed data and returns the size of the
+ decompressed block. If error occurs, e.g. the compressed data is
+ corrupted or the output buffer is not large enough, then 0 (zero)
+ will be returned instead.
+
+ The input buffer and the output buffer can not overlap.
+
+ Decompression is memory safe and guaranteed not to write the output buffer
+ more than what is specified in maxout.
+ */
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress above.
+*/
+
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* FASTLZ_H */
diff --git a/libs/fst/fstapi.cc b/libs/fst/fstapi.cc
new file mode 100644
index 000000000..b79470db3
--- /dev/null
+++ b/libs/fst/fstapi.cc
@@ -0,0 +1,6546 @@
+/*
+ * Copyright (c) 2009-2018 Tony Bybell.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/*
+ * possible disables:
+ *
+ * FST_DYNAMIC_ALIAS_DISABLE : dynamic aliases are not processed
+ * FST_DYNAMIC_ALIAS2_DISABLE : new encoding for dynamic aliases is not generated
+ * FST_WRITEX_DISABLE : fast write I/O routines are disabled
+ *
+ * possible enables:
+ *
+ * FST_DEBUG : not for production use, only enable for development
+ * FST_REMOVE_DUPLICATE_VC : glitch removal (has writer performance impact)
+ * HAVE_LIBPTHREAD -> FST_WRITER_PARALLEL : enables inclusion of parallel writer code
+ * FST_DO_MISALIGNED_OPS (defined automatically for x86 and some others) : CPU architecture can handle misaligned
+ * loads/stores _WAVE_HAVE_JUDY : use Judy arrays instead of Jenkins (undefine if LGPL is not acceptable)
+ *
+ */
+
+#ifndef FST_CONFIG_INCLUDE
+#define FST_CONFIG_INCLUDE "config.h"
+#endif
+#include FST_CONFIG_INCLUDE
+
+#include "fstapi.h"
+#include "fastlz.h"
+#include "lz4.h"
+#include <errno.h>
+
+#ifndef HAVE_LIBPTHREAD
+#undef FST_WRITER_PARALLEL
+#endif
+
+#ifdef FST_WRITER_PARALLEL
+#include <pthread.h>
+#endif
+
+#ifdef __MINGW32__
+#include <windows.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#elif defined(__GNUC__)
+#ifndef __MINGW32__
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#else
+#include <malloc.h>
+#endif
+#elif defined(_MSC_VER)
+#include <malloc.h>
+#define alloca _alloca
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX (4096)
+#endif
+
+#if defined(_MSC_VER)
+typedef int64_t fst_off_t;
+#else
+typedef off_t fst_off_t;
+#endif
+
+/* note that Judy versus Jenkins requires more experimentation: they are */
+/* functionally equivalent though it appears Jenkins is slightly faster. */
+/* in addition, Jenkins is not bound by the LGPL. */
+#ifdef _WAVE_HAVE_JUDY
+#include <Judy.h>
+#else
+/* should be more than enough for fstWriterSetSourceStem() */
+#define FST_PATH_HASHMASK ((1UL << 16) - 1)
+typedef const void *Pcvoid_t;
+typedef void *Pvoid_t;
+typedef void **PPvoid_t;
+#define JudyHSIns(a, b, c, d) JenkinsIns((a), (b), (c), (hashmask))
+#define JudyHSFreeArray(a, b) JenkinsFree((a), (hashmask))
+void JenkinsFree(void *base_i, uint32_t hashmask);
+void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask);
+#endif
+
+#ifndef FST_WRITEX_DISABLE
+#define FST_WRITEX_MAX (64 * 1024)
+#else
+#define fstWritex(a, b, c) fstFwrite((b), (c), 1, fv)
+#endif
+
+/* these defines have a large impact on writer speed when a model has a */
+/* huge number of symbols. as a default, use 128MB and increment when */
+/* every 1M signals are defined. */
+#define FST_BREAK_SIZE (1UL << 27)
+#define FST_BREAK_ADD_SIZE (1UL << 22)
+#define FST_BREAK_SIZE_MAX (1UL << 31)
+#define FST_ACTIVATE_HUGE_BREAK (1000000)
+#define FST_ACTIVATE_HUGE_INC (1000000)
+
+#define FST_WRITER_STR "fstWriter"
+#define FST_ID_NAM_SIZ (512)
+#define FST_ID_NAM_ATTR_SIZ (65536 + 4096)
+#define FST_DOUBLE_ENDTEST (2.7182818284590452354)
+#define FST_HDR_SIM_VERSION_SIZE (128)
+#define FST_HDR_DATE_SIZE (119)
+#define FST_HDR_FILETYPE_SIZE (1)
+#define FST_HDR_TIMEZERO_SIZE (8)
+#define FST_GZIO_LEN (32768)
+#define FST_HDR_FOURPACK_DUO_SIZE (4 * 1024 * 1024)
+
+#if defined(__i386__) || defined(__x86_64__) || defined(_AIX)
+#define FST_DO_MISALIGNED_OPS
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
+#define FST_MACOSX
+#include <sys/sysctl.h>
+#endif
+
+#ifdef __GNUC__
+/* Boolean expression more often true than false */
+#define FST_LIKELY(x) __builtin_expect(!!(x), 1)
+/* Boolean expression more often false than true */
+#define FST_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define FST_LIKELY(x) (!!(x))
+#define FST_UNLIKELY(x) (!!(x))
+#endif
+
+#define FST_APIMESS "FSTAPI | "
+
+/***********************/
+/*** ***/
+/*** common function ***/
+/*** ***/
+/***********************/
+
+#if defined(__MINGW32__) || defined(_MSC_VER)
+#include <io.h>
+#ifndef HAVE_FSEEKO
+#define ftello _ftelli64
+#define fseeko _fseeki64
+#endif
+#endif
+
+/*
+ * the recoded "extra" values...
+ * note that FST_RCV_Q is currently unused and is for future expansion.
+ * its intended use is as another level of escape such that any arbitrary
+ * value can be stored as the value: { time_delta, 8 bits, FST_RCV_Q }.
+ * this is currently not implemented so that the branchless decode is:
+ * uint32_t shcnt = 2 << (vli & 1); tdelta = vli >> shcnt;
+ */
+#define FST_RCV_X (1 | (0 << 1))
+#define FST_RCV_Z (1 | (1 << 1))
+#define FST_RCV_H (1 | (2 << 1))
+#define FST_RCV_U (1 | (3 << 1))
+#define FST_RCV_W (1 | (4 << 1))
+#define FST_RCV_L (1 | (5 << 1))
+#define FST_RCV_D (1 | (6 << 1))
+#define FST_RCV_Q (1 | (7 << 1))
+
+#define FST_RCV_STR "xzhuwl-?"
+/* 01234567 */
+
+/*
+ * prevent old file overwrite when currently being read
+ */
+static FILE *unlink_fopen(const char *nam, const char *mode)
+{
+ unlink(nam);
+ return (fopen(nam, mode));
+}
+
+/*
+ * system-specific temp file handling
+ */
+#ifdef __MINGW32__
+
+static FILE *tmpfile_open(char **nam)
+{
+ char *fname = NULL;
+ TCHAR szTempFileName[MAX_PATH];
+ TCHAR lpTempPathBuffer[MAX_PATH];
+ DWORD dwRetVal = 0;
+ UINT uRetVal = 0;
+ FILE *fh = NULL;
+
+ if (nam) /* cppcheck warning fix: nam is always defined, so this is not needed */
+ {
+ dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer);
+ if ((dwRetVal > MAX_PATH) || (dwRetVal == 0)) {
+ fprintf(stderr, FST_APIMESS "GetTempPath() failed in " __FILE__ " line %d, exiting.\n", __LINE__);
+ exit(255);
+ } else {
+ uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName);
+ if (uRetVal == 0) {
+ fprintf(stderr, FST_APIMESS "GetTempFileName() failed in " __FILE__ " line %d, exiting.\n", __LINE__);
+ exit(255);
+ } else {
+ fname = strdup(szTempFileName);
+ }
+ }
+
+ if (fname) {
+ *nam = fname;
+ fh = unlink_fopen(fname, "w+b");
+ }
+ }
+
+ return (fh);
+}
+
+#else
+
+static FILE *tmpfile_open(char **nam)
+{
+ FILE *f = tmpfile(); /* replace with mkstemp() + fopen(), etc if this is not good enough */
+ if (nam) {
+ *nam = NULL;
+ }
+ return (f);
+}
+
+#endif
+
+static void tmpfile_close(FILE **f, char **nam)
+{
+ if (f) {
+ if (*f) {
+ fclose(*f);
+ *f = NULL;
+ }
+ }
+
+ if (nam) {
+ if (*nam) {
+ unlink(*nam);
+ free(*nam);
+ *nam = NULL;
+ }
+ }
+}
+
+/*****************************************/
+
+/*
+ * to remove warn_unused_result compile time messages
+ * (in the future there needs to be results checking)
+ */
+static size_t fstFread(void *buf, size_t siz, size_t cnt, FILE *fp) { return (fread(buf, siz, cnt, fp)); }
+
+static size_t fstFwrite(const void *buf, size_t siz, size_t cnt, FILE *fp) { return (fwrite(buf, siz, cnt, fp)); }
+
+static int fstFtruncate(int fd, fst_off_t length) { return (ftruncate(fd, length)); }
+
+/*
+ * realpath compatibility
+ */
+static char *fstRealpath(const char *path, char *resolved_path)
+{
+#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
+#if (defined(__MACH__) && defined(__APPLE__))
+ if (!resolved_path) {
+ resolved_path = (char *)malloc(PATH_MAX + 1); /* fixes bug on Leopard when resolved_path == NULL */
+ }
+#endif
+
+ return (realpath(path, resolved_path));
+
+#else
+#ifdef __MINGW32__
+ if (!resolved_path) {
+ resolved_path = (char *)malloc(PATH_MAX + 1);
+ }
+ return (_fullpath(resolved_path, path, PATH_MAX));
+#else
+ (void)path;
+ (void)resolved_path;
+ return (NULL);
+#endif
+#endif
+}
+
+/*
+ * mmap compatibility
+ */
+#if defined __CYGWIN__ || defined __MINGW32__ || defined _MSC_VER
+#include <limits.h>
+#define fstMmap(__addr, __len, __prot, __flags, __fd, __off) fstMmap2((__len), (__fd), (__off))
+#define fstMunmap(__addr, __len) free(__addr)
+
+static void *fstMmap2(size_t __len, int __fd, fst_off_t __off)
+{
+ (void)__off;
+
+ unsigned char *pnt = (unsigned char *)malloc(__len);
+ fst_off_t cur_offs = lseek(__fd, 0, SEEK_CUR);
+ size_t i;
+
+ lseek(__fd, 0, SEEK_SET);
+ for (i = 0; i < __len; i += SSIZE_MAX) {
+ read(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i));
+ }
+ lseek(__fd, cur_offs, SEEK_SET);
+ return (pnt);
+}
+#else
+#include <sys/mman.h>
+#if defined(__SUNPRO_C)
+#define FST_CADDR_T_CAST (caddr_t)
+#else
+#define FST_CADDR_T_CAST
+#endif
+#define fstMmap(__addr, __len, __prot, __flags, __fd, __off) \
+ (void *)mmap(FST_CADDR_T_CAST(__addr), (__len), (__prot), (__flags), (__fd), (__off))
+#define fstMunmap(__addr, __len) \
+ { \
+ if (__addr) \
+ munmap(FST_CADDR_T_CAST(__addr), (__len)); \
+ }
+#endif
+
+/*
+ * regular and variable-length integer access functions
+ */
+#ifdef FST_DO_MISALIGNED_OPS
+#define fstGetUint32(x) (*(uint32_t *)(x))
+#else
+static uint32_t fstGetUint32(unsigned char *mem)
+{
+ uint32_t u32;
+ unsigned char *buf = (unsigned char *)(&u32);
+
+ buf[0] = mem[0];
+ buf[1] = mem[1];
+ buf[2] = mem[2];
+ buf[3] = mem[3];
+
+ return (*(uint32_t *)buf);
+}
+#endif
+
+static int fstWriterUint64(FILE *handle, uint64_t v)
+{
+ unsigned char buf[8];
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ buf[i] = v & 0xff;
+ v >>= 8;
+ }
+
+ fstFwrite(buf, 8, 1, handle);
+ return (8);
+}
+
+static uint64_t fstReaderUint64(FILE *f)
+{
+ uint64_t val = 0;
+ unsigned char buf[sizeof(uint64_t)];
+ unsigned int i;
+
+ fstFread(buf, sizeof(uint64_t), 1, f);
+ for (i = 0; i < sizeof(uint64_t); i++) {
+ val <<= 8;
+ val |= buf[i];
+ }
+
+ return (val);
+}
+
+static uint32_t fstGetVarint32(unsigned char *mem, int *skiplen)
+{
+ unsigned char *mem_orig = mem;
+ uint32_t rc = 0;
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ *skiplen = mem - mem_orig + 1;
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == mem_orig) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint32_t fstGetVarint32Length(unsigned char *mem)
+{
+ unsigned char *mem_orig = mem;
+
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ return (mem - mem_orig + 1);
+}
+
+static uint32_t fstGetVarint32NoSkip(unsigned char *mem)
+{
+ unsigned char *mem_orig = mem;
+ uint32_t rc = 0;
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == mem_orig) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static unsigned char *fstCopyVarint32ToLeft(unsigned char *pnt, uint32_t v)
+{
+ unsigned char *spnt;
+ uint32_t nxt = v;
+ int cnt = 1;
+ int i;
+
+ while ((nxt = nxt >> 7)) /* determine len to avoid temp buffer copying to cut down on load-hit-store */
+ {
+ cnt++;
+ }
+
+ pnt -= cnt;
+ spnt = pnt;
+ cnt--;
+
+ for (i = 0; i < cnt; i++) /* now generate left to right as normal */
+ {
+ nxt = v >> 7;
+ *(spnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *spnt = (unsigned char)v;
+
+ return (pnt);
+}
+
+static unsigned char *fstCopyVarint64ToRight(unsigned char *pnt, uint64_t v)
+{
+ uint64_t nxt;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ return (pnt);
+}
+
+static uint64_t fstGetVarint64(unsigned char *mem, int *skiplen)
+{
+ unsigned char *mem_orig = mem;
+ uint64_t rc = 0;
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ *skiplen = mem - mem_orig + 1;
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint64_t)(*mem & 0x7f);
+ if (mem == mem_orig) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint32_t fstReaderVarint32(FILE *f)
+{
+ unsigned char buf[5];
+ unsigned char *mem = buf;
+ uint32_t rc = 0;
+ int ch;
+
+ do {
+ ch = fgetc(f);
+ *(mem++) = ch;
+ } while (ch & 0x80);
+ mem--;
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == buf) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint32_t fstReaderVarint32WithSkip(FILE *f, uint32_t *skiplen)
+{
+ unsigned char buf[5];
+ unsigned char *mem = buf;
+ uint32_t rc = 0;
+ int ch;
+
+ do {
+ ch = fgetc(f);
+ *(mem++) = ch;
+ } while (ch & 0x80);
+ *skiplen = mem - buf;
+ mem--;
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == buf) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint64_t fstReaderVarint64(FILE *f)
+{
+ unsigned char buf[16];
+ unsigned char *mem = buf;
+ uint64_t rc = 0;
+ int ch;
+
+ do {
+ ch = fgetc(f);
+ *(mem++) = ch;
+ } while (ch & 0x80);
+ mem--;
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint64_t)(*mem & 0x7f);
+ if (mem == buf) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static int fstWriterVarint(FILE *handle, uint64_t v)
+{
+ uint64_t nxt;
+ unsigned char buf[10]; /* ceil(64/7) = 10 */
+ unsigned char *pnt = buf;
+ int len;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ len = pnt - buf;
+ fstFwrite(buf, len, 1, handle);
+ return (len);
+}
+
+/* signed integer read/write routines are currently unused */
+static int64_t fstGetSVarint64(unsigned char *mem, int *skiplen)
+{
+ unsigned char *mem_orig = mem;
+ int64_t rc = 0;
+ const int64_t one = 1;
+ const int siz = sizeof(int64_t) * 8;
+ int shift = 0;
+ unsigned char byt;
+
+ do {
+ byt = *(mem++);
+ rc |= ((int64_t)(byt & 0x7f)) << shift;
+ shift += 7;
+
+ } while (byt & 0x80);
+
+ if ((shift < siz) && (byt & 0x40)) {
+ rc |= -(one << shift); /* sign extend */
+ }
+
+ *skiplen = mem - mem_orig;
+
+ return (rc);
+}
+
+#ifndef FST_DYNAMIC_ALIAS2_DISABLE
+static int fstWriterSVarint(FILE *handle, int64_t v)
+{
+ unsigned char buf[15]; /* ceil(64/7) = 10 + sign byte padded way up */
+ unsigned char byt;
+ unsigned char *pnt = buf;
+ int more = 1;
+ int len;
+
+ do {
+ byt = v | 0x80;
+ v >>= 7;
+
+ if (((!v) && (!(byt & 0x40))) || ((v == -1) && (byt & 0x40))) {
+ more = 0;
+ byt &= 0x7f;
+ }
+
+ *(pnt++) = byt;
+ } while (more);
+
+ len = pnt - buf;
+ fstFwrite(buf, len, 1, handle);
+ return (len);
+}
+#endif
+
+/***********************/
+/*** ***/
+/*** writer function ***/
+/*** ***/
+/***********************/
+
+/*
+ * private structs
+ */
+struct fstBlackoutChain
+{
+ struct fstBlackoutChain *next;
+ uint64_t tim;
+ unsigned active : 1;
+};
+
+struct fstWriterContext
+{
+ FILE *handle;
+ FILE *hier_handle;
+ FILE *geom_handle;
+ FILE *valpos_handle;
+ FILE *curval_handle;
+ FILE *tchn_handle;
+
+ unsigned char *vchg_mem;
+
+ fst_off_t hier_file_len;
+
+ uint32_t *valpos_mem;
+ unsigned char *curval_mem;
+
+ unsigned char *outval_mem; /* for two-state / Verilator-style value changes */
+ uint32_t outval_alloc_siz;
+
+ char *filename;
+
+ fstHandle maxhandle;
+ fstHandle numsigs;
+ uint32_t maxvalpos;
+
+ unsigned vc_emitted : 1;
+ unsigned is_initial_time : 1;
+ unsigned fourpack : 1;
+ unsigned fastpack : 1;
+
+ int64_t timezero;
+ fst_off_t section_header_truncpos;
+ uint32_t tchn_cnt, tchn_idx;
+ uint64_t curtime;
+ uint64_t firsttime;
+ uint32_t vchg_siz;
+ uint32_t vchg_alloc_siz;
+
+ uint32_t secnum;
+ fst_off_t section_start;
+
+ uint32_t numscopes;
+ double nan; /* nan value for uninitialized doubles */
+
+ struct fstBlackoutChain *blackout_head;
+ struct fstBlackoutChain *blackout_curr;
+ uint32_t num_blackouts;
+
+ uint64_t dump_size_limit;
+
+ unsigned char filetype; /* default is 0, FST_FT_VERILOG */
+
+ unsigned compress_hier : 1;
+ unsigned repack_on_close : 1;
+ unsigned skip_writing_section_hdr : 1;
+ unsigned size_limit_locked : 1;
+ unsigned section_header_only : 1;
+ unsigned flush_context_pending : 1;
+ unsigned parallel_enabled : 1;
+ unsigned parallel_was_enabled : 1;
+
+ /* should really be semaphores, but are bytes to cut down on read-modify-write window size */
+ unsigned char already_in_flush; /* in case control-c handlers interrupt */
+ unsigned char already_in_close; /* in case control-c handlers interrupt */
+
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_t mutex;
+ pthread_t thread;
+ pthread_attr_t thread_attr;
+ struct fstWriterContext *xc_parent;
+#endif
+ unsigned in_pthread : 1;
+
+ size_t fst_orig_break_size;
+ size_t fst_orig_break_add_size;
+
+ size_t fst_break_size;
+ size_t fst_break_add_size;
+
+ size_t fst_huge_break_size;
+
+ fstHandle next_huge_break;
+
+ Pvoid_t path_array;
+ uint32_t path_array_count;
+
+ unsigned fseek_failed : 1;
+
+ char *geom_handle_nam;
+ char *valpos_handle_nam;
+ char *curval_handle_nam;
+ char *tchn_handle_nam;
+
+ fstEnumHandle max_enumhandle;
+};
+
+static int fstWriterFseeko(struct fstWriterContext *xc, FILE *stream, fst_off_t offset, int whence)
+{
+ int rc = fseeko(stream, offset, whence);
+
+ if (rc < 0) {
+ xc->fseek_failed = 1;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence);
+ perror("Why");
+#endif
+ }
+
+ return (rc);
+}
+
+static uint32_t fstWriterUint32WithVarint32(struct fstWriterContext *xc, uint32_t *u, uint32_t v, const void *dbuf,
+ uint32_t siz)
+{
+ unsigned char *buf = xc->vchg_mem + xc->vchg_siz;
+ unsigned char *pnt = buf;
+ uint32_t nxt;
+ uint32_t len;
+
+#ifdef FST_DO_MISALIGNED_OPS
+ (*(uint32_t *)(pnt)) = (*(uint32_t *)(u));
+#else
+ memcpy(pnt, u, sizeof(uint32_t));
+#endif
+ pnt += 4;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+ memcpy(pnt, dbuf, siz);
+
+ len = pnt - buf + siz;
+ return (len);
+}
+
+static uint32_t fstWriterUint32WithVarint32AndLength(struct fstWriterContext *xc, uint32_t *u, uint32_t v,
+ const void *dbuf, uint32_t siz)
+{
+ unsigned char *buf = xc->vchg_mem + xc->vchg_siz;
+ unsigned char *pnt = buf;
+ uint32_t nxt;
+ uint32_t len;
+
+#ifdef FST_DO_MISALIGNED_OPS
+ (*(uint32_t *)(pnt)) = (*(uint32_t *)(u));
+#else
+ memcpy(pnt, u, sizeof(uint32_t));
+#endif
+ pnt += 4;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ v = siz;
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ memcpy(pnt, dbuf, siz);
+
+ len = pnt - buf + siz;
+ return (len);
+}
+
+/*
+ * header bytes, write here so defines are set up before anything else
+ * that needs to use them
+ */
+static void fstWriterEmitHdrBytes(struct fstWriterContext *xc)
+{
+ char vbuf[FST_HDR_SIM_VERSION_SIZE];
+ char dbuf[FST_HDR_DATE_SIZE];
+ double endtest = FST_DOUBLE_ENDTEST;
+ time_t walltime;
+
+#define FST_HDR_OFFS_TAG (0)
+ fputc(FST_BL_HDR, xc->handle); /* +0 tag */
+
+#define FST_HDR_OFFS_SECLEN (FST_HDR_OFFS_TAG + 1)
+ fstWriterUint64(xc->handle, 329); /* +1 section length */
+
+#define FST_HDR_OFFS_START_TIME (FST_HDR_OFFS_SECLEN + 8)
+ fstWriterUint64(xc->handle, 0); /* +9 start time */
+
+#define FST_HDR_OFFS_END_TIME (FST_HDR_OFFS_START_TIME + 8)
+ fstWriterUint64(xc->handle, 0); /* +17 end time */
+
+#define FST_HDR_OFFS_ENDIAN_TEST (FST_HDR_OFFS_END_TIME + 8)
+ fstFwrite(&endtest, 8, 1, xc->handle); /* +25 endian test for reals */
+
+#define FST_HDR_OFFS_MEM_USED (FST_HDR_OFFS_ENDIAN_TEST + 8)
+ fstWriterUint64(xc->handle, xc->fst_break_size); /* +33 memory used by writer */
+
+#define FST_HDR_OFFS_NUM_SCOPES (FST_HDR_OFFS_MEM_USED + 8)
+ fstWriterUint64(xc->handle, 0); /* +41 scope creation count */
+
+#define FST_HDR_OFFS_NUM_VARS (FST_HDR_OFFS_NUM_SCOPES + 8)
+ fstWriterUint64(xc->handle, 0); /* +49 var creation count */
+
+#define FST_HDR_OFFS_MAXHANDLE (FST_HDR_OFFS_NUM_VARS + 8)
+ fstWriterUint64(xc->handle, 0); /* +57 max var idcode */
+
+#define FST_HDR_OFFS_SECTION_CNT (FST_HDR_OFFS_MAXHANDLE + 8)
+ fstWriterUint64(xc->handle, 0); /* +65 vc section count */
+
+#define FST_HDR_OFFS_TIMESCALE (FST_HDR_OFFS_SECTION_CNT + 8)
+ fputc((-9) & 255, xc->handle); /* +73 timescale 1ns */
+
+#define FST_HDR_OFFS_SIM_VERSION (FST_HDR_OFFS_TIMESCALE + 1)
+ memset(vbuf, 0, FST_HDR_SIM_VERSION_SIZE);
+ strcpy(vbuf, FST_WRITER_STR);
+ fstFwrite(vbuf, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle); /* +74 version */
+
+#define FST_HDR_OFFS_DATE (FST_HDR_OFFS_SIM_VERSION + FST_HDR_SIM_VERSION_SIZE)
+ memset(dbuf, 0, FST_HDR_DATE_SIZE);
+ time(&walltime);
+ strcpy(dbuf, asctime(localtime(&walltime)));
+ fstFwrite(dbuf, FST_HDR_DATE_SIZE, 1, xc->handle); /* +202 date */
+
+ /* date size is deliberately overspecified at 119 bytes (originally 128) in order to provide backfill for new args
+ */
+
+#define FST_HDR_OFFS_FILETYPE (FST_HDR_OFFS_DATE + FST_HDR_DATE_SIZE)
+ fputc(xc->filetype, xc->handle); /* +321 filetype */
+
+#define FST_HDR_OFFS_TIMEZERO (FST_HDR_OFFS_FILETYPE + FST_HDR_FILETYPE_SIZE)
+ fstWriterUint64(xc->handle, xc->timezero); /* +322 timezero */
+
+#define FST_HDR_LENGTH (FST_HDR_OFFS_TIMEZERO + FST_HDR_TIMEZERO_SIZE)
+ /* +330 next section starts here */
+ fflush(xc->handle);
+}
+
+/*
+ * mmap functions
+ */
+static void fstWriterMmapSanity(void *pnt, const char *file, int line, const char *usage)
+{
+#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(_MSC_VER)
+ if (pnt == MAP_FAILED) {
+ fprintf(stderr, "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", usage, errno, file, line);
+ perror("Why");
+ pnt = NULL;
+ }
+#endif
+}
+
+static void fstWriterCreateMmaps(struct fstWriterContext *xc)
+{
+ fst_off_t curpos = ftello(xc->handle);
+
+ fflush(xc->hier_handle);
+
+ /* write out intermediate header */
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->firsttime);
+ fstWriterUint64(xc->handle, xc->curtime);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->numscopes);
+ fstWriterUint64(xc->handle, xc->numsigs);
+ fstWriterUint64(xc->handle, xc->maxhandle);
+ fstWriterUint64(xc->handle, xc->secnum);
+ fstWriterFseeko(xc, xc->handle, curpos, SEEK_SET);
+ fflush(xc->handle);
+
+ /* do mappings */
+ if (!xc->valpos_mem) {
+ fflush(xc->valpos_handle);
+ errno = 0;
+ if (xc->maxhandle) {
+ fstWriterMmapSanity(xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t),
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fileno(xc->valpos_handle), 0),
+ __FILE__, __LINE__, "xc->valpos_mem");
+ }
+ }
+ if (!xc->curval_mem) {
+ fflush(xc->curval_handle);
+ errno = 0;
+ if (xc->maxvalpos) {
+ fstWriterMmapSanity(xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fileno(xc->curval_handle), 0),
+ __FILE__, __LINE__, "xc->curval_handle");
+ }
+ }
+}
+
+static void fstDestroyMmaps(struct fstWriterContext *xc, int is_closing)
+{
+#if !defined __CYGWIN__ && !defined __MINGW32__
+ (void)is_closing;
+#endif
+
+ fstMunmap(xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t));
+ xc->valpos_mem = NULL;
+
+#if defined __CYGWIN__ || defined __MINGW32__
+ if (xc->curval_mem) {
+ if (!is_closing) /* need to flush out for next emulated mmap() read */
+ {
+ unsigned char *pnt = xc->curval_mem;
+ int __fd = fileno(xc->curval_handle);
+ fst_off_t cur_offs = lseek(__fd, 0, SEEK_CUR);
+ size_t i;
+ size_t __len = xc->maxvalpos;
+
+ lseek(__fd, 0, SEEK_SET);
+ for (i = 0; i < __len; i += SSIZE_MAX) {
+ write(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i));
+ }
+ lseek(__fd, cur_offs, SEEK_SET);
+ }
+ }
+#endif
+
+ fstMunmap(xc->curval_mem, xc->maxvalpos);
+ xc->curval_mem = NULL;
+}
+
+/*
+ * set up large and small memory usages
+ * crossover point in model is FST_ACTIVATE_HUGE_BREAK number of signals
+ */
+static void fstDetermineBreakSize(struct fstWriterContext *xc)
+{
+#if defined(__linux__) || defined(FST_MACOSX)
+ int was_set = 0;
+
+#ifdef __linux__
+ FILE *f = fopen("/proc/meminfo", "rb");
+
+ if (f) {
+ char buf[257];
+ char *s;
+ while (!feof(f)) {
+ buf[0] = 0;
+ s = fgets(buf, 256, f);
+ if (s && *s) {
+ if (!strncmp(s, "MemTotal:", 9)) {
+ size_t v = atol(s + 10);
+ v *= 1024; /* convert to bytes */
+ v /= 8; /* chop down to 1/8 physical memory */
+ if (v > FST_BREAK_SIZE) {
+ if (v > FST_BREAK_SIZE_MAX) {
+ v = FST_BREAK_SIZE_MAX;
+ }
+
+ xc->fst_huge_break_size = v;
+ was_set = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose(f);
+ }
+
+ if (!was_set) {
+ xc->fst_huge_break_size = FST_BREAK_SIZE;
+ }
+#else
+ int mib[2];
+ int64_t v;
+ size_t length;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ length = sizeof(int64_t);
+ if (!sysctl(mib, 2, &v, &length, NULL, 0)) {
+ v /= 8;
+
+ if (v > (int64_t)FST_BREAK_SIZE) {
+ if (v > (int64_t)FST_BREAK_SIZE_MAX) {
+ v = FST_BREAK_SIZE_MAX;
+ }
+
+ xc->fst_huge_break_size = v;
+ was_set = 1;
+ }
+ }
+
+ if (!was_set) {
+ xc->fst_huge_break_size = FST_BREAK_SIZE;
+ }
+#endif
+#else
+ xc->fst_huge_break_size = FST_BREAK_SIZE;
+#endif
+
+ xc->fst_break_size = xc->fst_orig_break_size = FST_BREAK_SIZE;
+ xc->fst_break_add_size = xc->fst_orig_break_add_size = FST_BREAK_ADD_SIZE;
+ xc->next_huge_break = FST_ACTIVATE_HUGE_BREAK;
+}
+
+/*
+ * file creation and close
+ */
+void *fstWriterCreate(const char *nam, int use_compressed_hier)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)calloc(1, sizeof(struct fstWriterContext));
+
+ xc->compress_hier = use_compressed_hier;
+ fstDetermineBreakSize(xc);
+
+ if ((!nam) || (!(xc->handle = unlink_fopen(nam, "w+b")))) {
+ free(xc);
+ xc = NULL;
+ } else {
+ int flen = strlen(nam);
+ char *hf = (char *)calloc(1, flen + 6);
+
+ memcpy(hf, nam, flen);
+ strcpy(hf + flen, ".hier");
+ xc->hier_handle = unlink_fopen(hf, "w+b");
+
+ xc->geom_handle = tmpfile_open(&xc->geom_handle_nam); /* .geom */
+ xc->valpos_handle = tmpfile_open(&xc->valpos_handle_nam); /* .offs */
+ xc->curval_handle = tmpfile_open(&xc->curval_handle_nam); /* .bits */
+ xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* .tchn */
+ xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size;
+ xc->vchg_mem = (unsigned char *)malloc(xc->vchg_alloc_siz);
+
+ if (xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem &&
+ xc->tchn_handle) {
+ xc->filename = strdup(nam);
+ xc->is_initial_time = 1;
+
+ fstWriterEmitHdrBytes(xc);
+ xc->nan = strtod("NaN", NULL);
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_init(&xc->mutex, NULL);
+ pthread_attr_init(&xc->thread_attr);
+ pthread_attr_setdetachstate(&xc->thread_attr, PTHREAD_CREATE_DETACHED);
+#endif
+ } else {
+ fclose(xc->handle);
+ if (xc->hier_handle) {
+ fclose(xc->hier_handle);
+ unlink(hf);
+ }
+ tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam);
+ tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam);
+ tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam);
+ tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
+ free(xc->vchg_mem);
+ free(xc);
+ xc = NULL;
+ }
+
+ free(hf);
+ }
+
+ return (xc);
+}
+
+/*
+ * generation and writing out of value change data sections
+ */
+static void fstWriterEmitSectionHeader(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ unsigned long destlen;
+ unsigned char *dmem;
+ int rc;
+
+ destlen = xc->maxvalpos;
+ dmem = (unsigned char *)malloc(compressBound(destlen));
+ rc = compress2(dmem, &destlen, xc->curval_mem, xc->maxvalpos,
+ 4); /* was 9...which caused performance drag on traces with many signals */
+
+ fputc(FST_BL_SKIP, xc->handle); /* temporarily tag the section, use FST_BL_VCDATA on finalize */
+ xc->section_start = ftello(xc->handle);
+#ifdef FST_WRITER_PARALLEL
+ if (xc->xc_parent)
+ xc->xc_parent->section_start = xc->section_start;
+#endif
+ xc->section_header_only = 1; /* indicates truncate might be needed */
+ fstWriterUint64(xc->handle, 0); /* placeholder = section length */
+ fstWriterUint64(xc->handle, xc->is_initial_time ? xc->firsttime : xc->curtime); /* begin time of section */
+ fstWriterUint64(xc->handle, xc->curtime); /* end time of section (placeholder) */
+ fstWriterUint64(xc->handle,
+ 0); /* placeholder = amount of buffer memory required in reader for full vc traversal */
+ fstWriterVarint(xc->handle, xc->maxvalpos); /* maxvalpos = length of uncompressed data */
+
+ if ((rc == Z_OK) && (destlen < xc->maxvalpos)) {
+ fstWriterVarint(xc->handle, destlen); /* length of compressed data */
+ } else {
+ fstWriterVarint(xc->handle, xc->maxvalpos); /* length of (unable to be) compressed data */
+ }
+ fstWriterVarint(xc->handle,
+ xc->maxhandle); /* max handle associated with this data (in case of dynamic facility adds) */
+
+ if ((rc == Z_OK) && (destlen < xc->maxvalpos)) {
+ fstFwrite(dmem, destlen, 1, xc->handle);
+ } else /* comparison between compressed / decompressed len tells if compressed */
+ {
+ fstFwrite(xc->curval_mem, xc->maxvalpos, 1, xc->handle);
+ }
+
+ free(dmem);
+ }
+}
+
+/*
+ * only to be called directly by fst code...otherwise must
+ * be synced up with time changes
+ */
+#ifdef FST_WRITER_PARALLEL
+static void fstWriterFlushContextPrivate2(void *ctx)
+#else
+static void fstWriterFlushContextPrivate(void *ctx)
+#endif
+{
+#ifdef FST_DEBUG
+ int cnt = 0;
+#endif
+ unsigned int i;
+ unsigned char *vchg_mem;
+ FILE *f;
+ fst_off_t fpos, indxpos, endpos;
+ uint32_t prevpos;
+ int zerocnt;
+ unsigned char *scratchpad;
+ unsigned char *scratchpnt;
+ unsigned char *tmem;
+ fst_off_t tlen;
+ fst_off_t unc_memreq = 0; /* for reader */
+ unsigned char *packmem;
+ unsigned int packmemlen;
+ uint32_t *vm4ip;
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+#ifdef FST_WRITER_PARALLEL
+ struct fstWriterContext *xc2 = xc->xc_parent;
+#else
+ struct fstWriterContext *xc2 = xc;
+#endif
+
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ Pvoid_t PJHSArray = (Pvoid_t)NULL;
+#ifndef _WAVE_HAVE_JUDY
+ uint32_t hashmask = xc->maxhandle;
+ hashmask |= hashmask >> 1;
+ hashmask |= hashmask >> 2;
+ hashmask |= hashmask >> 4;
+ hashmask |= hashmask >> 8;
+ hashmask |= hashmask >> 16;
+#endif
+#endif
+
+ if ((xc->vchg_siz <= 1) || (xc->already_in_flush))
+ return;
+ xc->already_in_flush = 1; /* should really do this with a semaphore */
+
+ xc->section_header_only = 0;
+ scratchpad = (unsigned char *)malloc(xc->vchg_siz);
+
+ vchg_mem = xc->vchg_mem;
+
+ f = xc->handle;
+ fstWriterVarint(f, xc->maxhandle); /* emit current number of handles */
+ fputc(xc->fourpack ? '4' : (xc->fastpack ? 'F' : 'Z'), f);
+ fpos = 1;
+
+ packmemlen = 1024; /* maintain a running "longest" allocation to */
+ packmem = (unsigned char *)malloc(packmemlen); /* prevent continual malloc...free every loop iter */
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ vm4ip = &(xc->valpos_mem[4 * i]);
+
+ if (vm4ip[2]) {
+ uint32_t offs = vm4ip[2];
+ uint32_t next_offs;
+ unsigned int wrlen;
+
+ vm4ip[2] = fpos;
+
+ scratchpnt = scratchpad + xc->vchg_siz; /* build this buffer backwards */
+ if (vm4ip[1] <= 1) {
+ if (vm4ip[1] == 1) {
+ wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */
+#ifndef FST_REMOVE_DUPLICATE_VC
+ xc->curval_mem[vm4ip[0]] = vchg_mem[offs + 4 + wrlen]; /* checkpoint variable */
+#endif
+ while (offs) {
+ unsigned char val;
+ uint32_t time_delta, rcv;
+ next_offs = fstGetUint32(vchg_mem + offs);
+ offs += 4;
+
+ time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen);
+ val = vchg_mem[offs + wrlen];
+ offs = next_offs;
+
+ switch (val) {
+ case '0':
+ case '1':
+ rcv = ((val & 1) << 1) | (time_delta << 2);
+ break; /* pack more delta bits in for 0/1 vchs */
+
+ case 'x':
+ case 'X':
+ rcv = FST_RCV_X | (time_delta << 4);
+ break;
+ case 'z':
+ case 'Z':
+ rcv = FST_RCV_Z | (time_delta << 4);
+ break;
+ case 'h':
+ case 'H':
+ rcv = FST_RCV_H | (time_delta << 4);
+ break;
+ case 'u':
+ case 'U':
+ rcv = FST_RCV_U | (time_delta << 4);
+ break;
+ case 'w':
+ case 'W':
+ rcv = FST_RCV_W | (time_delta << 4);
+ break;
+ case 'l':
+ case 'L':
+ rcv = FST_RCV_L | (time_delta << 4);
+ break;
+ default:
+ rcv = FST_RCV_D | (time_delta << 4);
+ break;
+ }
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, rcv);
+ }
+ } else {
+ /* variable length */
+ /* fstGetUint32 (next_offs) + fstGetVarint32 (time_delta) + fstGetVarint32 (len) + payload */
+ unsigned char *pnt;
+ uint32_t record_len;
+ uint32_t time_delta;
+
+ while (offs) {
+ next_offs = fstGetUint32(vchg_mem + offs);
+ offs += 4;
+ pnt = vchg_mem + offs;
+ offs = next_offs;
+ time_delta = fstGetVarint32(pnt, (int *)&wrlen);
+ pnt += wrlen;
+ record_len = fstGetVarint32(pnt, (int *)&wrlen);
+ pnt += wrlen;
+
+ scratchpnt -= record_len;
+ memcpy(scratchpnt, pnt, record_len);
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, record_len);
+ scratchpnt = fstCopyVarint32ToLeft(
+ scratchpnt, (time_delta << 1)); /* reserve | 1 case for future expansion */
+ }
+ }
+ } else {
+ wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */
+#ifndef FST_REMOVE_DUPLICATE_VC
+ memcpy(xc->curval_mem + vm4ip[0], vchg_mem + offs + 4 + wrlen, vm4ip[1]); /* checkpoint variable */
+#endif
+ while (offs) {
+ unsigned int idx;
+ char is_binary = 1;
+ unsigned char *pnt;
+ uint32_t time_delta;
+
+ next_offs = fstGetUint32(vchg_mem + offs);
+ offs += 4;
+
+ time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen);
+
+ pnt = vchg_mem + offs + wrlen;
+ offs = next_offs;
+
+ for (idx = 0; idx < vm4ip[1]; idx++) {
+ if ((pnt[idx] == '0') || (pnt[idx] == '1')) {
+ continue;
+ } else {
+ is_binary = 0;
+ break;
+ }
+ }
+
+ if (is_binary) {
+ unsigned char acc = 0;
+ /* new algorithm */
+ idx = ((vm4ip[1] + 7) & ~7);
+ switch (vm4ip[1] & 7) {
+ case 0:
+ do {
+ acc = (pnt[idx + 7 - 8] & 1) << 0; /* fallthrough */
+ case 7:
+ acc |= (pnt[idx + 6 - 8] & 1) << 1; /* fallthrough */
+ case 6:
+ acc |= (pnt[idx + 5 - 8] & 1) << 2; /* fallthrough */
+ case 5:
+ acc |= (pnt[idx + 4 - 8] & 1) << 3; /* fallthrough */
+ case 4:
+ acc |= (pnt[idx + 3 - 8] & 1) << 4; /* fallthrough */
+ case 3:
+ acc |= (pnt[idx + 2 - 8] & 1) << 5; /* fallthrough */
+ case 2:
+ acc |= (pnt[idx + 1 - 8] & 1) << 6; /* fallthrough */
+ case 1:
+ acc |= (pnt[idx + 0 - 8] & 1) << 7;
+ *(--scratchpnt) = acc;
+ idx -= 8;
+ } while (idx);
+ }
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1));
+ } else {
+ scratchpnt -= vm4ip[1];
+ memcpy(scratchpnt, pnt, vm4ip[1]);
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1) | 1);
+ }
+ }
+ }
+
+ wrlen = scratchpad + xc->vchg_siz - scratchpnt;
+ unc_memreq += wrlen;
+ if (wrlen > 32) {
+ unsigned long destlen = wrlen;
+ unsigned char *dmem;
+ unsigned int rc;
+
+ if (!xc->fastpack) {
+ if (wrlen <= packmemlen) {
+ dmem = packmem;
+ } else {
+ free(packmem);
+ dmem = packmem = (unsigned char *)malloc(compressBound(packmemlen = wrlen));
+ }
+
+ rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4);
+ if (rc == Z_OK) {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, destlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, wrlen);
+ fpos += destlen;
+ fstFwrite(dmem, destlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ } else {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, 0);
+ fpos += wrlen;
+ fstFwrite(scratchpnt, wrlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ }
+ } else {
+ /* this is extremely conservative: fastlz needs +5% for worst case, lz4 needs siz+(siz/255)+16 */
+ if (((wrlen * 2) + 2) <= packmemlen) {
+ dmem = packmem;
+ } else {
+ free(packmem);
+ dmem = packmem = (unsigned char *)malloc(packmemlen = (wrlen * 2) + 2);
+ }
+
+ rc = (xc->fourpack) ? LZ4_compress((char *)scratchpnt, (char *)dmem, wrlen)
+ : fastlz_compress(scratchpnt, wrlen, dmem);
+ if (rc < destlen) {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, rc, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, wrlen);
+ fpos += rc;
+ fstFwrite(dmem, rc, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ } else {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, 0);
+ fpos += wrlen;
+ fstFwrite(scratchpnt, wrlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ }
+ }
+ } else {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, 0);
+ fpos += wrlen;
+ fstFwrite(scratchpnt, wrlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ }
+
+ /* vm4ip[3] = 0; ...redundant with clearing below */
+#ifdef FST_DEBUG
+ cnt++;
+#endif
+ }
+ }
+
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ JudyHSFreeArray(&PJHSArray, NULL);
+#endif
+
+ free(packmem);
+ packmem = NULL; /* packmemlen = 0; */ /* scan-build */
+
+ prevpos = 0;
+ zerocnt = 0;
+ free(scratchpad);
+ scratchpad = NULL;
+
+ indxpos = ftello(f);
+ xc->secnum++;
+
+#ifndef FST_DYNAMIC_ALIAS2_DISABLE
+ if (1) {
+ uint32_t prev_alias = 0;
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ vm4ip = &(xc->valpos_mem[4 * i]);
+
+ if (vm4ip[2]) {
+ if (zerocnt) {
+ fpos += fstWriterVarint(f, (zerocnt << 1));
+ zerocnt = 0;
+ }
+
+ if (vm4ip[2] & 0x80000000) {
+ if (vm4ip[2] != prev_alias) {
+ fpos += fstWriterSVarint(f, (((int64_t)((int32_t)(prev_alias = vm4ip[2]))) << 1) | 1);
+ } else {
+ fpos += fstWriterSVarint(f, (0 << 1) | 1);
+ }
+ } else {
+ fpos += fstWriterSVarint(f, ((vm4ip[2] - prevpos) << 1) | 1);
+ prevpos = vm4ip[2];
+ }
+ vm4ip[2] = 0;
+ vm4ip[3] = 0; /* clear out tchn idx */
+ } else {
+ zerocnt++;
+ }
+ }
+ } else
+#endif
+ {
+ for (i = 0; i < xc->maxhandle; i++) {
+ vm4ip = &(xc->valpos_mem[4 * i]);
+
+ if (vm4ip[2]) {
+ if (zerocnt) {
+ fpos += fstWriterVarint(f, (zerocnt << 1));
+ zerocnt = 0;
+ }
+
+ if (vm4ip[2] & 0x80000000) {
+ fpos += fstWriterVarint(f, 0); /* signal, note that using a *signed* varint would be more efficient
+ than this byte escape! */
+ fpos += fstWriterVarint(f, (-(int32_t)vm4ip[2]));
+ } else {
+ fpos += fstWriterVarint(f, ((vm4ip[2] - prevpos) << 1) | 1);
+ prevpos = vm4ip[2];
+ }
+ vm4ip[2] = 0;
+ vm4ip[3] = 0; /* clear out tchn idx */
+ } else {
+ zerocnt++;
+ }
+ }
+ }
+
+ if (zerocnt) {
+ /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
+ }
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "value chains: %d\n", cnt);
+#endif
+
+ xc->vchg_mem[0] = '!';
+ xc->vchg_siz = 1;
+
+ endpos = ftello(xc->handle);
+ fstWriterUint64(xc->handle, endpos - indxpos); /* write delta index position at very end of block */
+
+ /*emit time changes for block */
+ fflush(xc->tchn_handle);
+ tlen = ftello(xc->tchn_handle);
+ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
+
+ errno = 0;
+ fstWriterMmapSanity(
+ tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0),
+ __FILE__, __LINE__, "tmem");
+ if (tmem) {
+ unsigned long destlen = tlen;
+ unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen));
+ int rc = compress2(dmem, &destlen, tmem, tlen, 9);
+
+ if ((rc == Z_OK) && (((fst_off_t)destlen) < tlen)) {
+ fstFwrite(dmem, destlen, 1, xc->handle);
+ } else /* comparison between compressed / decompressed len tells if compressed */
+ {
+ fstFwrite(tmem, tlen, 1, xc->handle);
+ destlen = tlen;
+ }
+ free(dmem);
+ fstMunmap(tmem, tlen);
+ fstWriterUint64(xc->handle, tlen); /* uncompressed */
+ fstWriterUint64(xc->handle, destlen); /* compressed */
+ fstWriterUint64(xc->handle, xc->tchn_cnt); /* number of time items */
+ }
+
+ xc->tchn_cnt = xc->tchn_idx = 0;
+ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
+ fstFtruncate(fileno(xc->tchn_handle), 0);
+
+ /* write block trailer */
+ endpos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, xc->section_start, SEEK_SET);
+ fstWriterUint64(xc->handle, endpos - xc->section_start); /* write block length */
+ fstWriterFseeko(xc, xc->handle, 8, SEEK_CUR); /* skip begin time */
+ fstWriterUint64(xc->handle, xc->curtime); /* write end time for section */
+ fstWriterUint64(xc->handle, unc_memreq); /* amount of buffer memory required in reader for full traversal */
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, xc->section_start - 1, SEEK_SET); /* write out FST_BL_VCDATA over FST_BL_SKIP */
+
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+#ifndef FST_DYNAMIC_ALIAS2_DISABLE
+ fputc(FST_BL_VCDATA_DYN_ALIAS2, xc->handle);
+#else
+ fputc(FST_BL_VCDATA_DYN_ALIAS, xc->handle);
+#endif
+#else
+ fputc(FST_BL_VCDATA, xc->handle);
+#endif
+
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, endpos, SEEK_SET); /* seek to end of file */
+
+ xc2->section_header_truncpos = endpos; /* cache in case of need to truncate */
+ if (xc->dump_size_limit) {
+ if (endpos >= ((fst_off_t)xc->dump_size_limit)) {
+ xc2->skip_writing_section_hdr = 1;
+ xc2->size_limit_locked = 1;
+ xc2->is_initial_time = 1; /* to trick emit value and emit time change */
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "<< dump file size limit reached, stopping dumping >>\n");
+#endif
+ }
+ }
+
+ if (!xc2->skip_writing_section_hdr) {
+ fstWriterEmitSectionHeader(xc); /* emit next section header */
+ }
+ fflush(xc->handle);
+
+ xc->already_in_flush = 0;
+}
+
+#ifdef FST_WRITER_PARALLEL
+static void *fstWriterFlushContextPrivate1(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ struct fstWriterContext *xc_parent;
+
+ pthread_mutex_lock(&(xc->xc_parent->mutex));
+ fstWriterFlushContextPrivate2(xc);
+
+#ifdef FST_REMOVE_DUPLICATE_VC
+ free(xc->curval_mem);
+#endif
+ free(xc->valpos_mem);
+ free(xc->vchg_mem);
+ tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
+ xc_parent = xc->xc_parent;
+ free(xc);
+
+ xc_parent->in_pthread = 0;
+ pthread_mutex_unlock(&(xc_parent->mutex));
+
+ return (NULL);
+}
+
+static void fstWriterFlushContextPrivate(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc->parallel_enabled) {
+ struct fstWriterContext *xc2 = (struct fstWriterContext *)malloc(sizeof(struct fstWriterContext));
+ unsigned int i;
+
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+
+ xc->xc_parent = xc;
+ memcpy(xc2, xc, sizeof(struct fstWriterContext));
+
+ xc2->valpos_mem = (uint32_t *)malloc(xc->maxhandle * 4 * sizeof(uint32_t));
+ memcpy(xc2->valpos_mem, xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t));
+
+ /* curval mem is updated in the thread */
+#ifdef FST_REMOVE_DUPLICATE_VC
+ xc2->curval_mem = (unsigned char *)malloc(xc->maxvalpos);
+ memcpy(xc2->curval_mem, xc->curval_mem, xc->maxvalpos);
+#endif
+
+ xc->vchg_mem = (unsigned char *)malloc(xc->vchg_alloc_siz);
+ xc->vchg_mem[0] = '!';
+ xc->vchg_siz = 1;
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ uint32_t *vm4ip = &(xc->valpos_mem[4 * i]);
+ vm4ip[2] = 0; /* zero out offset val */
+ vm4ip[3] = 0; /* zero out last time change val */
+ }
+
+ xc->tchn_cnt = xc->tchn_idx = 0;
+ xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* child thread will deallocate file/name */
+ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
+ fstFtruncate(fileno(xc->tchn_handle), 0);
+
+ xc->section_header_only = 0;
+ xc->secnum++;
+
+ while (xc->in_pthread) {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ };
+
+ pthread_mutex_lock(&xc->mutex);
+ xc->in_pthread = 1;
+ pthread_mutex_unlock(&xc->mutex);
+
+ pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2);
+ } else {
+ if (xc->parallel_was_enabled) /* conservatively block */
+ {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ }
+
+ xc->xc_parent = xc;
+ fstWriterFlushContextPrivate2(xc);
+ }
+}
+#endif
+
+/*
+ * queues up a flush context operation
+ */
+void fstWriterFlushContext(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ if (xc->tchn_idx > 1) {
+ xc->flush_context_pending = 1;
+ }
+ }
+}
+
+/*
+ * close out FST file
+ */
+void fstWriterClose(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+#ifdef FST_WRITER_PARALLEL
+ if (xc) {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ }
+#endif
+
+ if (xc && !xc->already_in_close && !xc->already_in_flush) {
+ unsigned char *tmem = NULL;
+ fst_off_t fixup_offs, tlen, hlen;
+
+ xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
+
+ if (xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time)) {
+ fstFtruncate(fileno(xc->handle), xc->section_header_truncpos);
+ fstWriterFseeko(xc, xc->handle, xc->section_header_truncpos, SEEK_SET);
+ xc->section_header_only = 0;
+ } else {
+ xc->skip_writing_section_hdr = 1;
+ if (!xc->size_limit_locked) {
+ if (FST_UNLIKELY(xc->is_initial_time)) /* simulation time never advanced so mock up the changes as time
+ zero ones */
+ {
+ fstHandle dupe_idx;
+
+ fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */
+ for (dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */
+ {
+ fstWriterEmitValueChange(xc, dupe_idx + 1, xc->curval_mem + xc->valpos_mem[4 * dupe_idx]);
+ }
+ }
+ fstWriterFlushContextPrivate(xc);
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+
+ while (xc->in_pthread) {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ };
+#endif
+ }
+ }
+ fstDestroyMmaps(xc, 1);
+ if (xc->outval_mem) {
+ free(xc->outval_mem);
+ xc->outval_mem = NULL;
+ xc->outval_alloc_siz = 0;
+ }
+
+ /* write out geom section */
+ fflush(xc->geom_handle);
+ tlen = ftello(xc->geom_handle);
+ errno = 0;
+ if (tlen) {
+ fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fileno(xc->geom_handle), 0),
+ __FILE__, __LINE__, "tmem");
+ }
+
+ if (tmem) {
+ unsigned long destlen = tlen;
+ unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen));
+ int rc = compress2(dmem, &destlen, tmem, tlen, 9);
+
+ if ((rc != Z_OK) || (((fst_off_t)destlen) > tlen)) {
+ destlen = tlen;
+ }
+
+ fixup_offs = ftello(xc->handle);
+ fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
+ fstWriterUint64(xc->handle, destlen + 24); /* section length */
+ fstWriterUint64(xc->handle, tlen); /* uncompressed */
+ /* compressed len is section length - 24 */
+ fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */
+ fstFwrite((((fst_off_t)destlen) != tlen) ? dmem : tmem, destlen, 1, xc->handle);
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET);
+ fputc(FST_BL_GEOM, xc->handle); /* actual tag */
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
+ fflush(xc->handle);
+
+ free(dmem);
+ fstMunmap(tmem, tlen);
+ }
+
+ if (xc->num_blackouts) {
+ uint64_t cur_bl = 0;
+ fst_off_t bpos, eos;
+ uint32_t i;
+
+ fixup_offs = ftello(xc->handle);
+ fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
+ bpos = fixup_offs + 1;
+ fstWriterUint64(xc->handle, 0); /* section length */
+ fstWriterVarint(xc->handle, xc->num_blackouts);
+
+ for (i = 0; i < xc->num_blackouts; i++) {
+ fputc(xc->blackout_head->active, xc->handle);
+ fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl);
+ cur_bl = xc->blackout_head->tim;
+ xc->blackout_curr = xc->blackout_head->next;
+ free(xc->blackout_head);
+ xc->blackout_head = xc->blackout_curr;
+ }
+
+ eos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, bpos, SEEK_SET);
+ fstWriterUint64(xc->handle, eos - bpos);
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET);
+ fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
+ fflush(xc->handle);
+ }
+
+ if (xc->compress_hier) {
+ fst_off_t hl, eos;
+ gzFile zhandle;
+ int zfd;
+ int fourpack_duo = 0;
+#ifndef __MINGW32__
+ char *fnam = (char *)malloc(strlen(xc->filename) + 5 + 1);
+#endif
+
+ fixup_offs = ftello(xc->handle);
+ fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
+ hlen = ftello(xc->handle);
+ fstWriterUint64(xc->handle, 0); /* section length */
+ fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */
+
+ if (!xc->fourpack) {
+ unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN);
+ zfd = dup(fileno(xc->handle));
+ fflush(xc->handle);
+ zhandle = gzdopen(zfd, "wb4");
+ if (zhandle) {
+ fstWriterFseeko(xc, xc->hier_handle, 0, SEEK_SET);
+ for (hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN) {
+ unsigned len =
+ ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl);
+ fstFread(mem, len, 1, xc->hier_handle);
+ gzwrite(zhandle, mem, len);
+ }
+ gzclose(zhandle);
+ } else {
+ close(zfd);
+ }
+ free(mem);
+ } else {
+ int lz4_maxlen;
+ unsigned char *mem;
+ unsigned char *hmem = NULL;
+ int packed_len;
+
+ fflush(xc->handle);
+
+ lz4_maxlen = LZ4_compressBound(xc->hier_file_len);
+ mem = (unsigned char *)malloc(lz4_maxlen);
+ errno = 0;
+ if (xc->hier_file_len) {
+ fstWriterMmapSanity(hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fileno(xc->hier_handle), 0),
+ __FILE__, __LINE__, "hmem");
+ }
+ packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len);
+ fstMunmap(hmem, xc->hier_file_len);
+
+ fourpack_duo =
+ (!xc->repack_on_close) &&
+ (xc->hier_file_len > FST_HDR_FOURPACK_DUO_SIZE); /* double pack when hierarchy is large */
+
+ if (fourpack_duo) /* double packing with LZ4 is faster than gzip */
+ {
+ unsigned char *mem_duo;
+ int lz4_maxlen_duo;
+ int packed_len_duo;
+
+ lz4_maxlen_duo = LZ4_compressBound(packed_len);
+ mem_duo = (unsigned char *)malloc(lz4_maxlen_duo);
+ packed_len_duo = LZ4_compress((char *)mem, (char *)mem_duo, packed_len);
+
+ fstWriterVarint(xc->handle, packed_len); /* 1st round compressed length */
+ fstFwrite(mem_duo, packed_len_duo, 1, xc->handle);
+ free(mem_duo);
+ } else {
+ fstFwrite(mem, packed_len, 1, xc->handle);
+ }
+
+ free(mem);
+ }
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END);
+ eos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, hlen, SEEK_SET);
+ fstWriterUint64(xc->handle, eos - hlen);
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET);
+ fputc(xc->fourpack ? (fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : FST_BL_HIER,
+ xc->handle); /* actual tag now also == compression type */
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
+ fflush(xc->handle);
+
+#ifndef __MINGW32__
+ sprintf(fnam, "%s.hier", xc->filename);
+ unlink(fnam);
+ free(fnam);
+#endif
+ }
+
+ /* finalize out header */
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->firsttime);
+ fstWriterUint64(xc->handle, xc->curtime);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->numscopes);
+ fstWriterUint64(xc->handle, xc->numsigs);
+ fstWriterUint64(xc->handle, xc->maxhandle);
+ fstWriterUint64(xc->handle, xc->secnum);
+ fflush(xc->handle);
+
+ tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
+ free(xc->vchg_mem);
+ xc->vchg_mem = NULL;
+ tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam);
+ tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam);
+ tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam);
+ if (xc->hier_handle) {
+ fclose(xc->hier_handle);
+ xc->hier_handle = NULL;
+ }
+ if (xc->handle) {
+ if (xc->repack_on_close) {
+ FILE *fp;
+ fst_off_t offpnt, uclen;
+ int flen = strlen(xc->filename);
+ char *hf = (char *)calloc(1, flen + 5);
+
+ strcpy(hf, xc->filename);
+ strcpy(hf + flen, ".pak");
+ fp = fopen(hf, "wb");
+
+ if (fp) {
+ gzFile dsth;
+ int zfd;
+ char gz_membuf[FST_GZIO_LEN];
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END);
+ uclen = ftello(xc->handle);
+
+ fputc(FST_BL_ZWRAPPER, fp);
+ fstWriterUint64(fp, 0);
+ fstWriterUint64(fp, uclen);
+ fflush(fp);
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_SET);
+ zfd = dup(fileno(fp));
+ dsth = gzdopen(zfd, "wb4");
+ if (dsth) {
+ for (offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) {
+ size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
+ fstFread(gz_membuf, this_len, 1, xc->handle);
+ gzwrite(dsth, gz_membuf, this_len);
+ }
+ gzclose(dsth);
+ } else {
+ close(zfd);
+ }
+ fstWriterFseeko(xc, fp, 0, SEEK_END);
+ offpnt = ftello(fp);
+ fstWriterFseeko(xc, fp, 1, SEEK_SET);
+ fstWriterUint64(fp, offpnt - 1);
+ fclose(fp);
+ fclose(xc->handle);
+ xc->handle = NULL;
+
+ unlink(xc->filename);
+ rename(hf, xc->filename);
+ } else {
+ xc->repack_on_close = 0;
+ fclose(xc->handle);
+ xc->handle = NULL;
+ }
+
+ free(hf);
+ } else {
+ fclose(xc->handle);
+ xc->handle = NULL;
+ }
+ }
+
+#ifdef __MINGW32__
+ {
+ int flen = strlen(xc->filename);
+ char *hf = (char *)calloc(1, flen + 6);
+ strcpy(hf, xc->filename);
+
+ if (xc->compress_hier) {
+ strcpy(hf + flen, ".hier");
+ unlink(hf); /* no longer needed as a section now exists for this */
+ }
+
+ free(hf);
+ }
+#endif
+
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_destroy(&xc->mutex);
+ pthread_attr_destroy(&xc->thread_attr);
+#endif
+
+ if (xc->path_array) {
+#ifndef _WAVE_HAVE_JUDY
+ const uint32_t hashmask = FST_PATH_HASHMASK;
+#endif
+ JudyHSFreeArray(&(xc->path_array), NULL);
+ }
+
+ free(xc->filename);
+ xc->filename = NULL;
+ free(xc);
+ }
+}
+
+/*
+ * functions to set miscellaneous header/block information
+ */
+void fstWriterSetDate(void *ctx, const char *dat)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ char s[FST_HDR_DATE_SIZE];
+ fst_off_t fpos = ftello(xc->handle);
+ int len = strlen(dat);
+
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_DATE, SEEK_SET);
+ memset(s, 0, FST_HDR_DATE_SIZE);
+ memcpy(s, dat, (len < FST_HDR_DATE_SIZE) ? len : FST_HDR_DATE_SIZE);
+ fstFwrite(s, FST_HDR_DATE_SIZE, 1, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetVersion(void *ctx, const char *vers)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && vers) {
+ char s[FST_HDR_SIM_VERSION_SIZE];
+ fst_off_t fpos = ftello(xc->handle);
+ int len = strlen(vers);
+
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_SIM_VERSION, SEEK_SET);
+ memset(s, 0, FST_HDR_SIM_VERSION_SIZE);
+ memcpy(s, vers, (len < FST_HDR_SIM_VERSION_SIZE) ? len : FST_HDR_SIM_VERSION_SIZE);
+ fstFwrite(s, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetFileType(void *ctx, enum fstFileType filetype)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ if (/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) {
+ fst_off_t fpos = ftello(xc->handle);
+
+ xc->filetype = filetype;
+
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_FILETYPE, SEEK_SET);
+ fputc(xc->filetype, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+ }
+}
+
+static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1, uint64_t arg2)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ unsigned char buf[11]; /* ceil(64/7) = 10 + null term */
+ unsigned char *pnt = fstCopyVarint64ToRight(buf, arg1);
+ if (arg1) {
+ *pnt = 0; /* this converts any *nonzero* arg1 when made a varint into a null-term string */
+ }
+
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, (char *)buf, arg2);
+ }
+}
+
+static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64_t arg)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && comm) {
+ char *s = strdup(comm);
+ char *sf = s;
+
+ while (*s) {
+ if ((*s == '\n') || (*s == '\r'))
+ *s = ' ';
+ s++;
+ }
+
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, sf, arg);
+ free(sf);
+ }
+}
+
+static void fstWriterSetSourceStem_2(void *ctx, const char *path, unsigned int line, unsigned int use_realpath, int typ)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc && path && path[0]) {
+ uint64_t sidx = 0;
+ int slen = strlen(path);
+#ifndef _WAVE_HAVE_JUDY
+ const uint32_t hashmask = FST_PATH_HASHMASK;
+ const unsigned char *path2 = (const unsigned char *)path;
+ PPvoid_t pv;
+#else
+ char *path2 = (char *)alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */
+ PPvoid_t pv;
+ strcpy(path2, path);
+#endif
+
+ pv = JudyHSIns(&(xc->path_array), path2, slen, NULL);
+ if (*pv) {
+ sidx = (intptr_t)(*pv);
+ } else {
+ char *rp = NULL;
+
+ sidx = ++xc->path_array_count;
+ *pv = (void *)(intptr_t)(xc->path_array_count);
+
+ if (use_realpath) {
+ rp = fstRealpath(
+#ifndef _WAVE_HAVE_JUDY
+ (const char *)
+#endif
+ path2,
+ NULL);
+ }
+
+ fstWriterSetAttrGeneric(xc,
+ rp ? rp :
+#ifndef _WAVE_HAVE_JUDY
+ (const char *)
+#endif
+ path2,
+ FST_MT_PATHNAME, sidx);
+
+ if (rp) {
+ free(rp);
+ }
+ }
+
+ fstWriterSetAttrDoubleArgGeneric(xc, typ, sidx, line);
+ }
+}
+
+void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath)
+{
+ fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCESTEM);
+}
+
+void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath)
+{
+ fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCEISTEM);
+}
+
+void fstWriterSetComment(void *ctx, const char *comm) { fstWriterSetAttrGeneric(ctx, comm, FST_MT_COMMENT, 0); }
+
+void fstWriterSetValueList(void *ctx, const char *vl) { fstWriterSetAttrGeneric(ctx, vl, FST_MT_VALUELIST, 0); }
+
+void fstWriterSetEnvVar(void *ctx, const char *envvar) { fstWriterSetAttrGeneric(ctx, envvar, FST_MT_ENVVAR, 0); }
+
+void fstWriterSetTimescale(void *ctx, int ts)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ fst_off_t fpos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET);
+ fputc(ts & 255, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetTimescaleFromString(void *ctx, const char *s)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && s) {
+ int mat = 0;
+ int seconds_exp = -9;
+ int tv = atoi(s);
+ const char *pnt = s;
+
+ while (*pnt) {
+ switch (*pnt) {
+ case 'm':
+ seconds_exp = -3;
+ mat = 1;
+ break;
+ case 'u':
+ seconds_exp = -6;
+ mat = 1;
+ break;
+ case 'n':
+ seconds_exp = -9;
+ mat = 1;
+ break;
+ case 'p':
+ seconds_exp = -12;
+ mat = 1;
+ break;
+ case 'f':
+ seconds_exp = -15;
+ mat = 1;
+ break;
+ case 'a':
+ seconds_exp = -18;
+ mat = 1;
+ break;
+ case 'z':
+ seconds_exp = -21;
+ mat = 1;
+ break;
+ case 's':
+ seconds_exp = 0;
+ mat = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (mat)
+ break;
+ pnt++;
+ }
+
+ if (tv == 10) {
+ seconds_exp++;
+ } else if (tv == 100) {
+ seconds_exp += 2;
+ }
+
+ fstWriterSetTimescale(ctx, seconds_exp);
+ }
+}
+
+void fstWriterSetTimezero(void *ctx, int64_t tim)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ fst_off_t fpos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET);
+ fstWriterUint64(xc->handle, (xc->timezero = tim));
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->fastpack = (typ != FST_WR_PT_ZLIB);
+ xc->fourpack = (typ == FST_WR_PT_LZ4);
+ }
+}
+
+void fstWriterSetRepackOnClose(void *ctx, int enable)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->repack_on_close = (enable != 0);
+ }
+}
+
+void fstWriterSetParallelMode(void *ctx, int enable)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */
+ xc->parallel_enabled = (enable != 0);
+#ifndef FST_WRITER_PARALLEL
+ if (xc->parallel_enabled) {
+ fprintf(stderr, FST_APIMESS
+ "fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n");
+ exit(255);
+ }
+#endif
+ }
+}
+
+void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->dump_size_limit = numbytes;
+ }
+}
+
+int fstWriterGetDumpSizeLimitReached(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ return (xc->size_limit_locked != 0);
+ }
+
+ return (0);
+}
+
+int fstWriterGetFseekFailed(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ return (xc->fseek_failed != 0);
+ }
+
+ return (0);
+}
+
+/*
+ * writer attr/scope/var creation:
+ * fstWriterCreateVar2() is used to dump VHDL or other languages, but the
+ * underlying variable needs to map to Verilog/SV via the proper fstVarType vt
+ */
+fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle, const char *type, enum fstSupplementalVarType svt,
+ enum fstSupplementalDataType sdt)
+{
+ fstWriterSetAttrGeneric(ctx, type ? type : "", FST_MT_SUPVAR,
+ (svt << FST_SDT_SVT_SHIFT_COUNT) | (sdt & FST_SDT_ABS_MAX));
+ return (fstWriterCreateVar(ctx, vt, vd, len, nam, aliasHandle));
+}
+
+fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ unsigned int i;
+ int nlen, is_real;
+
+ if (xc && nam) {
+ if (xc->valpos_mem) {
+ fstDestroyMmaps(xc, 0);
+ }
+
+ fputc(vt, xc->hier_handle);
+ fputc(vd, xc->hier_handle);
+ nlen = strlen(nam);
+ fstFwrite(nam, nlen, 1, xc->hier_handle);
+ fputc(0, xc->hier_handle);
+ xc->hier_file_len += (nlen + 3);
+
+ if ((vt == FST_VT_VCD_REAL) || (vt == FST_VT_VCD_REAL_PARAMETER) || (vt == FST_VT_VCD_REALTIME) ||
+ (vt == FST_VT_SV_SHORTREAL)) {
+ is_real = 1;
+ len = 8; /* recast number of bytes to that of what a double is */
+ } else {
+ is_real = 0;
+ if (vt == FST_VT_GEN_STRING) {
+ len = 0;
+ }
+ }
+
+ xc->hier_file_len += fstWriterVarint(xc->hier_handle, len);
+
+ if (aliasHandle > xc->maxhandle)
+ aliasHandle = 0;
+ xc->hier_file_len += fstWriterVarint(xc->hier_handle, aliasHandle);
+ xc->numsigs++;
+ if (xc->numsigs == xc->next_huge_break) {
+ if (xc->fst_break_size < xc->fst_huge_break_size) {
+ xc->next_huge_break += FST_ACTIVATE_HUGE_INC;
+ xc->fst_break_size += xc->fst_orig_break_size;
+ xc->fst_break_add_size += xc->fst_orig_break_add_size;
+
+ xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size;
+ if (xc->vchg_mem) {
+ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
+ }
+ }
+ }
+
+ if (!aliasHandle) {
+ uint32_t zero = 0;
+
+ if (len) {
+ fstWriterVarint(xc->geom_handle, !is_real ? len : 0); /* geom section encodes reals as zero byte */
+ } else {
+ fstWriterVarint(xc->geom_handle, 0xFFFFFFFF); /* geom section encodes zero len as 32b -1 */
+ }
+
+ fstFwrite(&xc->maxvalpos, sizeof(uint32_t), 1, xc->valpos_handle);
+ fstFwrite(&len, sizeof(uint32_t), 1, xc->valpos_handle);
+ fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle);
+ fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle);
+
+ if (!is_real) {
+ for (i = 0; i < len; i++) {
+ fputc('x', xc->curval_handle);
+ }
+ } else {
+ fstFwrite(&xc->nan, 8, 1, xc->curval_handle); /* initialize doubles to NaN rather than x */
+ }
+
+ xc->maxvalpos += len;
+ xc->maxhandle++;
+ return (xc->maxhandle);
+ } else {
+ return (aliasHandle);
+ }
+ }
+
+ return (0);
+}
+
+void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, const char *scopename, const char *scopecomp)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_VCD_SCOPE, xc->hier_handle);
+ if (/*(scopetype < FST_ST_VCD_MODULE) ||*/ (scopetype > FST_ST_MAX)) {
+ scopetype = FST_ST_VCD_MODULE;
+ }
+ fputc(scopetype, xc->hier_handle);
+ fprintf(xc->hier_handle, "%s%c%s%c", scopename ? scopename : "", 0, scopecomp ? scopecomp : "", 0);
+
+ if (scopename) {
+ xc->hier_file_len += strlen(scopename);
+ }
+ if (scopecomp) {
+ xc->hier_file_len += strlen(scopecomp);
+ }
+
+ xc->hier_file_len += 4; /* FST_ST_VCD_SCOPE + scopetype + two string terminating zeros */
+ xc->numscopes++;
+ }
+}
+
+void fstWriterSetUpscope(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle);
+ xc->hier_file_len++;
+ }
+}
+
+void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, const char *attrname, uint64_t arg)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_GEN_ATTRBEGIN, xc->hier_handle);
+ if (/*(attrtype < FST_AT_MISC) ||*/ (attrtype > FST_AT_MAX)) {
+ attrtype = FST_AT_MISC;
+ subtype = FST_MT_UNKNOWN;
+ }
+ fputc(attrtype, xc->hier_handle);
+
+ switch (attrtype) {
+ case FST_AT_ARRAY:
+ if ((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX))
+ subtype = FST_AR_NONE;
+ break;
+ case FST_AT_ENUM:
+ if ((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX))
+ subtype = FST_EV_SV_INTEGER;
+ break;
+ case FST_AT_PACK:
+ if ((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX))
+ subtype = FST_PT_NONE;
+ break;
+
+ case FST_AT_MISC:
+ default:
+ break;
+ }
+
+ fputc(subtype, xc->hier_handle);
+ fprintf(xc->hier_handle, "%s%c", attrname ? attrname : "", 0);
+
+ if (attrname) {
+ xc->hier_file_len += strlen(attrname);
+ }
+
+ xc->hier_file_len += 4; /* FST_ST_GEN_ATTRBEGIN + type + subtype + string terminating zero */
+ xc->hier_file_len += fstWriterVarint(xc->hier_handle, arg);
+ }
+}
+
+void fstWriterSetAttrEnd(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_GEN_ATTREND, xc->hier_handle);
+ xc->hier_file_len++;
+ }
+}
+
+fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits,
+ const char **literal_arr, const char **val_arr)
+{
+ fstEnumHandle handle = 0;
+ unsigned int *literal_lens = NULL;
+ unsigned int *val_lens = NULL;
+ int lit_len_tot = 0;
+ int val_len_tot = 0;
+ int name_len;
+ char elem_count_buf[16];
+ int elem_count_len;
+ int total_len;
+ int pos = 0;
+ char *attr_str = NULL;
+
+ if (ctx && name && literal_arr && val_arr && (elem_count != 0)) {
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ uint32_t i;
+
+ name_len = strlen(name);
+ elem_count_len = sprintf(elem_count_buf, "%" PRIu32, elem_count);
+
+ literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
+ val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
+
+ for (i = 0; i < elem_count; i++) {
+ literal_lens[i] = strlen(literal_arr[i]);
+ lit_len_tot += fstUtilityBinToEscConvertedLen((unsigned char *)literal_arr[i], literal_lens[i]);
+
+ val_lens[i] = strlen(val_arr[i]);
+ val_len_tot += fstUtilityBinToEscConvertedLen((unsigned char *)val_arr[i], val_lens[i]);
+
+ if (min_valbits > 0) {
+ if (val_lens[i] < min_valbits) {
+ val_len_tot += (min_valbits - val_lens[i]); /* additional converted len is same for '0' character */
+ }
+ }
+ }
+
+ total_len = name_len + 1 + elem_count_len + 1 + lit_len_tot + elem_count + val_len_tot + elem_count;
+
+ attr_str = (char *)malloc(total_len);
+ pos = 0;
+
+ memcpy(attr_str + pos, name, name_len);
+ pos += name_len;
+ attr_str[pos++] = ' ';
+
+ memcpy(attr_str + pos, elem_count_buf, elem_count_len);
+ pos += elem_count_len;
+ attr_str[pos++] = ' ';
+
+ for (i = 0; i < elem_count; i++) {
+ pos += fstUtilityBinToEsc((unsigned char *)attr_str + pos, (unsigned char *)literal_arr[i],
+ literal_lens[i]);
+ attr_str[pos++] = ' ';
+ }
+
+ for (i = 0; i < elem_count; i++) {
+ if (min_valbits > 0) {
+ if (val_lens[i] < min_valbits) {
+ memset(attr_str + pos, '0', min_valbits - val_lens[i]);
+ pos += (min_valbits - val_lens[i]);
+ }
+ }
+
+ pos += fstUtilityBinToEsc((unsigned char *)attr_str + pos, (unsigned char *)val_arr[i], val_lens[i]);
+ attr_str[pos++] = ' ';
+ }
+
+ attr_str[pos - 1] = 0;
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "fstWriterCreateEnumTable() total_len: %d, pos: %d\n", total_len, pos);
+ fprintf(stderr, FST_APIMESS "*%s*\n", attr_str);
+#endif
+
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, attr_str, handle = ++xc->max_enumhandle);
+
+ free(attr_str);
+ free(val_lens);
+ free(literal_lens);
+ }
+
+ return (handle);
+}
+
+void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && handle) {
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle);
+ }
+}
+
+/*
+ * value and time change emission
+ */
+void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ const unsigned char *buf = (const unsigned char *)val;
+ uint32_t offs;
+ int len;
+
+ if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) {
+ uint32_t fpos;
+ uint32_t *vm4ip;
+
+ if (FST_UNLIKELY(!xc->valpos_mem)) {
+ xc->vc_emitted = 1;
+ fstWriterCreateMmaps(xc);
+ }
+
+ handle--; /* move starting at 1 index to starting at 0 */
+ vm4ip = &(xc->valpos_mem[4 * handle]);
+
+ len = vm4ip[1];
+ if (FST_LIKELY(len)) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */
+ {
+ if (FST_LIKELY(!xc->is_initial_time)) {
+ fpos = xc->vchg_siz;
+
+ if (FST_UNLIKELY((fpos + len + 10) > xc->vchg_alloc_siz)) {
+ xc->vchg_alloc_siz +=
+ (xc->fst_break_add_size +
+ len); /* +len added in the case of extremely long vectors and small break add sizes */
+ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
+ if (FST_UNLIKELY(!xc->vchg_mem)) {
+ fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChange, exiting.\n");
+ exit(255);
+ }
+ }
+#ifdef FST_REMOVE_DUPLICATE_VC
+ offs = vm4ip[0];
+
+ if (len != 1) {
+ if ((vm4ip[3] == xc->tchn_idx) && (vm4ip[2])) {
+ unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */
+ while (*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */
+ }
+ memcpy(old_value, buf, len); /* overlay new value */
+
+ memcpy(xc->curval_mem + offs, buf, len);
+ return;
+ } else {
+ if (!memcmp(xc->curval_mem + offs, buf, len)) {
+ if (!xc->curtime) {
+ int i;
+ for (i = 0; i < len; i++) {
+ if (buf[i] != 'x')
+ break;
+ }
+
+ if (i < len)
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ memcpy(xc->curval_mem + offs, buf, len);
+ } else {
+ if ((vm4ip[3] == xc->tchn_idx) && (vm4ip[2])) {
+ unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */
+ while (*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */
+ }
+ *old_value = *buf; /* overlay new value */
+
+ *(xc->curval_mem + offs) = *buf;
+ return;
+ } else {
+ if ((*(xc->curval_mem + offs)) == (*buf)) {
+ if (!xc->curtime) {
+ if (*buf != 'x')
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ *(xc->curval_mem + offs) = *buf;
+ }
+#endif
+ xc->vchg_siz += fstWriterUint32WithVarint32(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf,
+ len); /* do one fwrite op only */
+ vm4ip[3] = xc->tchn_idx;
+ vm4ip[2] = fpos;
+ } else {
+ offs = vm4ip[0];
+ memcpy(xc->curval_mem + offs, buf, len);
+ }
+ }
+ }
+}
+
+void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val)
+{
+ char buf[32];
+ char *s = buf;
+ uint32_t i;
+ for (i = 0; i < bits; ++i) {
+ *s++ = '0' + ((val >> (bits - i - 1)) & 1);
+ }
+ fstWriterEmitValueChange(ctx, handle, buf);
+}
+void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val)
+{
+ char buf[64];
+ char *s = buf;
+ uint32_t i;
+ for (i = 0; i < bits; ++i) {
+ *s++ = '0' + ((val >> (bits - i - 1)) & 1);
+ }
+ fstWriterEmitValueChange(ctx, handle, buf);
+}
+void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (FST_UNLIKELY(bits <= 32)) {
+ fstWriterEmitValueChange32(ctx, handle, bits, val[0]);
+ } else if (FST_LIKELY(xc)) {
+ int bq = bits / 32;
+ int br = bits & 31;
+ int i;
+ int w;
+ uint32_t v;
+ unsigned char *s;
+ if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) {
+ xc->outval_alloc_siz = bits * 2 + 1;
+ xc->outval_mem = (unsigned char *)realloc(xc->outval_mem, xc->outval_alloc_siz);
+ if (FST_UNLIKELY(!xc->outval_mem)) {
+ fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec32, exiting.\n");
+ exit(255);
+ }
+ }
+ s = xc->outval_mem;
+ {
+ w = bq;
+ v = val[w];
+ for (i = 0; i < br; ++i) {
+ *s++ = '0' + ((v >> (br - i - 1)) & 1);
+ }
+ }
+ for (w = bq - 1; w >= 0; --w) {
+ v = val[w];
+ for (i = (32 - 4); i >= 0; i -= 4) {
+ s[0] = '0' + ((v >> (i + 3)) & 1);
+ s[1] = '0' + ((v >> (i + 2)) & 1);
+ s[2] = '0' + ((v >> (i + 1)) & 1);
+ s[3] = '0' + ((v >> (i + 0)) & 1);
+ s += 4;
+ }
+ }
+ fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
+ }
+}
+void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (FST_UNLIKELY(bits <= 64)) {
+ fstWriterEmitValueChange64(ctx, handle, bits, val[0]);
+ } else if (FST_LIKELY(xc)) {
+ int bq = bits / 64;
+ int br = bits & 63;
+ int i;
+ int w;
+ uint32_t v;
+ unsigned char *s;
+ if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) {
+ xc->outval_alloc_siz = bits * 2 + 1;
+ xc->outval_mem = (unsigned char *)realloc(xc->outval_mem, xc->outval_alloc_siz);
+ if (FST_UNLIKELY(!xc->outval_mem)) {
+ fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec64, exiting.\n");
+ exit(255);
+ }
+ }
+ s = xc->outval_mem;
+ {
+ w = bq;
+ v = val[w];
+ for (i = 0; i < br; ++i) {
+ *s++ = '0' + ((v >> (br - i - 1)) & 1);
+ }
+ }
+ for (w = bq - 1; w >= 0; --w) {
+ v = val[w];
+ for (i = (64 - 4); i >= 0; i -= 4) {
+ s[0] = '0' + ((v >> (i + 3)) & 1);
+ s[1] = '0' + ((v >> (i + 2)) & 1);
+ s[2] = '0' + ((v >> (i + 1)) & 1);
+ s[3] = '0' + ((v >> (i + 0)) & 1);
+ s += 4;
+ }
+ }
+ fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
+ }
+}
+
+void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ const unsigned char *buf = (const unsigned char *)val;
+
+ if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) {
+ uint32_t fpos;
+ uint32_t *vm4ip;
+
+ if (FST_UNLIKELY(!xc->valpos_mem)) {
+ xc->vc_emitted = 1;
+ fstWriterCreateMmaps(xc);
+ }
+
+ handle--; /* move starting at 1 index to starting at 0 */
+ vm4ip = &(xc->valpos_mem[4 * handle]);
+
+ /* there is no initial time dump for variable length value changes */
+ if (FST_LIKELY(!vm4ip[1])) /* len of zero = variable length */
+ {
+ fpos = xc->vchg_siz;
+
+ if (FST_UNLIKELY((fpos + len + 10 + 5) > xc->vchg_alloc_siz)) {
+ xc->vchg_alloc_siz +=
+ (xc->fst_break_add_size + len +
+ 5); /* +len added in the case of extremely long vectors and small break add sizes */
+ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
+ if (FST_UNLIKELY(!xc->vchg_mem)) {
+ fprintf(stderr,
+ FST_APIMESS "Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n");
+ exit(255);
+ }
+ }
+
+ xc->vchg_siz += fstWriterUint32WithVarint32AndLength(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf,
+ len); /* do one fwrite op only */
+ vm4ip[3] = xc->tchn_idx;
+ vm4ip[2] = fpos;
+ }
+ }
+}
+
+void fstWriterEmitTimeChange(void *ctx, uint64_t tim)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ unsigned int i;
+ int skip = 0;
+ if (xc) {
+ if (FST_UNLIKELY(xc->is_initial_time)) {
+ if (xc->size_limit_locked) /* this resets xc->is_initial_time to one */
+ {
+ return;
+ }
+
+ if (!xc->valpos_mem) {
+ fstWriterCreateMmaps(xc);
+ }
+
+ skip = 1;
+
+ xc->firsttime = (xc->vc_emitted) ? 0 : tim;
+ xc->curtime = 0;
+ xc->vchg_mem[0] = '!';
+ xc->vchg_siz = 1;
+ fstWriterEmitSectionHeader(xc);
+ for (i = 0; i < xc->maxhandle; i++) {
+ xc->valpos_mem[4 * i + 2] = 0; /* zero out offset val */
+ xc->valpos_mem[4 * i + 3] = 0; /* zero out last time change val */
+ }
+ xc->is_initial_time = 0;
+ } else {
+ if ((xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending)) {
+ xc->flush_context_pending = 0;
+ fstWriterFlushContextPrivate(xc);
+ xc->tchn_cnt++;
+ fstWriterVarint(xc->tchn_handle, xc->curtime);
+ }
+ }
+
+ if (!skip) {
+ xc->tchn_idx++;
+ }
+ fstWriterVarint(xc->tchn_handle, tim - xc->curtime);
+ xc->tchn_cnt++;
+ xc->curtime = tim;
+ }
+}
+
+void fstWriterEmitDumpActive(void *ctx, int enable)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ struct fstBlackoutChain *b = (struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain));
+
+ b->tim = xc->curtime;
+ b->active = (enable != 0);
+
+ xc->num_blackouts++;
+ if (xc->blackout_curr) {
+ xc->blackout_curr->next = b;
+ xc->blackout_curr = b;
+ } else {
+ xc->blackout_head = b;
+ xc->blackout_curr = b;
+ }
+ }
+}
+
+/***********************/
+/*** ***/
+/*** reader function ***/
+/*** ***/
+/***********************/
+
+/*
+ * private structs
+ */
+static const char *vartypes[] = {"event", "integer", "parameter", "real", "real_parameter", "reg", "supply0",
+ "supply1", "time", "tri", "triand", "trior", "trireg", "tri0",
+ "tri1", "wand", "wire", "wor", "port", "sparray", "realtime",
+ "string", "bit", "logic", "int", "shortint", "longint", "byte",
+ "enum", "shortreal"};
+
+static const char *modtypes[] = {"module",
+ "task",
+ "function",
+ "begin",
+ "fork",
+ "generate",
+ "struct",
+ "union",
+ "class",
+ "interface",
+ "package",
+ "program",
+ "vhdl_architecture",
+ "vhdl_procedure",
+ "vhdl_function",
+ "vhdl_record",
+ "vhdl_process",
+ "vhdl_block",
+ "vhdl_for_generate",
+ "vhdl_if_generate",
+ "vhdl_generate",
+ "vhdl_package"};
+
+static const char *attrtypes[] = {"misc", "array", "enum", "class"};
+
+static const char *arraytypes[] = {"none", "unpacked", "packed", "sparse"};
+
+static const char *enumvaluetypes[] = {"integer",
+ "bit",
+ "logic",
+ "int",
+ "shortint",
+ "longint",
+ "byte",
+ "unsigned_integer",
+ "unsigned_bit",
+ "unsigned_logic",
+ "unsigned_int",
+ "unsigned_shortint",
+ "unsigned_longint",
+ "unsigned_byte"};
+
+static const char *packtypes[] = {"none", "unpacked", "packed", "tagged_packed"};
+
+struct fstCurrHier
+{
+ struct fstCurrHier *prev;
+ void *user_info;
+ int len;
+};
+
+struct fstReaderContext
+{
+ /* common entries */
+
+ FILE *f, *fh;
+
+ uint64_t start_time, end_time;
+ uint64_t mem_used_by_writer;
+ uint64_t scope_count;
+ uint64_t var_count;
+ fstHandle maxhandle;
+ uint64_t num_alias;
+ uint64_t vc_section_count;
+
+ uint32_t *signal_lens; /* maxhandle sized */
+ unsigned char *signal_typs; /* maxhandle sized */
+ unsigned char *process_mask; /* maxhandle-based, bitwise sized */
+ uint32_t longest_signal_value_len; /* longest len value encountered */
+ unsigned char *temp_signal_value_buf; /* malloced for len in longest_signal_value_len */
+
+ signed char timescale;
+ unsigned char filetype;
+
+ unsigned use_vcd_extensions : 1;
+ unsigned double_endian_match : 1;
+ unsigned native_doubles_for_cb : 1;
+ unsigned contains_geom_section : 1;
+ unsigned contains_hier_section : 1; /* valid for hier_pos */
+ unsigned contains_hier_section_lz4duo : 1; /* valid for hier_pos (contains_hier_section_lz4 always also set) */
+ unsigned contains_hier_section_lz4 : 1; /* valid for hier_pos */
+ unsigned limit_range_valid : 1; /* valid for limit_range_start, limit_range_end */
+
+ char version[FST_HDR_SIM_VERSION_SIZE + 1];
+ char date[FST_HDR_DATE_SIZE + 1];
+ int64_t timezero;
+
+ char *filename, *filename_unpacked;
+ fst_off_t hier_pos;
+
+ uint32_t num_blackouts;
+ uint64_t *blackout_times;
+ unsigned char *blackout_activity;
+
+ uint64_t limit_range_start, limit_range_end;
+
+ /* entries specific to read value at time functions */
+
+ unsigned rvat_data_valid : 1;
+ uint64_t *rvat_time_table;
+ uint64_t rvat_beg_tim, rvat_end_tim;
+ unsigned char *rvat_frame_data;
+ uint64_t rvat_frame_maxhandle;
+ fst_off_t *rvat_chain_table;
+ uint32_t *rvat_chain_table_lengths;
+ uint64_t rvat_vc_maxhandle;
+ fst_off_t rvat_vc_start;
+ uint32_t *rvat_sig_offs;
+ int rvat_packtype;
+
+ uint32_t rvat_chain_len;
+ unsigned char *rvat_chain_mem;
+ fstHandle rvat_chain_facidx;
+
+ uint32_t rvat_chain_pos_tidx;
+ uint32_t rvat_chain_pos_idx;
+ uint64_t rvat_chain_pos_time;
+ unsigned rvat_chain_pos_valid : 1;
+
+ /* entries specific to hierarchy traversal */
+
+ struct fstHier hier;
+ struct fstCurrHier *curr_hier;
+ fstHandle current_handle;
+ char *curr_flat_hier_nam;
+ int flat_hier_alloc_len;
+ unsigned do_rewind : 1;
+ char str_scope_nam[FST_ID_NAM_SIZ + 1];
+ char str_scope_comp[FST_ID_NAM_SIZ + 1];
+
+ unsigned fseek_failed : 1;
+
+ /* self-buffered I/O for writes */
+
+#ifndef FST_WRITEX_DISABLE
+ int writex_pos;
+ int writex_fd;
+ unsigned char writex_buf[FST_WRITEX_MAX];
+#endif
+
+ char *f_nam;
+ char *fh_nam;
+};
+
+int fstReaderFseeko(struct fstReaderContext *xc, FILE *stream, fst_off_t offset, int whence)
+{
+ int rc = fseeko(stream, offset, whence);
+
+ if (rc < 0) {
+ xc->fseek_failed = 1;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence);
+ perror("Why");
+#endif
+ }
+
+ return (rc);
+}
+
+#ifndef FST_WRITEX_DISABLE
+static void fstWritex(struct fstReaderContext *xc, void *v, int len)
+{
+ unsigned char *s = (unsigned char *)v;
+
+ if (len) {
+ if (len < FST_WRITEX_MAX) {
+ if (xc->writex_pos + len >= FST_WRITEX_MAX) {
+ fstWritex(xc, NULL, 0);
+ }
+
+ memcpy(xc->writex_buf + xc->writex_pos, s, len);
+ xc->writex_pos += len;
+ } else {
+ fstWritex(xc, NULL, 0);
+ if (write(xc->writex_fd, s, len)) {
+ };
+ }
+ } else {
+ if (xc->writex_pos) {
+ if (write(xc->writex_fd, xc->writex_buf, xc->writex_pos)) {
+ };
+ xc->writex_pos = 0;
+ }
+ }
+}
+#endif
+
+/*
+ * scope -> flat name handling
+ */
+static void fstReaderDeallocateScopeData(struct fstReaderContext *xc)
+{
+ struct fstCurrHier *chp;
+
+ free(xc->curr_flat_hier_nam);
+ xc->curr_flat_hier_nam = NULL;
+ while (xc->curr_hier) {
+ chp = xc->curr_hier->prev;
+ free(xc->curr_hier);
+ xc->curr_hier = chp;
+ }
+}
+
+const char *fstReaderGetCurrentFlatScope(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : "");
+ } else {
+ return (NULL);
+ }
+}
+
+void *fstReaderGetCurrentScopeUserInfo(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ return (xc->curr_hier ? xc->curr_hier->user_info : NULL);
+ } else {
+ return (NULL);
+ }
+}
+
+const char *fstReaderPopScope(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc && xc->curr_hier) {
+ struct fstCurrHier *ch = xc->curr_hier;
+ if (xc->curr_hier->prev) {
+ xc->curr_flat_hier_nam[xc->curr_hier->prev->len] = 0;
+ } else {
+ *xc->curr_flat_hier_nam = 0;
+ }
+ xc->curr_hier = xc->curr_hier->prev;
+ free(ch);
+ return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : "");
+ }
+
+ return (NULL);
+}
+
+void fstReaderResetScope(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ while (fstReaderPopScope(xc))
+ ; /* remove any already-built scoping info */
+ }
+}
+
+const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ struct fstCurrHier *ch = (struct fstCurrHier *)malloc(sizeof(struct fstCurrHier));
+ int chl = xc->curr_hier ? xc->curr_hier->len : 0;
+ int len = chl + 1 + strlen(nam);
+ if (len >= xc->flat_hier_alloc_len) {
+ xc->curr_flat_hier_nam =
+ xc->curr_flat_hier_nam ? (char *)realloc(xc->curr_flat_hier_nam, len + 1) : (char *)malloc(len + 1);
+ }
+
+ if (chl) {
+ xc->curr_flat_hier_nam[chl] = '.';
+ strcpy(xc->curr_flat_hier_nam + chl + 1, nam);
+ } else {
+ strcpy(xc->curr_flat_hier_nam, nam);
+ len--;
+ }
+
+ ch->len = len;
+ ch->prev = xc->curr_hier;
+ ch->user_info = user_info;
+ xc->curr_hier = ch;
+ return (xc->curr_flat_hier_nam);
+ }
+
+ return (NULL);
+}
+
+int fstReaderGetCurrentScopeLen(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc && xc->curr_hier) {
+ return (xc->curr_hier->len);
+ }
+
+ return (0);
+}
+
+int fstReaderGetFseekFailed(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ return (xc->fseek_failed != 0);
+ }
+
+ return (0);
+}
+
+/*
+ * iter mask manipulation util functions
+ */
+int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ facidx--;
+ if (facidx < xc->maxhandle) {
+ int process_idx = facidx / 8;
+ int process_bit = facidx & 7;
+
+ return ((xc->process_mask[process_idx] & (1 << process_bit)) != 0);
+ }
+ }
+ return (0);
+}
+
+void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ facidx--;
+ if (facidx < xc->maxhandle) {
+ int idx = facidx / 8;
+ int bitpos = facidx & 7;
+
+ xc->process_mask[idx] |= (1 << bitpos);
+ }
+ }
+}
+
+void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ facidx--;
+ if (facidx < xc->maxhandle) {
+ int idx = facidx / 8;
+ int bitpos = facidx & 7;
+
+ xc->process_mask[idx] &= (~(1 << bitpos));
+ }
+ }
+}
+
+void fstReaderSetFacProcessMaskAll(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ memset(xc->process_mask, 0xff, (xc->maxhandle + 7) / 8);
+ }
+}
+
+void fstReaderClrFacProcessMaskAll(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ memset(xc->process_mask, 0x00, (xc->maxhandle + 7) / 8);
+ }
+}
+
+/*
+ * various utility read/write functions
+ */
+signed char fstReaderGetTimescale(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->timescale : 0);
+}
+
+uint64_t fstReaderGetStartTime(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->start_time : 0);
+}
+
+uint64_t fstReaderGetEndTime(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->end_time : 0);
+}
+
+uint64_t fstReaderGetMemoryUsedByWriter(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->mem_used_by_writer : 0);
+}
+
+uint64_t fstReaderGetScopeCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->scope_count : 0);
+}
+
+uint64_t fstReaderGetVarCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->var_count : 0);
+}
+
+fstHandle fstReaderGetMaxHandle(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->maxhandle : 0);
+}
+
+uint64_t fstReaderGetAliasCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->num_alias : 0);
+}
+
+uint64_t fstReaderGetValueChangeSectionCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->vc_section_count : 0);
+}
+
+int fstReaderGetDoubleEndianMatchState(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->double_endian_match : 0);
+}
+
+const char *fstReaderGetVersionString(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->version : NULL);
+}
+
+const char *fstReaderGetDateString(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->date : NULL);
+}
+
+int fstReaderGetFileType(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? (int)xc->filetype : (int)FST_FT_VERILOG);
+}
+
+int64_t fstReaderGetTimezero(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->timezero : 0);
+}
+
+uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->num_blackouts : 0);
+}
+
+uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc && (idx < xc->num_blackouts) && (xc->blackout_times)) {
+ return (xc->blackout_times[idx]);
+ } else {
+ return (0);
+ }
+}
+
+unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc && (idx < xc->num_blackouts) && (xc->blackout_activity)) {
+ return (xc->blackout_activity[idx]);
+ } else {
+ return (0);
+ }
+}
+
+void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ xc->limit_range_valid = 1;
+ xc->limit_range_start = start_time;
+ xc->limit_range_end = end_time;
+ }
+}
+
+void fstReaderSetUnlimitedTimeRange(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ xc->limit_range_valid = 0;
+ }
+}
+
+void fstReaderSetVcdExtensions(void *ctx, int enable)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ xc->use_vcd_extensions = (enable != 0);
+ }
+}
+
+void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ xc->native_doubles_for_cb = (enable != 0);
+ }
+}
+
+/*
+ * hierarchy processing
+ */
+static void fstVcdID(char *buf, unsigned int value)
+{
+ char *pnt = buf;
+
+ /* zero is illegal for a value...it is assumed they start at one */
+ while (value) {
+ value--;
+ *(pnt++) = (char)('!' + value % 94);
+ value = value / 94;
+ }
+
+ *pnt = 0;
+}
+
+static int fstVcdIDForFwrite(char *buf, unsigned int value)
+{
+ char *pnt = buf;
+
+ /* zero is illegal for a value...it is assumed they start at one */
+ while (value) {
+ value--;
+ *(pnt++) = (char)('!' + value % 94);
+ value = value / 94;
+ }
+
+ return (pnt - buf);
+}
+
+static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
+{
+ int pass_status = 1;
+
+ if (!xc->fh) {
+ fst_off_t offs_cache = ftello(xc->f);
+ char *fnam = (char *)malloc(strlen(xc->filename) + 6 + 16 + 32 + 1);
+ unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN);
+ fst_off_t hl, uclen;
+ fst_off_t clen = 0;
+ gzFile zhandle = NULL;
+ int zfd;
+ int htyp = FST_BL_SKIP;
+
+ /* can't handle both set at once should never happen in a real file */
+ if (!xc->contains_hier_section_lz4 && xc->contains_hier_section) {
+ htyp = FST_BL_HIER;
+ } else if (xc->contains_hier_section_lz4 && !xc->contains_hier_section) {
+ htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4;
+ }
+
+ sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc);
+ fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET);
+ uclen = fstReaderUint64(xc->f);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+ if (htyp == FST_BL_HIER) {
+ fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET);
+ uclen = fstReaderUint64(xc->f);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+ zfd = dup(fileno(xc->f));
+ zhandle = gzdopen(zfd, "rb");
+ if (!zhandle) {
+ close(zfd);
+ free(mem);
+ free(fnam);
+ return (0);
+ }
+ } else if ((htyp == FST_BL_HIER_LZ4) || (htyp == FST_BL_HIER_LZ4DUO)) {
+ fstReaderFseeko(xc, xc->f, xc->hier_pos - 8, SEEK_SET); /* get section len */
+ clen = fstReaderUint64(xc->f) - 16;
+ uclen = fstReaderUint64(xc->f);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+ }
+
+#ifndef __MINGW32__
+ xc->fh = fopen(fnam, "w+b");
+ if (!xc->fh)
+#endif
+ {
+ xc->fh = tmpfile_open(&xc->fh_nam);
+ free(fnam);
+ fnam = NULL;
+ if (!xc->fh) {
+ tmpfile_close(&xc->fh, &xc->fh_nam);
+ free(mem);
+ return (0);
+ }
+ }
+
+#ifndef __MINGW32__
+ if (fnam)
+ unlink(fnam);
+#endif
+
+ if (htyp == FST_BL_HIER) {
+ for (hl = 0; hl < uclen; hl += FST_GZIO_LEN) {
+ size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl);
+ size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */
+ size_t fwlen;
+
+ if (gzreadlen != len) {
+ pass_status = 0;
+ break;
+ }
+
+ fwlen = fstFwrite(mem, len, 1, xc->fh);
+ if (fwlen != 1) {
+ pass_status = 0;
+ break;
+ }
+ }
+ gzclose(zhandle);
+ } else if (htyp == FST_BL_HIER_LZ4DUO) {
+ unsigned char *lz4_cmem = (unsigned char *)malloc(clen);
+ unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen);
+ unsigned char *lz4_ucmem2;
+ uint64_t uclen2;
+ int skiplen2 = 0;
+
+ fstFread(lz4_cmem, clen, 1, xc->f);
+
+ uclen2 = fstGetVarint64(lz4_cmem, &skiplen2);
+ lz4_ucmem2 = (unsigned char *)malloc(uclen2);
+ pass_status =
+ (uclen2 == (uint64_t)LZ4_decompress_safe_partial((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2,
+ clen - skiplen2, uclen2, uclen2));
+ if (pass_status) {
+ pass_status = (uclen == LZ4_decompress_safe_partial((char *)lz4_ucmem2, (char *)lz4_ucmem, uclen2,
+ uclen, uclen));
+
+ if (fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) {
+ pass_status = 0;
+ }
+ }
+
+ free(lz4_ucmem2);
+ free(lz4_ucmem);
+ free(lz4_cmem);
+ } else if (htyp == FST_BL_HIER_LZ4) {
+ unsigned char *lz4_cmem = (unsigned char *)malloc(clen);
+ unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen);
+
+ fstFread(lz4_cmem, clen, 1, xc->f);
+ pass_status =
+ (uclen == LZ4_decompress_safe_partial((char *)lz4_cmem, (char *)lz4_ucmem, clen, uclen, uclen));
+
+ if (fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) {
+ pass_status = 0;
+ }
+
+ free(lz4_ucmem);
+ free(lz4_cmem);
+ } else /* FST_BL_SKIP */
+ {
+ pass_status = 0;
+ if (xc->fh) {
+ fclose(xc->fh);
+ xc->fh = NULL; /* needed in case .hier file is missing and there are no hier sections */
+ }
+ }
+
+ free(mem);
+ free(fnam);
+
+ fstReaderFseeko(xc, xc->f, offs_cache, SEEK_SET);
+ }
+
+ return (pass_status);
+}
+
+int fstReaderIterateHierRewind(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ int pass_status = 0;
+
+ if (xc) {
+ pass_status = 1;
+ if (!xc->fh) {
+ pass_status = fstReaderRecreateHierFile(xc);
+ }
+
+ xc->do_rewind = 1;
+ }
+
+ return (pass_status);
+}
+
+struct fstHier *fstReaderIterateHier(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ int isfeof;
+ fstHandle alias;
+ char *pnt;
+ int ch;
+
+ if (!xc)
+ return (NULL);
+
+ if (!xc->fh) {
+ if (!fstReaderRecreateHierFile(xc)) {
+ return (NULL);
+ }
+ }
+
+ if (xc->do_rewind) {
+ xc->do_rewind = 0;
+ xc->current_handle = 0;
+ fstReaderFseeko(xc, xc->fh, 0, SEEK_SET);
+ clearerr(xc->fh);
+ }
+
+ if (!(isfeof = feof(xc->fh))) {
+ int tag = fgetc(xc->fh);
+ switch (tag) {
+ case FST_ST_VCD_SCOPE:
+ xc->hier.htyp = FST_HT_SCOPE;
+ xc->hier.u.scope.typ = fgetc(xc->fh);
+ xc->hier.u.scope.name = pnt = xc->str_scope_nam;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopename */
+ *pnt = 0;
+ xc->hier.u.scope.name_length = pnt - xc->hier.u.scope.name;
+
+ xc->hier.u.scope.component = pnt = xc->str_scope_comp;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopecomp */
+ *pnt = 0;
+ xc->hier.u.scope.component_length = pnt - xc->hier.u.scope.component;
+ break;
+
+ case FST_ST_VCD_UPSCOPE:
+ xc->hier.htyp = FST_HT_UPSCOPE;
+ break;
+
+ case FST_ST_GEN_ATTRBEGIN:
+ xc->hier.htyp = FST_HT_ATTRBEGIN;
+ xc->hier.u.attr.typ = fgetc(xc->fh);
+ xc->hier.u.attr.subtype = fgetc(xc->fh);
+ xc->hier.u.attr.name = pnt = xc->str_scope_nam;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopename */
+ *pnt = 0;
+ xc->hier.u.attr.name_length = pnt - xc->hier.u.scope.name;
+
+ xc->hier.u.attr.arg = fstReaderVarint64(xc->fh);
+
+ if (xc->hier.u.attr.typ == FST_AT_MISC) {
+ if ((xc->hier.u.attr.subtype == FST_MT_SOURCESTEM) || (xc->hier.u.attr.subtype == FST_MT_SOURCEISTEM)) {
+ int sidx_skiplen_dummy = 0;
+ xc->hier.u.attr.arg_from_name =
+ fstGetVarint64((unsigned char *)xc->str_scope_nam, &sidx_skiplen_dummy);
+ }
+ }
+ break;
+
+ case FST_ST_GEN_ATTREND:
+ xc->hier.htyp = FST_HT_ATTREND;
+ break;
+
+ case FST_VT_VCD_EVENT:
+ case FST_VT_VCD_INTEGER:
+ case FST_VT_VCD_PARAMETER:
+ case FST_VT_VCD_REAL:
+ case FST_VT_VCD_REAL_PARAMETER:
+ case FST_VT_VCD_REG:
+ case FST_VT_VCD_SUPPLY0:
+ case FST_VT_VCD_SUPPLY1:
+ case FST_VT_VCD_TIME:
+ case FST_VT_VCD_TRI:
+ case FST_VT_VCD_TRIAND:
+ case FST_VT_VCD_TRIOR:
+ case FST_VT_VCD_TRIREG:
+ case FST_VT_VCD_TRI0:
+ case FST_VT_VCD_TRI1:
+ case FST_VT_VCD_WAND:
+ case FST_VT_VCD_WIRE:
+ case FST_VT_VCD_WOR:
+ case FST_VT_VCD_PORT:
+ case FST_VT_VCD_SPARRAY:
+ case FST_VT_VCD_REALTIME:
+ case FST_VT_GEN_STRING:
+ case FST_VT_SV_BIT:
+ case FST_VT_SV_LOGIC:
+ case FST_VT_SV_INT:
+ case FST_VT_SV_SHORTINT:
+ case FST_VT_SV_LONGINT:
+ case FST_VT_SV_BYTE:
+ case FST_VT_SV_ENUM:
+ case FST_VT_SV_SHORTREAL:
+ xc->hier.htyp = FST_HT_VAR;
+ xc->hier.u.var.svt_workspace = FST_SVT_NONE;
+ xc->hier.u.var.sdt_workspace = FST_SDT_NONE;
+ xc->hier.u.var.sxt_workspace = 0;
+ xc->hier.u.var.typ = tag;
+ xc->hier.u.var.direction = fgetc(xc->fh);
+ xc->hier.u.var.name = pnt = xc->str_scope_nam;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* varname */
+ *pnt = 0;
+ xc->hier.u.var.name_length = pnt - xc->hier.u.var.name;
+ xc->hier.u.var.length = fstReaderVarint32(xc->fh);
+ if (tag == FST_VT_VCD_PORT) {
+ xc->hier.u.var.length -= 2; /* removal of delimiting spaces */
+ xc->hier.u.var.length /= 3; /* port -> signal size adjust */
+ }
+
+ alias = fstReaderVarint32(xc->fh);
+
+ if (!alias) {
+ xc->current_handle++;
+ xc->hier.u.var.handle = xc->current_handle;
+ xc->hier.u.var.is_alias = 0;
+ } else {
+ xc->hier.u.var.handle = alias;
+ xc->hier.u.var.is_alias = 1;
+ }
+
+ break;
+
+ default:
+ isfeof = 1;
+ break;
+ }
+ }
+
+ return (!isfeof ? &xc->hier : NULL);
+}
+
+int fstReaderProcessHier(void *ctx, FILE *fv)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ char *str;
+ char *pnt;
+ int ch, scopetype;
+ int vartype;
+ uint32_t len, alias;
+ /* uint32_t maxvalpos=0; */
+ unsigned int num_signal_dyn = 65536;
+ int attrtype, subtype;
+ uint64_t attrarg;
+ fstHandle maxhandle_scanbuild;
+
+ if (!xc)
+ return (0);
+
+ xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */
+
+ if (!xc->fh) {
+ if (!fstReaderRecreateHierFile(xc)) {
+ return (0);
+ }
+ }
+
+ str = (char *)malloc(FST_ID_NAM_ATTR_SIZ + 1);
+
+ if (fv) {
+ char time_dimension[2] = {0, 0};
+ int time_scale = 1;
+
+ fprintf(fv, "$date\n\t%s\n$end\n", xc->date);
+ fprintf(fv, "$version\n\t%s\n$end\n", xc->version);
+ if (xc->timezero)
+ fprintf(fv, "$timezero\n\t%" PRId64 "\n$end\n", xc->timezero);
+
+ switch (xc->timescale) {
+ case 2:
+ time_scale = 100;
+ time_dimension[0] = 0;
+ break;
+ case 1:
+ time_scale = 10; /* fallthrough */
+ case 0:
+ time_dimension[0] = 0;
+ break;
+
+ case -1:
+ time_scale = 100;
+ time_dimension[0] = 'm';
+ break;
+ case -2:
+ time_scale = 10; /* fallthrough */
+ case -3:
+ time_dimension[0] = 'm';
+ break;
+
+ case -4:
+ time_scale = 100;
+ time_dimension[0] = 'u';
+ break;
+ case -5:
+ time_scale = 10; /* fallthrough */
+ case -6:
+ time_dimension[0] = 'u';
+ break;
+
+ case -10:
+ time_scale = 100;
+ time_dimension[0] = 'p';
+ break;
+ case -11:
+ time_scale = 10; /* fallthrough */
+ case -12:
+ time_dimension[0] = 'p';
+ break;
+
+ case -13:
+ time_scale = 100;
+ time_dimension[0] = 'f';
+ break;
+ case -14:
+ time_scale = 10; /* fallthrough */
+ case -15:
+ time_dimension[0] = 'f';
+ break;
+
+ case -16:
+ time_scale = 100;
+ time_dimension[0] = 'a';
+ break;
+ case -17:
+ time_scale = 10; /* fallthrough */
+ case -18:
+ time_dimension[0] = 'a';
+ break;
+
+ case -19:
+ time_scale = 100;
+ time_dimension[0] = 'z';
+ break;
+ case -20:
+ time_scale = 10; /* fallthrough */
+ case -21:
+ time_dimension[0] = 'z';
+ break;
+
+ case -7:
+ time_scale = 100;
+ time_dimension[0] = 'n';
+ break;
+ case -8:
+ time_scale = 10; /* fallthrough */
+ case -9:
+ default:
+ time_dimension[0] = 'n';
+ break;
+ }
+
+ if (fv)
+ fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension);
+ }
+
+ xc->maxhandle = 0;
+ xc->num_alias = 0;
+
+ free(xc->signal_lens);
+ xc->signal_lens = (uint32_t *)malloc(num_signal_dyn * sizeof(uint32_t));
+
+ free(xc->signal_typs);
+ xc->signal_typs = (unsigned char *)malloc(num_signal_dyn * sizeof(unsigned char));
+
+ fstReaderFseeko(xc, xc->fh, 0, SEEK_SET);
+ while (!feof(xc->fh)) {
+ int tag = fgetc(xc->fh);
+ switch (tag) {
+ case FST_ST_VCD_SCOPE:
+ scopetype = fgetc(xc->fh);
+ if ((scopetype < FST_ST_MIN) || (scopetype > FST_ST_MAX))
+ scopetype = FST_ST_VCD_MODULE;
+ pnt = str;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopename */
+ *pnt = 0;
+ while (fgetc(xc->fh)) {
+ }; /* scopecomp */
+
+ if (fv)
+ fprintf(fv, "$scope %s %s $end\n", modtypes[scopetype], str);
+ break;
+
+ case FST_ST_VCD_UPSCOPE:
+ if (fv)
+ fprintf(fv, "$upscope $end\n");
+ break;
+
+ case FST_ST_GEN_ATTRBEGIN:
+ attrtype = fgetc(xc->fh);
+ subtype = fgetc(xc->fh);
+ pnt = str;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* attrname */
+ *pnt = 0;
+
+ if (!str[0]) {
+ strcpy(str, "\"\"");
+ }
+
+ attrarg = fstReaderVarint64(xc->fh);
+
+ if (fv && xc->use_vcd_extensions) {
+ switch (attrtype) {
+ case FST_AT_ARRAY:
+ if ((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX))
+ subtype = FST_AR_NONE;
+ fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], arraytypes[subtype], str,
+ attrarg);
+ break;
+ case FST_AT_ENUM:
+ if ((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX))
+ subtype = FST_EV_SV_INTEGER;
+ fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], enumvaluetypes[subtype],
+ str, attrarg);
+ break;
+ case FST_AT_PACK:
+ if ((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX))
+ subtype = FST_PT_NONE;
+ fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], packtypes[subtype], str,
+ attrarg);
+ break;
+ case FST_AT_MISC:
+ default:
+ attrtype = FST_AT_MISC;
+ if (subtype == FST_MT_COMMENT) {
+ fprintf(fv, "$comment\n\t%s\n$end\n", str);
+ } else {
+ if ((subtype == FST_MT_SOURCESTEM) || (subtype == FST_MT_SOURCEISTEM)) {
+ int sidx_skiplen_dummy = 0;
+ uint64_t sidx = fstGetVarint64((unsigned char *)str, &sidx_skiplen_dummy);
+
+ fprintf(fv, "$attrbegin %s %02x %" PRId64 " %" PRId64 " $end\n", attrtypes[attrtype],
+ subtype, sidx, attrarg);
+ } else {
+ fprintf(fv, "$attrbegin %s %02x %s %" PRId64 " $end\n", attrtypes[attrtype], subtype, str,
+ attrarg);
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case FST_ST_GEN_ATTREND:
+ if (fv && xc->use_vcd_extensions)
+ fprintf(fv, "$attrend $end\n");
+ break;
+
+ case FST_VT_VCD_EVENT:
+ case FST_VT_VCD_INTEGER:
+ case FST_VT_VCD_PARAMETER:
+ case FST_VT_VCD_REAL:
+ case FST_VT_VCD_REAL_PARAMETER:
+ case FST_VT_VCD_REG:
+ case FST_VT_VCD_SUPPLY0:
+ case FST_VT_VCD_SUPPLY1:
+ case FST_VT_VCD_TIME:
+ case FST_VT_VCD_TRI:
+ case FST_VT_VCD_TRIAND:
+ case FST_VT_VCD_TRIOR:
+ case FST_VT_VCD_TRIREG:
+ case FST_VT_VCD_TRI0:
+ case FST_VT_VCD_TRI1:
+ case FST_VT_VCD_WAND:
+ case FST_VT_VCD_WIRE:
+ case FST_VT_VCD_WOR:
+ case FST_VT_VCD_PORT:
+ case FST_VT_VCD_SPARRAY:
+ case FST_VT_VCD_REALTIME:
+ case FST_VT_GEN_STRING:
+ case FST_VT_SV_BIT:
+ case FST_VT_SV_LOGIC:
+ case FST_VT_SV_INT:
+ case FST_VT_SV_SHORTINT:
+ case FST_VT_SV_LONGINT:
+ case FST_VT_SV_BYTE:
+ case FST_VT_SV_ENUM:
+ case FST_VT_SV_SHORTREAL:
+ vartype = tag;
+ /* vardir = */ fgetc(xc->fh); /* unused in VCD reader, but need to advance read pointer */
+ pnt = str;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* varname */
+ *pnt = 0;
+ len = fstReaderVarint32(xc->fh);
+ alias = fstReaderVarint32(xc->fh);
+
+ if (!alias) {
+ if (xc->maxhandle == num_signal_dyn) {
+ num_signal_dyn *= 2;
+ xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, num_signal_dyn * sizeof(uint32_t));
+ xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, num_signal_dyn * sizeof(unsigned char));
+ }
+ xc->signal_lens[xc->maxhandle] = len;
+ xc->signal_typs[xc->maxhandle] = vartype;
+
+ /* maxvalpos+=len; */
+ if (len > xc->longest_signal_value_len) {
+ xc->longest_signal_value_len = len;
+ }
+
+ if ((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) ||
+ (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) {
+ len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32;
+ xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL;
+ }
+ if (fv) {
+ char vcdid_buf[16];
+ uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3);
+ fstVcdID(vcdid_buf, xc->maxhandle + 1);
+ fprintf(fv, "$var %s %" PRIu32 " %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str);
+ }
+ xc->maxhandle++;
+ } else {
+ if ((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) ||
+ (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) {
+ len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32;
+ xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL;
+ }
+ if (fv) {
+ char vcdid_buf[16];
+ uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3);
+ fstVcdID(vcdid_buf, alias);
+ fprintf(fv, "$var %s %" PRIu32 " %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str);
+ }
+ xc->num_alias++;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (fv)
+ fprintf(fv, "$enddefinitions $end\n");
+
+ maxhandle_scanbuild = xc->maxhandle ? xc->maxhandle
+ : 1; /*scan-build warning suppression, in reality we have at least one signal */
+
+ xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, maxhandle_scanbuild * sizeof(uint32_t));
+ xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, maxhandle_scanbuild * sizeof(unsigned char));
+
+ free(xc->process_mask);
+ xc->process_mask = (unsigned char *)calloc(1, (maxhandle_scanbuild + 7) / 8);
+
+ free(xc->temp_signal_value_buf);
+ xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1);
+
+ xc->var_count = xc->maxhandle + xc->num_alias;
+
+ free(str);
+ return (1);
+}
+
+/*
+ * reader file open/close functions
+ */
+int fstReaderInit(struct fstReaderContext *xc)
+{
+ fst_off_t blkpos = 0;
+ fst_off_t endfile;
+ uint64_t seclen;
+ int sectype;
+ uint64_t vc_section_count_actual = 0;
+ int hdr_incomplete = 0;
+ int hdr_seen = 0;
+ int gzread_pass_status = 1;
+
+ sectype = fgetc(xc->f);
+ if (sectype == FST_BL_ZWRAPPER) {
+ FILE *fcomp;
+ fst_off_t offpnt, uclen;
+ char gz_membuf[FST_GZIO_LEN];
+ gzFile zhandle;
+ int zfd;
+ int flen = strlen(xc->filename);
+ char *hf;
+
+ seclen = fstReaderUint64(xc->f);
+ uclen = fstReaderUint64(xc->f);
+
+ if (!seclen)
+ return (0); /* not finished compressing, this is a failed read */
+
+ hf = (char *)calloc(1, flen + 16 + 32 + 1);
+
+ sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc);
+ fcomp = fopen(hf, "w+b");
+ if (!fcomp) {
+ fcomp = tmpfile_open(&xc->f_nam);
+ free(hf);
+ hf = NULL;
+ if (!fcomp) {
+ tmpfile_close(&fcomp, &xc->f_nam);
+ return (0);
+ }
+ }
+
+#if defined(FST_MACOSX)
+ setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
+#endif
+
+#ifdef __MINGW32__
+ setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
+ xc->filename_unpacked = hf;
+#else
+ if (hf) {
+ unlink(hf);
+ free(hf);
+ }
+#endif
+
+ fstReaderFseeko(xc, xc->f, 1 + 8 + 8, SEEK_SET);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+
+ zfd = dup(fileno(xc->f));
+ zhandle = gzdopen(zfd, "rb");
+ if (zhandle) {
+ for (offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) {
+ size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
+ size_t gzreadlen = gzread(zhandle, gz_membuf, this_len);
+ size_t fwlen;
+
+ if (gzreadlen != this_len) {
+ gzread_pass_status = 0;
+ break;
+ }
+ fwlen = fstFwrite(gz_membuf, this_len, 1, fcomp);
+ if (fwlen != 1) {
+ gzread_pass_status = 0;
+ break;
+ }
+ }
+ gzclose(zhandle);
+ } else {
+ close(zfd);
+ }
+ fflush(fcomp);
+ fclose(xc->f);
+ xc->f = fcomp;
+ }
+
+ if (gzread_pass_status) {
+ fstReaderFseeko(xc, xc->f, 0, SEEK_END);
+ endfile = ftello(xc->f);
+
+ while (blkpos < endfile) {
+ fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ if (sectype == EOF) {
+ break;
+ }
+
+ if ((hdr_incomplete) && (!seclen)) {
+ break;
+ }
+
+ if (!hdr_seen && (sectype != FST_BL_HDR)) {
+ break;
+ }
+
+ blkpos++;
+ if (sectype == FST_BL_HDR) {
+ if (!hdr_seen) {
+ int ch;
+ double dcheck;
+
+ xc->start_time = fstReaderUint64(xc->f);
+ xc->end_time = fstReaderUint64(xc->f);
+
+ hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0);
+
+ fstFread(&dcheck, 8, 1, xc->f);
+ xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST);
+ if (!xc->double_endian_match) {
+ union
+ {
+ unsigned char rvs_buf[8];
+ double d;
+ } vu;
+
+ unsigned char *dcheck_alias = (unsigned char *)&dcheck;
+ int rvs_idx;
+
+ for (rvs_idx = 0; rvs_idx < 8; rvs_idx++) {
+ vu.rvs_buf[rvs_idx] = dcheck_alias[7 - rvs_idx];
+ }
+ if (vu.d != FST_DOUBLE_ENDTEST) {
+ break; /* either corrupt file or wrong architecture (offset +33 also functions as matchword)
+ */
+ }
+ }
+
+ hdr_seen = 1;
+
+ xc->mem_used_by_writer = fstReaderUint64(xc->f);
+ xc->scope_count = fstReaderUint64(xc->f);
+ xc->var_count = fstReaderUint64(xc->f);
+ xc->maxhandle = fstReaderUint64(xc->f);
+ xc->num_alias = xc->var_count - xc->maxhandle;
+ xc->vc_section_count = fstReaderUint64(xc->f);
+ ch = fgetc(xc->f);
+ xc->timescale = (signed char)ch;
+ fstFread(xc->version, FST_HDR_SIM_VERSION_SIZE, 1, xc->f);
+ xc->version[FST_HDR_SIM_VERSION_SIZE] = 0;
+ fstFread(xc->date, FST_HDR_DATE_SIZE, 1, xc->f);
+ xc->date[FST_HDR_DATE_SIZE] = 0;
+ ch = fgetc(xc->f);
+ xc->filetype = (unsigned char)ch;
+ xc->timezero = fstReaderUint64(xc->f);
+ }
+ } else if ((sectype == FST_BL_VCDATA) || (sectype == FST_BL_VCDATA_DYN_ALIAS) ||
+ (sectype == FST_BL_VCDATA_DYN_ALIAS2)) {
+ if (hdr_incomplete) {
+ uint64_t bt = fstReaderUint64(xc->f);
+ xc->end_time = fstReaderUint64(xc->f);
+
+ if (!vc_section_count_actual) {
+ xc->start_time = bt;
+ }
+ }
+
+ vc_section_count_actual++;
+ } else if (sectype == FST_BL_GEOM) {
+ if (!hdr_incomplete) {
+ uint64_t clen = seclen - 24;
+ uint64_t uclen = fstReaderUint64(xc->f);
+ unsigned char *ucdata = (unsigned char *)malloc(uclen);
+ unsigned char *pnt = ucdata;
+ unsigned int i;
+
+ xc->contains_geom_section = 1;
+ xc->maxhandle = fstReaderUint64(xc->f);
+ xc->longest_signal_value_len =
+ 32; /* arbitrarily set at 32...this is much longer than an expanded double */
+
+ free(xc->process_mask);
+ xc->process_mask = (unsigned char *)calloc(1, (xc->maxhandle + 7) / 8);
+
+ if (clen != uclen) {
+ unsigned char *cdata = (unsigned char *)malloc(clen);
+ unsigned long destlen = uclen;
+ unsigned long sourcelen = clen;
+ int rc;
+
+ fstFread(cdata, clen, 1, xc->f);
+ rc = uncompress(ucdata, &destlen, cdata, sourcelen);
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderInit(), geom uncompress rc = %d, exiting.\n", rc);
+ exit(255);
+ }
+
+ free(cdata);
+ } else {
+ fstFread(ucdata, uclen, 1, xc->f);
+ }
+
+ free(xc->signal_lens);
+ xc->signal_lens = (uint32_t *)malloc(sizeof(uint32_t) * xc->maxhandle);
+ free(xc->signal_typs);
+ xc->signal_typs = (unsigned char *)malloc(sizeof(unsigned char) * xc->maxhandle);
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ int skiplen;
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ pnt += skiplen;
+
+ if (val) {
+ xc->signal_lens[i] = (val != 0xFFFFFFFF) ? val : 0;
+ xc->signal_typs[i] = FST_VT_VCD_WIRE;
+ if (xc->signal_lens[i] > xc->longest_signal_value_len) {
+ xc->longest_signal_value_len = xc->signal_lens[i];
+ }
+ } else {
+ xc->signal_lens[i] = 8; /* backpatch in real */
+ xc->signal_typs[i] = FST_VT_VCD_REAL;
+ /* xc->longest_signal_value_len handled above by overly large init size */
+ }
+ }
+
+ free(xc->temp_signal_value_buf);
+ xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1);
+
+ free(ucdata);
+ }
+ } else if (sectype == FST_BL_HIER) {
+ xc->contains_hier_section = 1;
+ xc->hier_pos = ftello(xc->f);
+ } else if (sectype == FST_BL_HIER_LZ4DUO) {
+ xc->contains_hier_section_lz4 = 1;
+ xc->contains_hier_section_lz4duo = 1;
+ xc->hier_pos = ftello(xc->f);
+ } else if (sectype == FST_BL_HIER_LZ4) {
+ xc->contains_hier_section_lz4 = 1;
+ xc->hier_pos = ftello(xc->f);
+ } else if (sectype == FST_BL_BLACKOUT) {
+ uint32_t i;
+ uint64_t cur_bl = 0;
+ uint64_t delta;
+
+ xc->num_blackouts = fstReaderVarint32(xc->f);
+ free(xc->blackout_times);
+ xc->blackout_times = (uint64_t *)calloc(xc->num_blackouts, sizeof(uint64_t));
+ free(xc->blackout_activity);
+ xc->blackout_activity = (unsigned char *)calloc(xc->num_blackouts, sizeof(unsigned char));
+
+ for (i = 0; i < xc->num_blackouts; i++) {
+ xc->blackout_activity[i] = fgetc(xc->f) != 0;
+ delta = fstReaderVarint64(xc->f);
+ cur_bl += delta;
+ xc->blackout_times[i] = cur_bl;
+ }
+ }
+
+ blkpos += seclen;
+ if (!hdr_seen)
+ break;
+ }
+
+ if (hdr_seen) {
+ if (xc->vc_section_count != vc_section_count_actual) {
+ xc->vc_section_count = vc_section_count_actual;
+ }
+
+ if (!xc->contains_geom_section) {
+ fstReaderProcessHier(xc, NULL); /* recreate signal_lens/signal_typs info */
+ }
+ }
+ }
+
+ return (hdr_seen);
+}
+
+void *fstReaderOpenForUtilitiesOnly(void)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
+
+ return (xc);
+}
+
+void *fstReaderOpen(const char *nam)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
+
+ if ((!nam) || (!(xc->f = fopen(nam, "rb")))) {
+ free(xc);
+ xc = NULL;
+ } else {
+ int flen = strlen(nam);
+ char *hf = (char *)calloc(1, flen + 6);
+ int rc;
+
+#if defined(__MINGW32__) || defined(FST_MACOSX)
+ setvbuf(xc->f, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
+#endif
+
+ memcpy(hf, nam, flen);
+ strcpy(hf + flen, ".hier");
+ xc->fh = fopen(hf, "rb");
+
+ free(hf);
+ xc->filename = strdup(nam);
+ rc = fstReaderInit(xc);
+
+ if ((rc) && (xc->vc_section_count) && (xc->maxhandle) &&
+ ((xc->fh) || (xc->contains_hier_section || (xc->contains_hier_section_lz4)))) {
+ /* more init */
+ xc->do_rewind = 1;
+ } else {
+ fstReaderClose(xc);
+ xc = NULL;
+ }
+ }
+
+ return (xc);
+}
+
+static void fstReaderDeallocateRvatData(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ free(xc->rvat_chain_mem);
+ xc->rvat_chain_mem = NULL;
+ free(xc->rvat_frame_data);
+ xc->rvat_frame_data = NULL;
+ free(xc->rvat_time_table);
+ xc->rvat_time_table = NULL;
+ free(xc->rvat_chain_table);
+ xc->rvat_chain_table = NULL;
+ free(xc->rvat_chain_table_lengths);
+ xc->rvat_chain_table_lengths = NULL;
+
+ xc->rvat_data_valid = 0;
+ }
+}
+
+void fstReaderClose(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ fstReaderDeallocateScopeData(xc);
+ fstReaderDeallocateRvatData(xc);
+ free(xc->rvat_sig_offs);
+ xc->rvat_sig_offs = NULL;
+
+ free(xc->process_mask);
+ xc->process_mask = NULL;
+ free(xc->blackout_times);
+ xc->blackout_times = NULL;
+ free(xc->blackout_activity);
+ xc->blackout_activity = NULL;
+ free(xc->temp_signal_value_buf);
+ xc->temp_signal_value_buf = NULL;
+ free(xc->signal_typs);
+ xc->signal_typs = NULL;
+ free(xc->signal_lens);
+ xc->signal_lens = NULL;
+ free(xc->filename);
+ xc->filename = NULL;
+
+ if (xc->fh) {
+ tmpfile_close(&xc->fh, &xc->fh_nam);
+ }
+
+ if (xc->f) {
+ tmpfile_close(&xc->f, &xc->f_nam);
+ if (xc->filename_unpacked) {
+ unlink(xc->filename_unpacked);
+ free(xc->filename_unpacked);
+ }
+ }
+
+ free(xc);
+ }
+}
+
+/*
+ * read processing
+ */
+
+/* normal read which re-interleaves the value change data */
+int fstReaderIterBlocks(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx,
+ const unsigned char *value),
+ void *user_callback_data_pointer, FILE *fv)
+{
+ return (fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data_pointer, fv));
+}
+
+int fstReaderIterBlocks2(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value),
+ void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value,
+ uint32_t len),
+ void *user_callback_data_pointer, FILE *fv)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ uint64_t previous_time = UINT64_MAX;
+ uint64_t *time_table = NULL;
+ uint64_t tsec_nitems;
+ unsigned int secnum = 0;
+ int blocks_skipped = 0;
+ fst_off_t blkpos = 0;
+ uint64_t seclen, beg_tim;
+ uint64_t end_tim;
+ uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle;
+ fst_off_t vc_start;
+ fst_off_t indx_pntr, indx_pos;
+ fst_off_t *chain_table = NULL;
+ uint32_t *chain_table_lengths = NULL;
+ unsigned char *chain_cmem;
+ unsigned char *pnt;
+ long chain_clen;
+ fstHandle idx, pidx = 0, i;
+ uint64_t pval;
+ uint64_t vc_maxhandle_largest = 0;
+ uint64_t tsec_uclen = 0, tsec_clen = 0;
+ int sectype;
+ uint64_t mem_required_for_traversal;
+ unsigned char *mem_for_traversal = NULL;
+ uint32_t traversal_mem_offs;
+ uint32_t *scatterptr, *headptr, *length_remaining;
+ uint32_t cur_blackout = 0;
+ int packtype;
+ unsigned char *mc_mem = NULL;
+ uint32_t mc_mem_len; /* corresponds to largest value encountered in chain_table_lengths[i] */
+ int dumpvars_state = 0;
+
+ if (!xc)
+ return (0);
+
+ scatterptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+ headptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+ length_remaining = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+
+ if (fv) {
+#ifndef FST_WRITEX_DISABLE
+ fflush(fv);
+ setvbuf(fv, (char *)NULL, _IONBF,
+ 0); /* even buffered IO is slow so disable it and use our own routines that don't need seeking */
+ xc->writex_fd = fileno(fv);
+#endif
+ }
+
+ for (;;) {
+ uint32_t *tc_head = NULL;
+ traversal_mem_offs = 0;
+
+ fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ if ((sectype == EOF) || (sectype == FST_BL_SKIP)) {
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "<< EOF >>\n");
+#endif
+ break;
+ }
+
+ blkpos++;
+ if ((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) &&
+ (sectype != FST_BL_VCDATA_DYN_ALIAS2)) {
+ blkpos += seclen;
+ continue;
+ }
+
+ if (!seclen)
+ break;
+
+ beg_tim = fstReaderUint64(xc->f);
+ end_tim = fstReaderUint64(xc->f);
+
+ if (xc->limit_range_valid) {
+ if (end_tim < xc->limit_range_start) {
+ blocks_skipped++;
+ blkpos += seclen;
+ continue;
+ }
+
+ if (beg_tim >
+ xc->limit_range_end) /* likely the compare in for(i=0;i<tsec_nitems;i++) below would do this earlier */
+ {
+ break;
+ }
+ }
+
+ mem_required_for_traversal = fstReaderUint64(xc->f);
+ mem_for_traversal =
+ (unsigned char *)malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim,
+ (int)end_tim);
+ fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
+#endif
+ /* process time block */
+ {
+ unsigned char *ucdata;
+ unsigned char *cdata;
+ unsigned long destlen /* = tsec_uclen */; /* scan-build */
+ unsigned long sourcelen /*= tsec_clen */; /* scan-build */
+ int rc;
+ unsigned char *tpnt;
+ uint64_t tpval;
+ unsigned int ti;
+
+ if (fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET) != 0)
+ break;
+ tsec_uclen = fstReaderUint64(xc->f);
+ tsec_clen = fstReaderUint64(xc->f);
+ tsec_nitems = fstReaderUint64(xc->f);
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen,
+ (int)tsec_nitems);
+#endif
+ if (tsec_clen > seclen)
+ break; /* corrupted tsec_clen: by definition it can't be larger than size of section */
+ ucdata = (unsigned char *)malloc(tsec_uclen);
+ if (!ucdata)
+ break; /* malloc fail as tsec_uclen out of range from corrupted file */
+ destlen = tsec_uclen;
+ sourcelen = tsec_clen;
+
+ fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR);
+
+ if (tsec_uclen != tsec_clen) {
+ cdata = (unsigned char *)malloc(tsec_clen);
+ fstFread(cdata, tsec_clen, 1, xc->f);
+
+ rc = uncompress(ucdata, &destlen, cdata, sourcelen);
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc);
+ exit(255);
+ }
+
+ free(cdata);
+ } else {
+ fstFread(ucdata, tsec_uclen, 1, xc->f);
+ }
+
+ free(time_table);
+ time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t));
+ tpnt = ucdata;
+ tpval = 0;
+ for (ti = 0; ti < tsec_nitems; ti++) {
+ int skiplen;
+ uint64_t val = fstGetVarint64(tpnt, &skiplen);
+ tpval = time_table[ti] = tpval + val;
+ tpnt += skiplen;
+ }
+
+ tc_head = (uint32_t *)calloc(tsec_nitems /* scan-build */ ? tsec_nitems : 1, sizeof(uint32_t));
+ free(ucdata);
+ }
+
+ fstReaderFseeko(xc, xc->f, blkpos + 32, SEEK_SET);
+
+ frame_uclen = fstReaderVarint64(xc->f);
+ frame_clen = fstReaderVarint64(xc->f);
+ frame_maxhandle = fstReaderVarint64(xc->f);
+
+ if (secnum == 0) {
+ if ((beg_tim != time_table[0]) || (blocks_skipped)) {
+ unsigned char *mu = (unsigned char *)malloc(frame_uclen);
+ uint32_t sig_offs = 0;
+
+ if (fv) {
+ char wx_buf[32];
+ int wx_len;
+
+ if (beg_tim) {
+ if (dumpvars_state == 1) {
+ wx_len = sprintf(wx_buf, "$end\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 2;
+ }
+ wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", beg_tim);
+ fstWritex(xc, wx_buf, wx_len);
+ if (!dumpvars_state) {
+ wx_len = sprintf(wx_buf, "$dumpvars\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 1;
+ }
+ }
+ if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) {
+ if (beg_tim == xc->blackout_times[cur_blackout]) {
+ wx_len = sprintf(wx_buf, "$dump%s $end\n",
+ (xc->blackout_activity[cur_blackout++]) ? "on" : "off");
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ }
+
+ if (frame_uclen == frame_clen) {
+ fstFread(mu, frame_uclen, 1, xc->f);
+ } else {
+ unsigned char *mc = (unsigned char *)malloc(frame_clen);
+ int rc;
+
+ unsigned long destlen = frame_uclen;
+ unsigned long sourcelen = frame_clen;
+
+ fstFread(mc, sourcelen, 1, xc->f);
+ rc = uncompress(mu, &destlen, mc, sourcelen);
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", rc);
+ exit(255);
+ }
+ free(mc);
+ }
+
+ for (idx = 0; idx < frame_maxhandle; idx++) {
+ int process_idx = idx / 8;
+ int process_bit = idx & 7;
+
+ if (xc->process_mask[process_idx] & (1 << process_bit)) {
+ if (xc->signal_lens[idx] <= 1) {
+ if (xc->signal_lens[idx] == 1) {
+ unsigned char val = mu[sig_offs];
+ if (value_change_callback) {
+ xc->temp_signal_value_buf[0] = val;
+ xc->temp_signal_value_buf[1] = 0;
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+ vcd_id[0] = val; /* collapse 3 writes into one I/O call */
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ } else {
+ /* variable-length ("0" length) records have no initial state */
+ }
+ } else {
+ if (xc->signal_typs[idx] != FST_VT_VCD_REAL) {
+ if (value_change_callback) {
+ memcpy(xc->temp_signal_value_buf, mu + sig_offs, xc->signal_lens[idx]);
+ xc->temp_signal_value_buf[xc->signal_lens[idx]] = 0;
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+
+ vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p';
+ fstWritex(xc, vcd_id, 1);
+ fstWritex(xc, mu + sig_offs, xc->signal_lens[idx]);
+
+ vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ } else {
+ double d;
+ unsigned char *clone_d;
+ unsigned char *srcdata = mu + sig_offs;
+
+ if (value_change_callback) {
+ if (xc->native_doubles_for_cb) {
+ if (xc->double_endian_match) {
+ clone_d = srcdata;
+ } else {
+ int j;
+
+ clone_d = (unsigned char *)&d;
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1, clone_d);
+ } else {
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ sprintf((char *)xc->temp_signal_value_buf, "%.16g", d);
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
+ xc->temp_signal_value_buf);
+ }
+ } else {
+ if (fv) {
+ char vcdid_buf[16];
+ char wx_buf[64];
+ int wx_len;
+
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ fstVcdID(vcdid_buf, idx + 1);
+ wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf);
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ }
+ }
+ }
+
+ sig_offs += xc->signal_lens[idx];
+ }
+
+ free(mu);
+ fstReaderFseeko(xc, xc->f, -((fst_off_t)frame_clen), SEEK_CUR);
+ }
+ }
+
+ fstReaderFseeko(xc, xc->f, (fst_off_t)frame_clen, SEEK_CUR); /* skip past compressed data */
+
+ vc_maxhandle = fstReaderVarint64(xc->f);
+ vc_start = ftello(xc->f); /* points to '!' character */
+ packtype = fgetc(xc->f);
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen,
+ (int)frame_clen, (int)frame_maxhandle);
+ fprintf(stderr, FST_APIMESS "vc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype);
+#endif
+
+ indx_pntr = blkpos + seclen - 24 - tsec_clen - 8;
+ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET);
+ chain_clen = fstReaderUint64(xc->f);
+ indx_pos = indx_pntr - chain_clen;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
+#endif
+ chain_cmem = (unsigned char *)malloc(chain_clen);
+ if (!chain_cmem)
+ goto block_err;
+ fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET);
+ fstFread(chain_cmem, chain_clen, 1, xc->f);
+
+ if (vc_maxhandle > vc_maxhandle_largest) {
+ free(chain_table);
+ free(chain_table_lengths);
+
+ vc_maxhandle_largest = vc_maxhandle;
+ chain_table = (fst_off_t *)calloc((vc_maxhandle + 1), sizeof(fst_off_t));
+ chain_table_lengths = (uint32_t *)calloc((vc_maxhandle + 1), sizeof(uint32_t));
+ }
+
+ if (!chain_table || !chain_table_lengths)
+ goto block_err;
+
+ pnt = chain_cmem;
+ idx = 0;
+ pval = 0;
+
+ if (sectype == FST_BL_VCDATA_DYN_ALIAS2) {
+ uint32_t prev_alias = 0;
+
+ do {
+ int skiplen;
+
+ if (*pnt & 0x01) {
+ int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1;
+ if (shval > 0) {
+ pval = chain_table[idx] = pval + shval;
+ if (idx) {
+ chain_table_lengths[pidx] = pval - chain_table[pidx];
+ }
+ pidx = idx++;
+ } else if (shval < 0) {
+ chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ chain_table_lengths[idx] = prev_alias =
+ shval; /* because during this loop iter would give stale data! */
+ idx++;
+ } else {
+ chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ chain_table_lengths[idx] =
+ prev_alias; /* because during this loop iter would give stale data! */
+ idx++;
+ }
+ } else {
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ } else {
+ do {
+ int skiplen;
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ if (!val) {
+ pnt += skiplen;
+ val = fstGetVarint32(pnt, &skiplen);
+ chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ chain_table_lengths[idx] = -val; /* because during this loop iter would give stale data! */
+ idx++;
+ } else if (val & 1) {
+ pval = chain_table[idx] = pval + (val >> 1);
+ if (idx) {
+ chain_table_lengths[pidx] = pval - chain_table[pidx];
+ }
+ pidx = idx++;
+ } else {
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ }
+
+ chain_table[idx] = indx_pos - vc_start;
+ chain_table_lengths[pidx] = chain_table[idx] - chain_table[pidx];
+
+ for (i = 0; i < idx; i++) {
+ int32_t v32 = chain_table_lengths[i];
+ if ((v32 < 0) && (!chain_table[i])) {
+ v32 = -v32;
+ v32--;
+ if (((uint32_t)v32) < i) /* sanity check */
+ {
+ chain_table[i] = chain_table[v32];
+ chain_table_lengths[i] = chain_table_lengths[v32];
+ }
+ }
+ }
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "decompressed chain idx len: %" PRIu32 "\n", idx);
+#endif
+
+ mc_mem_len = 16384;
+ mc_mem = (unsigned char *)malloc(mc_mem_len); /* buffer for compressed reads */
+
+ /* check compressed VC data */
+ if (idx > xc->maxhandle)
+ idx = xc->maxhandle;
+ for (i = 0; i < idx; i++) {
+ if (chain_table[i]) {
+ int process_idx = i / 8;
+ int process_bit = i & 7;
+
+ if (xc->process_mask[process_idx] & (1 << process_bit)) {
+ int rc = Z_OK;
+ uint32_t val;
+ uint32_t skiplen;
+ uint32_t tdelta;
+
+ fstReaderFseeko(xc, xc->f, vc_start + chain_table[i], SEEK_SET);
+ val = fstReaderVarint32WithSkip(xc->f, &skiplen);
+ if (val) {
+ unsigned char *mu = mem_for_traversal + traversal_mem_offs; /* uncomp: dst */
+ unsigned char *mc; /* comp: src */
+ unsigned long destlen = val;
+ unsigned long sourcelen = chain_table_lengths[i];
+
+ if (mc_mem_len < chain_table_lengths[i]) {
+ free(mc_mem);
+ mc_mem = (unsigned char *)malloc(mc_mem_len = chain_table_lengths[i]);
+ }
+ mc = mc_mem;
+
+ fstFread(mc, chain_table_lengths[i], 1, xc->f);
+
+ switch (packtype) {
+ case '4':
+ rc = (destlen == (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu,
+ sourcelen, destlen, destlen))
+ ? Z_OK
+ : Z_DATA_ERROR;
+ break;
+ case 'F':
+ fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */
+ break;
+ default:
+ rc = uncompress(mu, &destlen, mc, sourcelen);
+ break;
+ }
+
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ headptr[i] = traversal_mem_offs;
+ length_remaining[i] = val;
+ traversal_mem_offs += val;
+ } else {
+ int destlen = chain_table_lengths[i] - skiplen;
+ unsigned char *mu = mem_for_traversal + traversal_mem_offs;
+ fstFread(mu, destlen, 1, xc->f);
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ headptr[i] = traversal_mem_offs;
+ length_remaining[i] = destlen;
+ traversal_mem_offs += destlen;
+ }
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), fac: %d clen: %d (rc=%d), exiting.\n",
+ (int)i, (int)val, rc);
+ exit(255);
+ }
+
+ if (xc->signal_lens[i] == 1) {
+ uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]);
+ uint32_t shcnt = 2 << (vli & 1);
+ tdelta = vli >> shcnt;
+ } else {
+ uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]);
+ tdelta = vli >> 1;
+ }
+
+ scatterptr[i] = tc_head[tdelta];
+ tc_head[tdelta] = i + 1;
+ }
+ }
+ }
+
+ free(mc_mem); /* there is no usage below for this, no real need to clear out mc_mem or mc_mem_len */
+
+ for (i = 0; i < tsec_nitems; i++) {
+ uint32_t tdelta;
+ int skiplen, skiplen2;
+ uint32_t vli;
+
+ if (fv) {
+ char wx_buf[32];
+ int wx_len;
+
+ if (time_table[i] != previous_time) {
+ if (xc->limit_range_valid) {
+ if (time_table[i] > xc->limit_range_end) {
+ break;
+ }
+ }
+
+ if (dumpvars_state == 1) {
+ wx_len = sprintf(wx_buf, "$end\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 2;
+ }
+ wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", time_table[i]);
+ fstWritex(xc, wx_buf, wx_len);
+ if (!dumpvars_state) {
+ wx_len = sprintf(wx_buf, "$dumpvars\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 1;
+ }
+
+ if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) {
+ if (time_table[i] == xc->blackout_times[cur_blackout]) {
+ wx_len = sprintf(wx_buf, "$dump%s $end\n",
+ (xc->blackout_activity[cur_blackout++]) ? "on" : "off");
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ previous_time = time_table[i];
+ }
+ } else {
+ if (time_table[i] != previous_time) {
+ if (xc->limit_range_valid) {
+ if (time_table[i] > xc->limit_range_end) {
+ break;
+ }
+ }
+ previous_time = time_table[i];
+ }
+ }
+
+ while (tc_head[i]) {
+ idx = tc_head[i] - 1;
+ vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
+
+ if (xc->signal_lens[idx] <= 1) {
+ if (xc->signal_lens[idx] == 1) {
+ unsigned char val;
+ if (!(vli & 1)) {
+ /* tdelta = vli >> 2; */ /* scan-build */
+ val = ((vli >> 1) & 1) | '0';
+ } else {
+ /* tdelta = vli >> 4; */ /* scan-build */
+ val = FST_RCV_STR[((vli >> 1) & 7)];
+ }
+
+ if (value_change_callback) {
+ xc->temp_signal_value_buf[0] = val;
+ xc->temp_signal_value_buf[1] = 0;
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+
+ vcd_id[0] = val;
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ headptr[idx] += skiplen;
+ length_remaining[idx] -= skiplen;
+
+ tc_head[i] = scatterptr[idx];
+ scatterptr[idx] = 0;
+
+ if (length_remaining[idx]) {
+ int shamt;
+ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]);
+ shamt = 2 << (vli & 1);
+ tdelta = vli >> shamt;
+
+ scatterptr[idx] = tc_head[i + tdelta];
+ tc_head[i + tdelta] = idx + 1;
+ }
+ } else {
+ unsigned char *vdata;
+ uint32_t len;
+
+ vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
+ len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2);
+ /* tdelta = vli >> 1; */ /* scan-build */
+ skiplen += skiplen2;
+ vdata = mem_for_traversal + headptr[idx] + skiplen;
+
+ if (!(vli & 1)) {
+ if (value_change_callback_varlen) {
+ value_change_callback_varlen(user_callback_data_pointer, time_table[i], idx + 1, vdata,
+ len);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len;
+
+ vcd_id[0] = 's';
+ fstWritex(xc, vcd_id, 1);
+
+ vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+ {
+ unsigned char *vesc = (unsigned char *)malloc(len * 4 + 1);
+ int vlen = fstUtilityBinToEsc(vesc, vdata, len);
+ fstWritex(xc, vesc, vlen);
+ free(vesc);
+ }
+
+ vcd_id[0] = ' ';
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ }
+
+ skiplen += len;
+ headptr[idx] += skiplen;
+ length_remaining[idx] -= skiplen;
+
+ tc_head[i] = scatterptr[idx];
+ scatterptr[idx] = 0;
+
+ if (length_remaining[idx]) {
+ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]);
+ tdelta = vli >> 1;
+
+ scatterptr[idx] = tc_head[i + tdelta];
+ tc_head[i + tdelta] = idx + 1;
+ }
+ }
+ } else {
+ uint32_t len = xc->signal_lens[idx];
+ unsigned char *vdata;
+
+ vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
+ /* tdelta = vli >> 1; */ /* scan-build */
+ vdata = mem_for_traversal + headptr[idx] + skiplen;
+
+ if (xc->signal_typs[idx] != FST_VT_VCD_REAL) {
+ if (!(vli & 1)) {
+ int byte = 0;
+ int bit;
+ unsigned int j;
+
+ for (j = 0; j < len; j++) {
+ unsigned char ch;
+ byte = j / 8;
+ bit = 7 - (j & 7);
+ ch = ((vdata[byte] >> bit) & 1) | '0';
+ xc->temp_signal_value_buf[j] = ch;
+ }
+ xc->temp_signal_value_buf[j] = 0;
+
+ if (value_change_callback) {
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p';
+
+ fstWritex(xc, &ch_bp, 1);
+ fstWritex(xc, xc->temp_signal_value_buf, len);
+ }
+ }
+
+ len = byte + 1;
+ } else {
+ if (value_change_callback) {
+ memcpy(xc->temp_signal_value_buf, vdata, len);
+ xc->temp_signal_value_buf[len] = 0;
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p';
+
+ fstWritex(xc, &ch_bp, 1);
+ fstWritex(xc, vdata, len);
+ }
+ }
+ }
+ } else {
+ double d;
+ unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */
+ unsigned char buf[8];
+ unsigned char *srcdata;
+
+ if (!(vli & 1)) /* very rare case, but possible */
+ {
+ int bit;
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ unsigned char ch;
+ bit = 7 - (j & 7);
+ ch = ((vdata[0] >> bit) & 1) | '0';
+ buf[j] = ch;
+ }
+
+ len = 1;
+ srcdata = buf;
+ } else {
+ srcdata = vdata;
+ }
+
+ if (value_change_callback) {
+ if (xc->native_doubles_for_cb) {
+ if (xc->double_endian_match) {
+ clone_d = srcdata;
+ } else {
+ int j;
+
+ clone_d = (unsigned char *)&d;
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1, clone_d);
+ } else {
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ sprintf((char *)xc->temp_signal_value_buf, "%.16g", d);
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ }
+ } else {
+ if (fv) {
+ char wx_buf[32];
+ int wx_len;
+
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ wx_len = sprintf(wx_buf, "r%.16g", d);
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ }
+
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+ vcd_id[0] = ' ';
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+
+ skiplen += len;
+ headptr[idx] += skiplen;
+ length_remaining[idx] -= skiplen;
+
+ tc_head[i] = scatterptr[idx];
+ scatterptr[idx] = 0;
+
+ if (length_remaining[idx]) {
+ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]);
+ tdelta = vli >> 1;
+
+ scatterptr[idx] = tc_head[i + tdelta];
+ tc_head[i + tdelta] = idx + 1;
+ }
+ }
+ }
+ }
+
+ block_err:
+ free(tc_head);
+ free(chain_cmem);
+ free(mem_for_traversal);
+ mem_for_traversal = NULL;
+
+ secnum++;
+ if (secnum == xc->vc_section_count)
+ break; /* in case file is growing, keep with original block count */
+ blkpos += seclen;
+ }
+
+ if (mem_for_traversal)
+ free(mem_for_traversal); /* scan-build */
+ free(length_remaining);
+ free(headptr);
+ free(scatterptr);
+
+ if (chain_table)
+ free(chain_table);
+ if (chain_table_lengths)
+ free(chain_table_lengths);
+
+ free(time_table);
+
+#ifndef FST_WRITEX_DISABLE
+ if (fv) {
+ fstWritex(xc, NULL, 0);
+ }
+#endif
+
+ return (1);
+}
+
+/* rvat functions */
+
+static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle facidx, char *buf)
+{
+ if (facidx >= xc->rvat_frame_maxhandle) {
+ return (NULL);
+ }
+
+ if (xc->signal_lens[facidx] == 1) {
+ buf[0] = (char)xc->rvat_frame_data[xc->rvat_sig_offs[facidx]];
+ buf[1] = 0;
+ } else {
+ if (xc->signal_typs[facidx] != FST_VT_VCD_REAL) {
+ memcpy(buf, xc->rvat_frame_data + xc->rvat_sig_offs[facidx], xc->signal_lens[facidx]);
+ buf[xc->signal_lens[facidx]] = 0;
+ } else {
+ double d;
+ unsigned char *clone_d = (unsigned char *)&d;
+ unsigned char *srcdata = xc->rvat_frame_data + xc->rvat_sig_offs[facidx];
+
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ sprintf((char *)buf, "%.16g", d);
+ }
+ }
+
+ return (buf);
+}
+
+char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ fst_off_t blkpos = 0, prev_blkpos;
+ uint64_t beg_tim, end_tim, beg_tim2, end_tim2;
+ int sectype;
+ unsigned int secnum = 0;
+ uint64_t seclen;
+ uint64_t tsec_uclen = 0, tsec_clen = 0;
+ uint64_t tsec_nitems;
+ uint64_t frame_uclen, frame_clen;
+#ifdef FST_DEBUG
+ uint64_t mem_required_for_traversal;
+#endif
+ fst_off_t indx_pntr, indx_pos;
+ long chain_clen;
+ unsigned char *chain_cmem;
+ unsigned char *pnt;
+ fstHandle idx, pidx = 0, i;
+ uint64_t pval;
+
+ if ((!xc) || (!facidx) || (facidx > xc->maxhandle) || (!buf) || (!xc->signal_lens[facidx - 1])) {
+ return (NULL);
+ }
+
+ if (!xc->rvat_sig_offs) {
+ uint32_t cur_offs = 0;
+
+ xc->rvat_sig_offs = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+ for (i = 0; i < xc->maxhandle; i++) {
+ xc->rvat_sig_offs[i] = cur_offs;
+ cur_offs += xc->signal_lens[i];
+ }
+ }
+
+ if (xc->rvat_data_valid) {
+ if ((xc->rvat_beg_tim <= tim) && (tim <= xc->rvat_end_tim)) {
+ goto process_value;
+ }
+
+ fstReaderDeallocateRvatData(xc);
+ }
+
+ xc->rvat_chain_pos_valid = 0;
+
+ for (;;) {
+ fstReaderFseeko(xc, xc->f, (prev_blkpos = blkpos), SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ if ((sectype == EOF) || (sectype == FST_BL_SKIP) || (!seclen)) {
+ return (NULL); /* if this loop exits on break, it's successful */
+ }
+
+ blkpos++;
+ if ((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) &&
+ (sectype != FST_BL_VCDATA_DYN_ALIAS2)) {
+ blkpos += seclen;
+ continue;
+ }
+
+ beg_tim = fstReaderUint64(xc->f);
+ end_tim = fstReaderUint64(xc->f);
+
+ if ((beg_tim <= tim) && (tim <= end_tim)) {
+ if ((tim == end_tim) && (tim != xc->end_time)) {
+ fst_off_t cached_pos = ftello(xc->f);
+ fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ beg_tim2 = fstReaderUint64(xc->f);
+ end_tim2 = fstReaderUint64(xc->f);
+
+ if (((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) &&
+ (sectype != FST_BL_VCDATA_DYN_ALIAS2)) ||
+ (!seclen) || (beg_tim2 != tim)) {
+ blkpos = prev_blkpos;
+ break;
+ }
+ beg_tim = beg_tim2;
+ end_tim = end_tim2;
+ fstReaderFseeko(xc, xc->f, cached_pos, SEEK_SET);
+ }
+ break;
+ }
+
+ blkpos += seclen;
+ secnum++;
+ }
+
+ xc->rvat_beg_tim = beg_tim;
+ xc->rvat_end_tim = end_tim;
+
+#ifdef FST_DEBUG
+ mem_required_for_traversal =
+#endif
+ fstReaderUint64(xc->f);
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "rvat sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim,
+ (int)end_tim);
+ fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
+#endif
+
+ /* process time block */
+ {
+ unsigned char *ucdata;
+ unsigned char *cdata;
+ unsigned long destlen /* = tsec_uclen */; /* scan-build */
+ unsigned long sourcelen /* = tsec_clen */; /* scan-build */
+ int rc;
+ unsigned char *tpnt;
+ uint64_t tpval;
+ unsigned int ti;
+
+ fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET);
+ tsec_uclen = fstReaderUint64(xc->f);
+ tsec_clen = fstReaderUint64(xc->f);
+ tsec_nitems = fstReaderUint64(xc->f);
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen,
+ (int)tsec_nitems);
+#endif
+ ucdata = (unsigned char *)malloc(tsec_uclen);
+ destlen = tsec_uclen;
+ sourcelen = tsec_clen;
+
+ fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR);
+ if (tsec_uclen != tsec_clen) {
+ cdata = (unsigned char *)malloc(tsec_clen);
+ fstFread(cdata, tsec_clen, 1, xc->f);
+
+ rc = uncompress(ucdata, &destlen, cdata, sourcelen);
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\n",
+ rc);
+ exit(255);
+ }
+
+ free(cdata);
+ } else {
+ fstFread(ucdata, tsec_uclen, 1, xc->f);
+ }
+
+ xc->rvat_time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t));
+ tpnt = ucdata;
+ tpval = 0;
+ for (ti = 0; ti < tsec_nitems; ti++) {
+ int skiplen;
+ uint64_t val = fstGetVarint64(tpnt, &skiplen);
+ tpval = xc->rvat_time_table[ti] = tpval + val;
+ tpnt += skiplen;
+ }
+
+ free(ucdata);
+ }
+
+ fstReaderFseeko(xc, xc->f, blkpos + 32, SEEK_SET);
+
+ frame_uclen = fstReaderVarint64(xc->f);
+ frame_clen = fstReaderVarint64(xc->f);
+ xc->rvat_frame_maxhandle = fstReaderVarint64(xc->f);
+ xc->rvat_frame_data = (unsigned char *)malloc(frame_uclen);
+
+ if (frame_uclen == frame_clen) {
+ fstFread(xc->rvat_frame_data, frame_uclen, 1, xc->f);
+ } else {
+ unsigned char *mc = (unsigned char *)malloc(frame_clen);
+ int rc;
+
+ unsigned long destlen = frame_uclen;
+ unsigned long sourcelen = frame_clen;
+
+ fstFread(mc, sourcelen, 1, xc->f);
+ rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen);
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc);
+ exit(255);
+ }
+ free(mc);
+ }
+
+ xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f);
+ xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
+ xc->rvat_packtype = fgetc(xc->f);
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen,
+ (int)frame_clen, (int)xc->rvat_frame_maxhandle);
+ fprintf(stderr, FST_APIMESS "vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle);
+#endif
+
+ indx_pntr = blkpos + seclen - 24 - tsec_clen - 8;
+ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET);
+ chain_clen = fstReaderUint64(xc->f);
+ indx_pos = indx_pntr - chain_clen;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
+#endif
+ chain_cmem = (unsigned char *)malloc(chain_clen);
+ fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET);
+ fstFread(chain_cmem, chain_clen, 1, xc->f);
+
+ xc->rvat_chain_table = (fst_off_t *)calloc((xc->rvat_vc_maxhandle + 1), sizeof(fst_off_t));
+ xc->rvat_chain_table_lengths = (uint32_t *)calloc((xc->rvat_vc_maxhandle + 1), sizeof(uint32_t));
+
+ pnt = chain_cmem;
+ idx = 0;
+ pval = 0;
+
+ if (sectype == FST_BL_VCDATA_DYN_ALIAS2) {
+ uint32_t prev_alias = 0;
+
+ do {
+ int skiplen;
+
+ if (*pnt & 0x01) {
+ int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1;
+ if (shval > 0) {
+ pval = xc->rvat_chain_table[idx] = pval + shval;
+ if (idx) {
+ xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx];
+ }
+ pidx = idx++;
+ } else if (shval < 0) {
+ xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ xc->rvat_chain_table_lengths[idx] = prev_alias =
+ shval; /* because during this loop iter would give stale data! */
+ idx++;
+ } else {
+ xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ xc->rvat_chain_table_lengths[idx] =
+ prev_alias; /* because during this loop iter would give stale data! */
+ idx++;
+ }
+ } else {
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ xc->rvat_chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ } else {
+ do {
+ int skiplen;
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ if (!val) {
+ pnt += skiplen;
+ val = fstGetVarint32(pnt, &skiplen);
+ xc->rvat_chain_table[idx] = 0;
+ xc->rvat_chain_table_lengths[idx] = -val;
+ idx++;
+ } else if (val & 1) {
+ pval = xc->rvat_chain_table[idx] = pval + (val >> 1);
+ if (idx) {
+ xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx];
+ }
+ pidx = idx++;
+ } else {
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ xc->rvat_chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ }
+
+ free(chain_cmem);
+ xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start;
+ xc->rvat_chain_table_lengths[pidx] = xc->rvat_chain_table[idx] - xc->rvat_chain_table[pidx];
+
+ for (i = 0; i < idx; i++) {
+ int32_t v32 = xc->rvat_chain_table_lengths[i];
+ if ((v32 < 0) && (!xc->rvat_chain_table[i])) {
+ v32 = -v32;
+ v32--;
+ if (((uint32_t)v32) < i) /* sanity check */
+ {
+ xc->rvat_chain_table[i] = xc->rvat_chain_table[v32];
+ xc->rvat_chain_table_lengths[i] = xc->rvat_chain_table_lengths[v32];
+ }
+ }
+ }
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "decompressed chain idx len: %" PRIu32 "\n", idx);
+#endif
+
+ xc->rvat_data_valid = 1;
+
+/* all data at this point is loaded or resident in fst cache, process and return appropriate value */
+process_value:
+ if (facidx > xc->rvat_vc_maxhandle) {
+ return (NULL);
+ }
+
+ facidx--; /* scale down for array which starts at zero */
+
+ if (((tim == xc->rvat_beg_tim) && (!xc->rvat_chain_table[facidx])) || (!xc->rvat_chain_table[facidx])) {
+ return (fstExtractRvatDataFromFrame(xc, facidx, buf));
+ }
+
+ if (facidx != xc->rvat_chain_facidx) {
+ if (xc->rvat_chain_mem) {
+ free(xc->rvat_chain_mem);
+ xc->rvat_chain_mem = NULL;
+
+ xc->rvat_chain_pos_valid = 0;
+ }
+ }
+
+ if (!xc->rvat_chain_mem) {
+ uint32_t skiplen;
+ fstReaderFseeko(xc, xc->f, xc->rvat_vc_start + xc->rvat_chain_table[facidx], SEEK_SET);
+ xc->rvat_chain_len = fstReaderVarint32WithSkip(xc->f, &skiplen);
+ if (xc->rvat_chain_len) {
+ unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len);
+ unsigned char *mc = (unsigned char *)malloc(xc->rvat_chain_table_lengths[facidx]);
+ unsigned long destlen = xc->rvat_chain_len;
+ unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx];
+ int rc = Z_OK;
+
+ fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f);
+
+ switch (xc->rvat_packtype) {
+ case '4':
+ rc = (destlen ==
+ (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen))
+ ? Z_OK
+ : Z_DATA_ERROR;
+ break;
+ case 'F':
+ fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */
+ break;
+ default:
+ rc = uncompress(mu, &destlen, mc, sourcelen);
+ break;
+ }
+
+ free(mc);
+
+ if (rc != Z_OK) {
+ fprintf(stderr,
+ FST_APIMESS "fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d (rc=%d), exiting.\n",
+ (int)xc->rvat_chain_len, rc);
+ exit(255);
+ }
+
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ xc->rvat_chain_mem = mu;
+ } else {
+ int destlen = xc->rvat_chain_table_lengths[facidx] - skiplen;
+ unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len = destlen);
+ fstFread(mu, destlen, 1, xc->f);
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ xc->rvat_chain_mem = mu;
+ }
+
+ xc->rvat_chain_facidx = facidx;
+ }
+
+ /* process value chain here */
+
+ {
+ uint32_t tidx = 0, ptidx = 0;
+ uint32_t tdelta;
+ int skiplen;
+ unsigned int iprev = xc->rvat_chain_len;
+ uint32_t pvli = 0;
+ int pskip = 0;
+
+ if ((xc->rvat_chain_pos_valid) && (tim >= xc->rvat_chain_pos_time)) {
+ i = xc->rvat_chain_pos_idx;
+ tidx = xc->rvat_chain_pos_tidx;
+ } else {
+ i = 0;
+ tidx = 0;
+ xc->rvat_chain_pos_time = xc->rvat_beg_tim;
+ }
+
+ if (xc->signal_lens[facidx] == 1) {
+ while (i < xc->rvat_chain_len) {
+ uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen);
+ uint32_t shcnt = 2 << (vli & 1);
+ tdelta = vli >> shcnt;
+
+ if (xc->rvat_time_table[tidx + tdelta] <= tim) {
+ iprev = i;
+ pvli = vli;
+ ptidx = tidx;
+ /* pskip = skiplen; */ /* scan-build */
+
+ tidx += tdelta;
+ i += skiplen;
+ } else {
+ break;
+ }
+ }
+ if (iprev != xc->rvat_chain_len) {
+ xc->rvat_chain_pos_tidx = ptidx;
+ xc->rvat_chain_pos_idx = iprev;
+ xc->rvat_chain_pos_time = tim;
+ xc->rvat_chain_pos_valid = 1;
+
+ if (!(pvli & 1)) {
+ buf[0] = ((pvli >> 1) & 1) | '0';
+ } else {
+ buf[0] = FST_RCV_STR[((pvli >> 1) & 7)];
+ }
+ buf[1] = 0;
+ return (buf);
+ } else {
+ return (fstExtractRvatDataFromFrame(xc, facidx, buf));
+ }
+ } else {
+ while (i < xc->rvat_chain_len) {
+ uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen);
+ tdelta = vli >> 1;
+
+ if (xc->rvat_time_table[tidx + tdelta] <= tim) {
+ iprev = i;
+ pvli = vli;
+ ptidx = tidx;
+ pskip = skiplen;
+
+ tidx += tdelta;
+ i += skiplen;
+
+ if (!(pvli & 1)) {
+ i += ((xc->signal_lens[facidx] + 7) / 8);
+ } else {
+ i += xc->signal_lens[facidx];
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (iprev != xc->rvat_chain_len) {
+ unsigned char *vdata = xc->rvat_chain_mem + iprev + pskip;
+
+ xc->rvat_chain_pos_tidx = ptidx;
+ xc->rvat_chain_pos_idx = iprev;
+ xc->rvat_chain_pos_time = tim;
+ xc->rvat_chain_pos_valid = 1;
+
+ if (xc->signal_typs[facidx] != FST_VT_VCD_REAL) {
+ if (!(pvli & 1)) {
+ int byte = 0;
+ int bit;
+ unsigned int j;
+
+ for (j = 0; j < xc->signal_lens[facidx]; j++) {
+ unsigned char ch;
+ byte = j / 8;
+ bit = 7 - (j & 7);
+ ch = ((vdata[byte] >> bit) & 1) | '0';
+ buf[j] = ch;
+ }
+ buf[j] = 0;
+
+ return (buf);
+ } else {
+ memcpy(buf, vdata, xc->signal_lens[facidx]);
+ buf[xc->signal_lens[facidx]] = 0;
+ return (buf);
+ }
+ } else {
+ double d;
+ unsigned char *clone_d = (unsigned char *)&d;
+ unsigned char bufd[8];
+ unsigned char *srcdata;
+
+ if (!(pvli & 1)) /* very rare case, but possible */
+ {
+ int bit;
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ unsigned char ch;
+ bit = 7 - (j & 7);
+ ch = ((vdata[0] >> bit) & 1) | '0';
+ bufd[j] = ch;
+ }
+
+ srcdata = bufd;
+ } else {
+ srcdata = vdata;
+ }
+
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ sprintf(buf, "r%.16g", d);
+ return (buf);
+ }
+ } else {
+ return (fstExtractRvatDataFromFrame(xc, facidx, buf));
+ }
+ }
+ }
+
+ /* return(NULL); */
+}
+
+/**********************************************************************/
+#ifndef _WAVE_HAVE_JUDY
+
+/***********************/
+/*** ***/
+/*** jenkins hash ***/
+/*** ***/
+/***********************/
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bits set, and the deltas of all three
+ high bits or all three low bits, whether the original value of a,b,c
+ is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+ have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+ 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a
+ structure that could supported 2x parallelism, like so:
+ a -= b;
+ a -= c; x = (c>>13);
+ b -= c; a ^= x;
+ b -= a; x = (a<<8);
+ c -= a; b ^= x;
+ c -= b; x = (b>>13);
+ ...
+ Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ of that parallelism. They've also turned some of those single-cycle
+ latency instructions into multi-cycle latency instructions. Still,
+ this is the fastest good hash I could find. There were about 2^^68
+ to choose from. I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+#define mix(a, b, c) \
+ { \
+ a -= b; \
+ a -= c; \
+ a ^= (c >> 13); \
+ b -= c; \
+ b -= a; \
+ b ^= (a << 8); \
+ c -= a; \
+ c -= b; \
+ c ^= (b >> 13); \
+ a -= b; \
+ a -= c; \
+ a ^= (c >> 12); \
+ b -= c; \
+ b -= a; \
+ b ^= (a << 16); \
+ c -= a; \
+ c -= b; \
+ c ^= (b >> 5); \
+ a -= b; \
+ a -= c; \
+ a ^= (c >> 3); \
+ b -= c; \
+ b -= a; \
+ b ^= (a << 10); \
+ c -= a; \
+ c -= b; \
+ c ^= (b >> 15); \
+ }
+
+/*
+--------------------------------------------------------------------
+j_hash() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ initval : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Every 1-bit and 2-bit delta achieves avalanche.
+About 6*len+35 instructions.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+
+By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial. It's free.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^^32 is
+acceptable. Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+static uint32_t j_hash(const uint8_t *k, uint32_t length, uint32_t initval)
+{
+ uint32_t a, b, c, len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = initval; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 12) {
+ a += (k[0] + ((uint32_t)k[1] << 8) + ((uint32_t)k[2] << 16) + ((uint32_t)k[3] << 24));
+ b += (k[4] + ((uint32_t)k[5] << 8) + ((uint32_t)k[6] << 16) + ((uint32_t)k[7] << 24));
+ c += (k[8] + ((uint32_t)k[9] << 8) + ((uint32_t)k[10] << 16) + ((uint32_t)k[11] << 24));
+ mix(a, b, c);
+ k += 12;
+ len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += length;
+ switch (len) /* all the case statements fall through */
+ {
+ case 11:
+ c += ((uint32_t)k[10] << 24); /* fallthrough */
+ case 10:
+ c += ((uint32_t)k[9] << 16); /* fallthrough */
+ case 9:
+ c += ((uint32_t)k[8] << 8); /* fallthrough */
+ /* the first byte of c is reserved for the length */
+ case 8:
+ b += ((uint32_t)k[7] << 24); /* fallthrough */
+ case 7:
+ b += ((uint32_t)k[6] << 16); /* fallthrough */
+ case 6:
+ b += ((uint32_t)k[5] << 8); /* fallthrough */
+ case 5:
+ b += k[4]; /* fallthrough */
+ case 4:
+ a += ((uint32_t)k[3] << 24); /* fallthrough */
+ case 3:
+ a += ((uint32_t)k[2] << 16); /* fallthrough */
+ case 2:
+ a += ((uint32_t)k[1] << 8); /* fallthrough */
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a, b, c);
+ /*-------------------------------------------- report the result */
+ return (c);
+}
+
+/********************************************************************/
+
+/***************************/
+/*** ***/
+/*** judy HS emulation ***/
+/*** ***/
+/***************************/
+
+struct collchain_t
+{
+ struct collchain_t *next;
+ void *payload;
+ uint32_t fullhash, length;
+ unsigned char mem[1];
+};
+
+void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask)
+{
+ struct collchain_t ***base = (struct collchain_t ***)base_i;
+ uint32_t hf, h;
+ struct collchain_t **ar;
+ struct collchain_t *chain, *pchain;
+
+ if (!*base) {
+ *base = (struct collchain_t **)calloc(1, (hashmask + 1) * sizeof(void *));
+ }
+ ar = *base;
+
+ h = (hf = j_hash(mem, length, length)) & hashmask;
+ pchain = chain = ar[h];
+ while (chain) {
+ if ((chain->fullhash == hf) && (chain->length == length) && !memcmp(chain->mem, mem, length)) {
+ if (pchain != chain) /* move hit to front */
+ {
+ pchain->next = chain->next;
+ chain->next = ar[h];
+ ar[h] = chain;
+ }
+ return (&(chain->payload));
+ }
+
+ pchain = chain;
+ chain = chain->next;
+ }
+
+ chain = (struct collchain_t *)calloc(1, sizeof(struct collchain_t) + length - 1);
+ memcpy(chain->mem, mem, length);
+ chain->fullhash = hf;
+ chain->length = length;
+ chain->next = ar[h];
+ ar[h] = chain;
+ return (&(chain->payload));
+}
+
+void JenkinsFree(void *base_i, uint32_t hashmask)
+{
+ struct collchain_t ***base = (struct collchain_t ***)base_i;
+ uint32_t h;
+ struct collchain_t **ar;
+ struct collchain_t *chain, *chain_next;
+
+ if (base && *base) {
+ ar = *base;
+ for (h = 0; h <= hashmask; h++) {
+ chain = ar[h];
+ while (chain) {
+ chain_next = chain->next;
+ free(chain);
+ chain = chain_next;
+ }
+ }
+
+ free(*base);
+ *base = NULL;
+ }
+}
+
+#endif
+
+/**********************************************************************/
+
+/************************/
+/*** ***/
+/*** utility function ***/
+/*** ***/
+/************************/
+
+int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len)
+{
+ const unsigned char *src = s;
+ int dlen = 0;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (src[i]) {
+ case '\a': /* fallthrough */
+ case '\b': /* fallthrough */
+ case '\f': /* fallthrough */
+ case '\n': /* fallthrough */
+ case '\r': /* fallthrough */
+ case '\t': /* fallthrough */
+ case '\v': /* fallthrough */
+ case '\'': /* fallthrough */
+ case '\"': /* fallthrough */
+ case '\\': /* fallthrough */
+ case '\?':
+ dlen += 2;
+ break;
+ default:
+ if ((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */
+ {
+ dlen++;
+ } else {
+ dlen += 4;
+ }
+ break;
+ }
+ }
+
+ return (dlen);
+}
+
+int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len)
+{
+ const unsigned char *src = s;
+ unsigned char *dst = d;
+ unsigned char val;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (src[i]) {
+ case '\a':
+ *(dst++) = '\\';
+ *(dst++) = 'a';
+ break;
+ case '\b':
+ *(dst++) = '\\';
+ *(dst++) = 'b';
+ break;
+ case '\f':
+ *(dst++) = '\\';
+ *(dst++) = 'f';
+ break;
+ case '\n':
+ *(dst++) = '\\';
+ *(dst++) = 'n';
+ break;
+ case '\r':
+ *(dst++) = '\\';
+ *(dst++) = 'r';
+ break;
+ case '\t':
+ *(dst++) = '\\';
+ *(dst++) = 't';
+ break;
+ case '\v':
+ *(dst++) = '\\';
+ *(dst++) = 'v';
+ break;
+ case '\'':
+ *(dst++) = '\\';
+ *(dst++) = '\'';
+ break;
+ case '\"':
+ *(dst++) = '\\';
+ *(dst++) = '\"';
+ break;
+ case '\\':
+ *(dst++) = '\\';
+ *(dst++) = '\\';
+ break;
+ case '\?':
+ *(dst++) = '\\';
+ *(dst++) = '\?';
+ break;
+ default:
+ if ((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */
+ {
+ *(dst++) = src[i];
+ } else {
+ val = src[i];
+ *(dst++) = '\\';
+ *(dst++) = (val / 64) + '0';
+ val = val & 63;
+ *(dst++) = (val / 8) + '0';
+ val = val & 7;
+ *(dst++) = (val) + '0';
+ }
+ break;
+ }
+ }
+
+ return (dst - d);
+}
+
+/*
+ * this overwrites the original string if the destination pointer is NULL
+ */
+int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len)
+{
+ unsigned char *src = s;
+ unsigned char *dst = (!d) ? s : (s = d);
+ unsigned char val[3];
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (src[i] != '\\') {
+ *(dst++) = src[i];
+ } else {
+ switch (src[++i]) {
+ case 'a':
+ *(dst++) = '\a';
+ break;
+ case 'b':
+ *(dst++) = '\b';
+ break;
+ case 'f':
+ *(dst++) = '\f';
+ break;
+ case 'n':
+ *(dst++) = '\n';
+ break;
+ case 'r':
+ *(dst++) = '\r';
+ break;
+ case 't':
+ *(dst++) = '\t';
+ break;
+ case 'v':
+ *(dst++) = '\v';
+ break;
+ case '\'':
+ *(dst++) = '\'';
+ break;
+ case '\"':
+ *(dst++) = '\"';
+ break;
+ case '\\':
+ *(dst++) = '\\';
+ break;
+ case '\?':
+ *(dst++) = '\?';
+ break;
+
+ case 'x':
+ val[0] = toupper(src[++i]);
+ val[1] = toupper(src[++i]);
+ val[0] = ((val[0] >= 'A') && (val[0] <= 'F')) ? (val[0] - 'A' + 10) : (val[0] - '0');
+ val[1] = ((val[1] >= 'A') && (val[1] <= 'F')) ? (val[1] - 'A' + 10) : (val[1] - '0');
+ *(dst++) = val[0] * 16 + val[1];
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val[0] = src[i] - '0';
+ val[1] = src[++i] - '0';
+ val[2] = src[++i] - '0';
+ *(dst++) = val[0] * 64 + val[1] * 8 + val[2];
+ break;
+
+ default:
+ *(dst++) = src[i];
+ break;
+ }
+ }
+ }
+
+ return (dst - s);
+}
+
+struct fstETab *fstUtilityExtractEnumTableFromString(const char *s)
+{
+ struct fstETab *et = NULL;
+ int num_spaces = 0;
+ int i;
+ int newlen;
+
+ if (s) {
+ const char *csp = strchr(s, ' ');
+ int cnt = atoi(csp + 1);
+
+ for (;;) {
+ csp = strchr(csp + 1, ' ');
+ if (csp) {
+ num_spaces++;
+ } else {
+ break;
+ }
+ }
+
+ if (num_spaces == (2 * cnt)) {
+ char *sp, *sp2;
+
+ et = (struct fstETab *)calloc(1, sizeof(struct fstETab));
+ et->elem_count = cnt;
+ et->name = strdup(s);
+ et->literal_arr = (char **)calloc(cnt, sizeof(char *));
+ et->val_arr = (char **)calloc(cnt, sizeof(char *));
+
+ sp = strchr(et->name, ' ');
+ *sp = 0;
+
+ sp = strchr(sp + 1, ' ');
+
+ for (i = 0; i < cnt; i++) {
+ sp2 = strchr(sp + 1, ' ');
+ *(char *)sp2 = 0;
+ et->literal_arr[i] = sp + 1;
+ sp = sp2;
+
+ newlen = fstUtilityEscToBin(NULL, (unsigned char *)et->literal_arr[i], strlen(et->literal_arr[i]));
+ et->literal_arr[i][newlen] = 0;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ sp2 = strchr(sp + 1, ' ');
+ if (sp2) {
+ *sp2 = 0;
+ }
+ et->val_arr[i] = sp + 1;
+ sp = sp2;
+
+ newlen = fstUtilityEscToBin(NULL, (unsigned char *)et->val_arr[i], strlen(et->val_arr[i]));
+ et->val_arr[i][newlen] = 0;
+ }
+ }
+ }
+
+ return (et);
+}
+
+void fstUtilityFreeEnumTable(struct fstETab *etab)
+{
+ if (etab) {
+ free(etab->literal_arr);
+ free(etab->val_arr);
+ free(etab->name);
+ free(etab);
+ }
+}
diff --git a/libs/fst/fstapi.h b/libs/fst/fstapi.h
new file mode 100644
index 000000000..a5e0971a1
--- /dev/null
+++ b/libs/fst/fstapi.h
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2009-2018 Tony Bybell.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef FST_API_H
+#define FST_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+#if defined(_MSC_VER)
+#include "libs/zlib/zlib.h"
+#include <io.h>
+
+#include <process.h>
+
+#define ftruncate _chsize_s
+#define unlink _unlink
+#define fileno _fileno
+#define lseek _lseeki64
+
+#ifdef _WIN64
+#define ssize_t __int64
+#define SSIZE_MAX 9223372036854775807i64
+#else
+#define ssize_t long
+#define SSIZE_MAX 2147483647L
+#endif
+
+#include "stdint.h"
+#else
+#include <zlib.h>
+#include <unistd.h>
+#endif
+#include <time.h>
+
+#define FST_RDLOAD "FSTLOAD | "
+
+typedef uint32_t fstHandle;
+typedef uint32_t fstEnumHandle;
+
+enum fstWriterPackType
+{
+ FST_WR_PT_ZLIB = 0,
+ FST_WR_PT_FASTLZ = 1,
+ FST_WR_PT_LZ4 = 2
+};
+
+enum fstFileType
+{
+ FST_FT_MIN = 0,
+
+ FST_FT_VERILOG = 0,
+ FST_FT_VHDL = 1,
+ FST_FT_VERILOG_VHDL = 2,
+
+ FST_FT_MAX = 2
+};
+
+enum fstBlockType
+{
+ FST_BL_HDR = 0,
+ FST_BL_VCDATA = 1,
+ FST_BL_BLACKOUT = 2,
+ FST_BL_GEOM = 3,
+ FST_BL_HIER = 4,
+ FST_BL_VCDATA_DYN_ALIAS = 5,
+ FST_BL_HIER_LZ4 = 6,
+ FST_BL_HIER_LZ4DUO = 7,
+ FST_BL_VCDATA_DYN_ALIAS2 = 8,
+
+ FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */
+ FST_BL_SKIP = 255 /* used while block is being written */
+};
+
+enum fstScopeType
+{
+ FST_ST_MIN = 0,
+
+ FST_ST_VCD_MODULE = 0,
+ FST_ST_VCD_TASK = 1,
+ FST_ST_VCD_FUNCTION = 2,
+ FST_ST_VCD_BEGIN = 3,
+ FST_ST_VCD_FORK = 4,
+ FST_ST_VCD_GENERATE = 5,
+ FST_ST_VCD_STRUCT = 6,
+ FST_ST_VCD_UNION = 7,
+ FST_ST_VCD_CLASS = 8,
+ FST_ST_VCD_INTERFACE = 9,
+ FST_ST_VCD_PACKAGE = 10,
+ FST_ST_VCD_PROGRAM = 11,
+
+ FST_ST_VHDL_ARCHITECTURE = 12,
+ FST_ST_VHDL_PROCEDURE = 13,
+ FST_ST_VHDL_FUNCTION = 14,
+ FST_ST_VHDL_RECORD = 15,
+ FST_ST_VHDL_PROCESS = 16,
+ FST_ST_VHDL_BLOCK = 17,
+ FST_ST_VHDL_FOR_GENERATE = 18,
+ FST_ST_VHDL_IF_GENERATE = 19,
+ FST_ST_VHDL_GENERATE = 20,
+ FST_ST_VHDL_PACKAGE = 21,
+
+ FST_ST_MAX = 21,
+
+ FST_ST_GEN_ATTRBEGIN = 252,
+ FST_ST_GEN_ATTREND = 253,
+
+ FST_ST_VCD_SCOPE = 254,
+ FST_ST_VCD_UPSCOPE = 255
+};
+
+enum fstVarType
+{
+ FST_VT_MIN = 0, /* start of vartypes */
+
+ FST_VT_VCD_EVENT = 0,
+ FST_VT_VCD_INTEGER = 1,
+ FST_VT_VCD_PARAMETER = 2,
+ FST_VT_VCD_REAL = 3,
+ FST_VT_VCD_REAL_PARAMETER = 4,
+ FST_VT_VCD_REG = 5,
+ FST_VT_VCD_SUPPLY0 = 6,
+ FST_VT_VCD_SUPPLY1 = 7,
+ FST_VT_VCD_TIME = 8,
+ FST_VT_VCD_TRI = 9,
+ FST_VT_VCD_TRIAND = 10,
+ FST_VT_VCD_TRIOR = 11,
+ FST_VT_VCD_TRIREG = 12,
+ FST_VT_VCD_TRI0 = 13,
+ FST_VT_VCD_TRI1 = 14,
+ FST_VT_VCD_WAND = 15,
+ FST_VT_VCD_WIRE = 16,
+ FST_VT_VCD_WOR = 17,
+ FST_VT_VCD_PORT = 18,
+ FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
+ FST_VT_VCD_REALTIME = 20,
+
+ FST_VT_GEN_STRING =
+ 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
+
+ FST_VT_SV_BIT = 22,
+ FST_VT_SV_LOGIC = 23,
+ FST_VT_SV_INT = 24, /* declare as size = 32 */
+ FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */
+ FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
+ FST_VT_SV_BYTE = 27, /* declare as size = 8 */
+ FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
+ FST_VT_SV_SHORTREAL =
+ 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
+
+ FST_VT_MAX = 29 /* end of vartypes */
+};
+
+enum fstVarDir
+{
+ FST_VD_MIN = 0,
+
+ FST_VD_IMPLICIT = 0,
+ FST_VD_INPUT = 1,
+ FST_VD_OUTPUT = 2,
+ FST_VD_INOUT = 3,
+ FST_VD_BUFFER = 4,
+ FST_VD_LINKAGE = 5,
+
+ FST_VD_MAX = 5
+};
+
+enum fstHierType
+{
+ FST_HT_MIN = 0,
+
+ FST_HT_SCOPE = 0,
+ FST_HT_UPSCOPE = 1,
+ FST_HT_VAR = 2,
+ FST_HT_ATTRBEGIN = 3,
+ FST_HT_ATTREND = 4,
+
+ /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other
+ formats */
+ FST_HT_TREEBEGIN = 5,
+ FST_HT_TREEEND = 6,
+
+ FST_HT_MAX = 6
+};
+
+enum fstAttrType
+{
+ FST_AT_MIN = 0,
+
+ FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
+ FST_AT_ARRAY = 1,
+ FST_AT_ENUM = 2,
+ FST_AT_PACK = 3,
+
+ FST_AT_MAX = 3
+};
+
+enum fstMiscType
+{
+ FST_MT_MIN = 0,
+
+ FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
+ FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */
+ FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */
+ FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
+ FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
+ FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
+ FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
+ FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
+ FST_MT_UNKNOWN = 8,
+
+ FST_MT_MAX = 8
+};
+
+enum fstArrayType
+{
+ FST_AR_MIN = 0,
+
+ FST_AR_NONE = 0,
+ FST_AR_UNPACKED = 1,
+ FST_AR_PACKED = 2,
+ FST_AR_SPARSE = 3,
+
+ FST_AR_MAX = 3
+};
+
+enum fstEnumValueType
+{
+ FST_EV_SV_INTEGER = 0,
+ FST_EV_SV_BIT = 1,
+ FST_EV_SV_LOGIC = 2,
+ FST_EV_SV_INT = 3,
+ FST_EV_SV_SHORTINT = 4,
+ FST_EV_SV_LONGINT = 5,
+ FST_EV_SV_BYTE = 6,
+ FST_EV_SV_UNSIGNED_INTEGER = 7,
+ FST_EV_SV_UNSIGNED_BIT = 8,
+ FST_EV_SV_UNSIGNED_LOGIC = 9,
+ FST_EV_SV_UNSIGNED_INT = 10,
+ FST_EV_SV_UNSIGNED_SHORTINT = 11,
+ FST_EV_SV_UNSIGNED_LONGINT = 12,
+ FST_EV_SV_UNSIGNED_BYTE = 13,
+
+ FST_EV_REG = 14,
+ FST_EV_TIME = 15,
+
+ FST_EV_MAX = 15
+};
+
+enum fstPackType
+{
+ FST_PT_NONE = 0,
+ FST_PT_UNPACKED = 1,
+ FST_PT_PACKED = 2,
+ FST_PT_TAGGED_PACKED = 3,
+
+ FST_PT_MAX = 3
+};
+
+enum fstSupplementalVarType
+{
+ FST_SVT_MIN = 0,
+
+ FST_SVT_NONE = 0,
+
+ FST_SVT_VHDL_SIGNAL = 1,
+ FST_SVT_VHDL_VARIABLE = 2,
+ FST_SVT_VHDL_CONSTANT = 3,
+ FST_SVT_VHDL_FILE = 4,
+ FST_SVT_VHDL_MEMORY = 5,
+
+ FST_SVT_MAX = 5
+};
+
+enum fstSupplementalDataType
+{
+ FST_SDT_MIN = 0,
+
+ FST_SDT_NONE = 0,
+
+ FST_SDT_VHDL_BOOLEAN = 1,
+ FST_SDT_VHDL_BIT = 2,
+ FST_SDT_VHDL_BIT_VECTOR = 3,
+ FST_SDT_VHDL_STD_ULOGIC = 4,
+ FST_SDT_VHDL_STD_ULOGIC_VECTOR = 5,
+ FST_SDT_VHDL_STD_LOGIC = 6,
+ FST_SDT_VHDL_STD_LOGIC_VECTOR = 7,
+ FST_SDT_VHDL_UNSIGNED = 8,
+ FST_SDT_VHDL_SIGNED = 9,
+ FST_SDT_VHDL_INTEGER = 10,
+ FST_SDT_VHDL_REAL = 11,
+ FST_SDT_VHDL_NATURAL = 12,
+ FST_SDT_VHDL_POSITIVE = 13,
+ FST_SDT_VHDL_TIME = 14,
+ FST_SDT_VHDL_CHARACTER = 15,
+ FST_SDT_VHDL_STRING = 16,
+
+ FST_SDT_MAX = 16,
+
+ FST_SDT_SVT_SHIFT_COUNT =
+ 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */
+ FST_SDT_ABS_MAX = ((1 << (FST_SDT_SVT_SHIFT_COUNT)) - 1)
+};
+
+struct fstHier
+{
+ unsigned char htyp;
+
+ union
+ {
+ /* if htyp == FST_HT_SCOPE */
+ struct fstHierScope
+ {
+ unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
+ const char *name;
+ const char *component;
+ uint32_t name_length; /* strlen(u.scope.name) */
+ uint32_t component_length; /* strlen(u.scope.component) */
+ } scope;
+
+ /* if htyp == FST_HT_VAR */
+ struct fstHierVar
+ {
+ unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
+ unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
+ unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
+ unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */
+ unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */
+ const char *name;
+ uint32_t length;
+ fstHandle handle;
+ uint32_t name_length; /* strlen(u.var.name) */
+ unsigned is_alias : 1;
+ } var;
+
+ /* if htyp == FST_HT_ATTRBEGIN */
+ struct fstHierAttr
+ {
+ unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
+ unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
+ const char *name;
+ uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */
+ uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC +
+ FST_MT_SOURCESTEM) */
+ uint32_t name_length; /* strlen(u.attr.name) */
+ } attr;
+ } u;
+};
+
+struct fstETab
+{
+ char *name;
+ uint32_t elem_count;
+ char **literal_arr;
+ char **val_arr;
+};
+
+/*
+ * writer functions
+ */
+void fstWriterClose(void *ctx);
+void *fstWriterCreate(const char *nam, int use_compressed_hier);
+fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits,
+ const char **literal_arr, const char **val_arr);
+/* used for Verilog/SV */
+fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle);
+/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
+ the current Verilog/SV one. The "type" string is optional for a more verbose or custom description */
+fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle, const char *type, enum fstSupplementalVarType svt,
+ enum fstSupplementalDataType sdt);
+void fstWriterEmitDumpActive(void *ctx, int enable);
+void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
+void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
+void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val);
+void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val);
+void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val);
+void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val);
+void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
+void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
+void fstWriterFlushContext(void *ctx);
+int fstWriterGetDumpSizeLimitReached(void *ctx);
+int fstWriterGetFseekFailed(void *ctx);
+void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, const char *attrname, uint64_t arg);
+void fstWriterSetAttrEnd(void *ctx);
+void fstWriterSetComment(void *ctx, const char *comm);
+void fstWriterSetDate(void *ctx, const char *dat);
+void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
+void fstWriterSetEnvVar(void *ctx, const char *envvar);
+void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
+void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
+void fstWriterSetParallelMode(void *ctx, int enable);
+void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
+void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, const char *scopename, const char *scopecomp);
+void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
+void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
+void fstWriterSetTimescale(void *ctx, int ts);
+void fstWriterSetTimescaleFromString(void *ctx, const char *s);
+void fstWriterSetTimezero(void *ctx, int64_t tim);
+void fstWriterSetUpscope(void *ctx);
+void fstWriterSetValueList(void *ctx, const char *vl);
+void fstWriterSetVersion(void *ctx, const char *vers);
+
+/*
+ * reader functions
+ */
+void fstReaderClose(void *ctx);
+void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
+void fstReaderClrFacProcessMaskAll(void *ctx);
+uint64_t fstReaderGetAliasCount(void *ctx);
+const char *fstReaderGetCurrentFlatScope(void *ctx);
+void *fstReaderGetCurrentScopeUserInfo(void *ctx);
+int fstReaderGetCurrentScopeLen(void *ctx);
+const char *fstReaderGetDateString(void *ctx);
+int fstReaderGetDoubleEndianMatchState(void *ctx);
+uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
+unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
+uint64_t fstReaderGetEndTime(void *ctx);
+int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
+int fstReaderGetFileType(void *ctx);
+int fstReaderGetFseekFailed(void *ctx);
+fstHandle fstReaderGetMaxHandle(void *ctx);
+uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
+uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
+uint64_t fstReaderGetScopeCount(void *ctx);
+uint64_t fstReaderGetStartTime(void *ctx);
+signed char fstReaderGetTimescale(void *ctx);
+int64_t fstReaderGetTimezero(void *ctx);
+uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
+char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
+uint64_t fstReaderGetVarCount(void *ctx);
+const char *fstReaderGetVersionString(void *ctx);
+struct fstHier *fstReaderIterateHier(void *ctx);
+int fstReaderIterateHierRewind(void *ctx);
+int fstReaderIterBlocks(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx,
+ const unsigned char *value),
+ void *user_callback_data_pointer, FILE *vcdhandle);
+int fstReaderIterBlocks2(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value),
+ void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value,
+ uint32_t len),
+ void *user_callback_data_pointer, FILE *vcdhandle);
+void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
+void *fstReaderOpen(const char *nam);
+void *fstReaderOpenForUtilitiesOnly(void);
+const char *fstReaderPopScope(void *ctx);
+int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
+const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info);
+void fstReaderResetScope(void *ctx);
+void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
+void fstReaderSetFacProcessMaskAll(void *ctx);
+void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
+void fstReaderSetUnlimitedTimeRange(void *ctx);
+void fstReaderSetVcdExtensions(void *ctx, int enable);
+
+/*
+ * utility functions
+ */
+int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
+int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
+int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
+struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
+void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/fst/lz4.cc b/libs/fst/lz4.cc
new file mode 100644
index 000000000..7e94f2492
--- /dev/null
+++ b/libs/fst/lz4.cc
@@ -0,0 +1,1615 @@
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2015, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ SPDX-License-Identifier: BSD-2-Clause
+
+ You can contact the author at :
+ - LZ4 source repository : https://github.com/Cyan4973/lz4
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+
+/**************************************
+ * Tuning parameters
+ **************************************/
+/*
+ * HEAPMODE :
+ * Select how default compression functions will allocate memory for their hash table,
+ * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
+ */
+#define HEAPMODE 0
+
+/*
+ * ACCELERATION_DEFAULT :
+ * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
+ */
+#define ACCELERATION_DEFAULT 1
+
+/**************************************
+ * CPU Feature Detection
+ **************************************/
+/*
+ * LZ4_FORCE_SW_BITCOUNT
+ * Define this parameter if your target system or compiler does not support hardware bit count
+ */
+#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
+#define LZ4_FORCE_SW_BITCOUNT
+#endif
+
+/**************************************
+ * Includes
+ **************************************/
+#include "lz4.h"
+
+/**************************************
+ * Compiler Options
+ **************************************/
+#ifdef _MSC_VER /* Visual Studio */
+#define FORCE_INLINE static __forceinline
+#include <intrin.h>
+#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+#pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
+#else
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
+#if defined(__GNUC__) || defined(__clang__)
+#define FORCE_INLINE static inline __attribute__((always_inline))
+#else
+#define FORCE_INLINE static inline
+#endif
+#else
+#define FORCE_INLINE static
+#endif /* __STDC_VERSION__ */
+#endif /* _MSC_VER */
+
+/* LZ4_GCC_VERSION is defined into lz4.h */
+#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
+#define expect(expr, value) (__builtin_expect((expr), (value)))
+#else
+#define expect(expr, value) (expr)
+#endif
+
+#define likely(expr) expect((expr) != 0, 1)
+#define unlikely(expr) expect((expr) != 0, 0)
+
+/**************************************
+ * Memory routines
+ **************************************/
+#include <stdlib.h> /* malloc, calloc, free */
+#define ALLOCATOR(n, s) calloc(n, s)
+#define FREEMEM free
+#include <string.h> /* memset, memcpy */
+#define MEM_INIT memset
+
+/**************************************
+ * Basic Types
+ **************************************/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
+#include <stdint.h>
+typedef uint8_t BYTE;
+typedef uint16_t U16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+#else
+typedef unsigned char BYTE;
+typedef unsigned short U16;
+typedef unsigned int U32;
+typedef signed int S32;
+typedef unsigned long long U64;
+#endif
+
+/**************************************
+ * Reading and writing into memory
+ **************************************/
+#define STEPSIZE sizeof(size_t)
+
+static unsigned LZ4_64bits(void) { return sizeof(void *) == 8; }
+
+static unsigned LZ4_isLittleEndian(void)
+{
+ const union
+ {
+ U32 i;
+ BYTE c[4];
+ } one = {1}; /* don't use static : performance detrimental */
+ return one.c[0];
+}
+
+static U16 LZ4_read16(const void *memPtr)
+{
+ U16 val16;
+ memcpy(&val16, memPtr, 2);
+ return val16;
+}
+
+static U16 LZ4_readLE16(const void *memPtr)
+{
+ if (LZ4_isLittleEndian()) {
+ return LZ4_read16(memPtr);
+ } else {
+ const BYTE *p = (const BYTE *)memPtr;
+ return (U16)((U16)p[0] + (p[1] << 8));
+ }
+}
+
+static void LZ4_writeLE16(void *memPtr, U16 value)
+{
+ if (LZ4_isLittleEndian()) {
+ memcpy(memPtr, &value, 2);
+ } else {
+ BYTE *p = (BYTE *)memPtr;
+ p[0] = (BYTE)value;
+ p[1] = (BYTE)(value >> 8);
+ }
+}
+
+static U32 LZ4_read32(const void *memPtr)
+{
+ U32 val32;
+ memcpy(&val32, memPtr, 4);
+ return val32;
+}
+
+static U64 LZ4_read64(const void *memPtr)
+{
+ U64 val64;
+ memcpy(&val64, memPtr, 8);
+ return val64;
+}
+
+static size_t LZ4_read_ARCH(const void *p)
+{
+ if (LZ4_64bits())
+ return (size_t)LZ4_read64(p);
+ else
+ return (size_t)LZ4_read32(p);
+}
+
+static void LZ4_copy4(void *dstPtr, const void *srcPtr) { memcpy(dstPtr, srcPtr, 4); }
+
+static void LZ4_copy8(void *dstPtr, const void *srcPtr) { memcpy(dstPtr, srcPtr, 8); }
+
+/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
+static void LZ4_wildCopy(void *dstPtr, const void *srcPtr, void *dstEnd)
+{
+ BYTE *d = (BYTE *)dstPtr;
+ const BYTE *s = (const BYTE *)srcPtr;
+ BYTE *e = (BYTE *)dstEnd;
+ do {
+ LZ4_copy8(d, s);
+ d += 8;
+ s += 8;
+ } while (d < e);
+}
+
+/**************************************
+ * Common Constants
+ **************************************/
+#define MINMATCH 4
+
+#define COPYLENGTH 8
+#define LASTLITERALS 5
+#define MFLIMIT (COPYLENGTH + MINMATCH)
+static const int LZ4_minLength = (MFLIMIT + 1);
+
+#define KB *(1 << 10)
+#define MB *(1 << 20)
+#define GB *(1U << 30)
+
+#define MAXD_LOG 16
+#ifdef MAX_DISTANCE
+#undef MAX_DISTANCE
+#endif
+#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
+
+#define ML_BITS 4
+#define ML_MASK ((1U << ML_BITS) - 1)
+#define RUN_BITS (8 - ML_BITS)
+#define RUN_MASK ((1U << RUN_BITS) - 1)
+
+/**************************************
+ * Common Utils
+ **************************************/
+#define LZ4_STATIC_ASSERT(c) \
+ { \
+ enum \
+ { \
+ LZ4_static_assert = 1 / (int)(!!(c)) \
+ }; \
+ } /* use only *after* variable declarations */
+
+/**************************************
+ * Common functions
+ **************************************/
+static unsigned LZ4_NbCommonBytes(size_t val)
+{
+ if (LZ4_isLittleEndian()) {
+ if (LZ4_64bits()) {
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r = 0;
+ _BitScanForward64(&r, (U64)val);
+ return (int)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_ctzll((U64)val) >> 3);
+#else
+ static const int DeBruijnBytePos[64] = {0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5,
+ 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5,
+ 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7};
+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
+#endif
+ } else /* 32 bits */
+ {
+#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r;
+ _BitScanForward(&r, (U32)val);
+ return (int)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_ctz((U32)val) >> 3);
+#else
+ static const int DeBruijnBytePos[32] = {0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1,
+ 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1};
+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
+#endif
+ }
+ } else /* Big Endian CPU */
+ {
+ if (LZ4_64bits()) {
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r = 0;
+ _BitScanReverse64(&r, val);
+ return (unsigned)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_clzll((U64)val) >> 3);
+#else
+ unsigned r;
+ if (!(val >> 32)) {
+ r = 4;
+ } else {
+ r = 0;
+ val >>= 32;
+ }
+ if (!(val >> 16)) {
+ r += 2;
+ val >>= 8;
+ } else {
+ val >>= 24;
+ }
+ r += (!val);
+ return r;
+#endif
+ } else /* 32 bits */
+ {
+#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r = 0;
+ _BitScanReverse(&r, (unsigned long)val);
+ return (unsigned)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_clz((U32)val) >> 3);
+#else
+ unsigned r;
+ if (!(val >> 16)) {
+ r = 2;
+ val >>= 8;
+ } else {
+ r = 0;
+ val >>= 24;
+ }
+ r += (!val);
+ return r;
+#endif
+ }
+ }
+}
+
+static unsigned LZ4_count(const BYTE *pIn, const BYTE *pMatch, const BYTE *pInLimit)
+{
+ const BYTE *const pStart = pIn;
+
+ while (likely(pIn < pInLimit - (STEPSIZE - 1))) {
+ size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
+ if (!diff) {
+ pIn += STEPSIZE;
+ pMatch += STEPSIZE;
+ continue;
+ }
+ pIn += LZ4_NbCommonBytes(diff);
+ return (unsigned)(pIn - pStart);
+ }
+
+ if (LZ4_64bits())
+ if ((pIn < (pInLimit - 3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) {
+ pIn += 4;
+ pMatch += 4;
+ }
+ if ((pIn < (pInLimit - 1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) {
+ pIn += 2;
+ pMatch += 2;
+ }
+ if ((pIn < pInLimit) && (*pMatch == *pIn))
+ pIn++;
+ return (unsigned)(pIn - pStart);
+}
+
+#ifndef LZ4_COMMONDEFS_ONLY
+/**************************************
+ * Local Constants
+ **************************************/
+#define LZ4_HASHLOG (LZ4_MEMORY_USAGE - 2)
+#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
+#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
+
+static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT - 1));
+static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
+
+/**************************************
+ * Local Structures and types
+ **************************************/
+typedef struct
+{
+ U32 hashTable[HASH_SIZE_U32];
+ U32 currentOffset;
+ U32 initCheck;
+ const BYTE *dictionary;
+ BYTE *bufferStart; /* obsolete, used for slideInputBuffer */
+ U32 dictSize;
+} LZ4_stream_t_internal;
+
+typedef enum
+{
+ notLimited = 0,
+ limitedOutput = 1
+} limitedOutput_directive;
+typedef enum
+{
+ byPtr,
+ byU32,
+ byU16
+} tableType_t;
+
+typedef enum
+{
+ noDict = 0,
+ withPrefix64k,
+ usingExtDict
+} dict_directive;
+typedef enum
+{
+ noDictIssue = 0,
+ dictSmall
+} dictIssue_directive;
+
+typedef enum
+{
+ endOnOutputSize = 0,
+ endOnInputSize = 1
+} endCondition_directive;
+typedef enum
+{
+ full = 0,
+ partial = 1
+} earlyEnd_directive;
+
+/**************************************
+ * Local Utils
+ **************************************/
+int LZ4_versionNumber(void) { return LZ4_VERSION_NUMBER; }
+int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
+int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
+
+/********************************
+ * Compression functions
+ ********************************/
+
+static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType)
+{
+ if (tableType == byU16)
+ return (((sequence)*2654435761U) >> ((MINMATCH * 8) - (LZ4_HASHLOG + 1)));
+ else
+ return (((sequence)*2654435761U) >> ((MINMATCH * 8) - LZ4_HASHLOG));
+}
+
+static const U64 prime5bytes = 889523592379ULL;
+static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType)
+{
+ const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG + 1 : LZ4_HASHLOG;
+ const U32 hashMask = (1 << hashLog) - 1;
+ return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
+}
+
+static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
+{
+ if (LZ4_64bits())
+ return LZ4_hashSequence64(sequence, tableType);
+ return LZ4_hashSequence((U32)sequence, tableType);
+}
+
+static U32 LZ4_hashPosition(const void *p, tableType_t tableType)
+{
+ return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType);
+}
+
+static void LZ4_putPositionOnHash(const BYTE *p, U32 h, void *tableBase, tableType_t const tableType,
+ const BYTE *srcBase)
+{
+ switch (tableType) {
+ case byPtr: {
+ const BYTE **hashTable = (const BYTE **)tableBase;
+ hashTable[h] = p;
+ return;
+ }
+ case byU32: {
+ U32 *hashTable = (U32 *)tableBase;
+ hashTable[h] = (U32)(p - srcBase);
+ return;
+ }
+ case byU16: {
+ U16 *hashTable = (U16 *)tableBase;
+ hashTable[h] = (U16)(p - srcBase);
+ return;
+ }
+ }
+}
+
+static void LZ4_putPosition(const BYTE *p, void *tableBase, tableType_t tableType, const BYTE *srcBase)
+{
+ U32 h = LZ4_hashPosition(p, tableType);
+ LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
+}
+
+static const BYTE *LZ4_getPositionOnHash(U32 h, void *tableBase, tableType_t tableType, const BYTE *srcBase)
+{
+ if (tableType == byPtr) {
+ const BYTE **hashTable = (const BYTE **)tableBase;
+ return hashTable[h];
+ }
+ if (tableType == byU32) {
+ U32 *hashTable = (U32 *)tableBase;
+ return hashTable[h] + srcBase;
+ }
+ {
+ U16 *hashTable = (U16 *)tableBase;
+ return hashTable[h] + srcBase;
+ } /* default, to ensure a return */
+}
+
+static const BYTE *LZ4_getPosition(const BYTE *p, void *tableBase, tableType_t tableType, const BYTE *srcBase)
+{
+ U32 h = LZ4_hashPosition(p, tableType);
+ return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
+}
+
+FORCE_INLINE int LZ4_compress_generic(void *const ctx, const char *const source, char *const dest, const int inputSize,
+ const int maxOutputSize, const limitedOutput_directive outputLimited,
+ const tableType_t tableType, const dict_directive dict,
+ const dictIssue_directive dictIssue, const U32 acceleration)
+{
+ LZ4_stream_t_internal *const dictPtr = (LZ4_stream_t_internal *)ctx;
+
+ const BYTE *ip = (const BYTE *)source;
+ const BYTE *base;
+ const BYTE *lowLimit;
+ const BYTE *const lowRefLimit = ip - dictPtr->dictSize;
+ const BYTE *const dictionary = dictPtr->dictionary;
+ const BYTE *const dictEnd = dictionary + dictPtr->dictSize;
+ const size_t dictDelta = dictEnd - (const BYTE *)source;
+ const BYTE *anchor = (const BYTE *)source;
+ const BYTE *const iend = ip + inputSize;
+ const BYTE *const mflimit = iend - MFLIMIT;
+ const BYTE *const matchlimit = iend - LASTLITERALS;
+
+ BYTE *op = (BYTE *)dest;
+ BYTE *const olimit = op + maxOutputSize;
+
+ U32 forwardH;
+ size_t refDelta = 0;
+
+ /* Init conditions */
+ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE)
+ return 0; /* Unsupported input size, too large (or negative) */
+ switch (dict) {
+ case noDict:
+ default:
+ base = (const BYTE *)source;
+ lowLimit = (const BYTE *)source;
+ break;
+ case withPrefix64k:
+ base = (const BYTE *)source - dictPtr->currentOffset;
+ lowLimit = (const BYTE *)source - dictPtr->dictSize;
+ break;
+ case usingExtDict:
+ base = (const BYTE *)source - dictPtr->currentOffset;
+ lowLimit = (const BYTE *)source;
+ break;
+ }
+ if ((tableType == byU16) && (inputSize >= LZ4_64Klimit))
+ return 0; /* Size too large (not within 64K limit) */
+ if (inputSize < LZ4_minLength)
+ goto _last_literals; /* Input too small, no compression (all literals) */
+
+ /* First Byte */
+ LZ4_putPosition(ip, ctx, tableType, base);
+ ip++;
+ forwardH = LZ4_hashPosition(ip, tableType);
+
+ /* Main Loop */
+ for (;;) {
+ const BYTE *match;
+ BYTE *token;
+ {
+ const BYTE *forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
+
+ /* Find a match */
+ do {
+ U32 h = forwardH;
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimit))
+ goto _last_literals;
+
+ match = LZ4_getPositionOnHash(h, ctx, tableType, base);
+ if (dict == usingExtDict) {
+ if (match < (const BYTE *)source) {
+ refDelta = dictDelta;
+ lowLimit = dictionary;
+ } else {
+ refDelta = 0;
+ lowLimit = (const BYTE *)source;
+ }
+ }
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
+
+ } while (((dictIssue == dictSmall) ? (match < lowRefLimit) : 0) ||
+ ((tableType == byU16) ? 0 : (match + MAX_DISTANCE < ip)) ||
+ (LZ4_read32(match + refDelta) != LZ4_read32(ip)));
+ }
+
+ /* Catch up */
+ while ((ip > anchor) && (match + refDelta > lowLimit) && (unlikely(ip[-1] == match[refDelta - 1]))) {
+ ip--;
+ match--;
+ }
+
+ {
+ /* Encode Literal length */
+ unsigned litLength = (unsigned)(ip - anchor);
+ token = op++;
+ if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength / 255) > olimit)))
+ return 0; /* Check output limit */
+ if (litLength >= RUN_MASK) {
+ int len = (int)litLength - RUN_MASK;
+ *token = (RUN_MASK << ML_BITS);
+ for (; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)len;
+ } else
+ *token = (BYTE)(litLength << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_wildCopy(op, anchor, op + litLength);
+ op += litLength;
+ }
+
+ _next_match:
+ /* Encode Offset */
+ LZ4_writeLE16(op, (U16)(ip - match));
+ op += 2;
+
+ /* Encode MatchLength */
+ {
+ unsigned matchLength;
+
+ if ((dict == usingExtDict) && (lowLimit == dictionary)) {
+ const BYTE *limit;
+ match += refDelta;
+ limit = ip + (dictEnd - match);
+ if (limit > matchlimit)
+ limit = matchlimit;
+ matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, limit);
+ ip += MINMATCH + matchLength;
+ if (ip == limit) {
+ unsigned more = LZ4_count(ip, (const BYTE *)source, matchlimit);
+ matchLength += more;
+ ip += more;
+ }
+ } else {
+ matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
+ ip += MINMATCH + matchLength;
+ }
+
+ if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength >> 8) > olimit)))
+ return 0; /* Check output limit */
+ if (matchLength >= ML_MASK) {
+ *token += ML_MASK;
+ matchLength -= ML_MASK;
+ for (; matchLength >= 510; matchLength -= 510) {
+ *op++ = 255;
+ *op++ = 255;
+ }
+ if (matchLength >= 255) {
+ matchLength -= 255;
+ *op++ = 255;
+ }
+ *op++ = (BYTE)matchLength;
+ } else
+ *token += (BYTE)(matchLength);
+ }
+
+ anchor = ip;
+
+ /* Test end of chunk */
+ if (ip > mflimit)
+ break;
+
+ /* Fill table */
+ LZ4_putPosition(ip - 2, ctx, tableType, base);
+
+ /* Test next position */
+ match = LZ4_getPosition(ip, ctx, tableType, base);
+ if (dict == usingExtDict) {
+ if (match < (const BYTE *)source) {
+ refDelta = dictDelta;
+ lowLimit = dictionary;
+ } else {
+ refDelta = 0;
+ lowLimit = (const BYTE *)source;
+ }
+ }
+ LZ4_putPosition(ip, ctx, tableType, base);
+ if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1) && (match + MAX_DISTANCE >= ip) &&
+ (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
+ token = op++;
+ *token = 0;
+ goto _next_match;
+ }
+
+ /* Prepare next loop */
+ forwardH = LZ4_hashPosition(++ip, tableType);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ {
+ const size_t lastRun = (size_t)(iend - anchor);
+ if ((outputLimited) &&
+ ((op - (BYTE *)dest) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > (U32)maxOutputSize))
+ return 0; /* Check output limit */
+ if (lastRun >= RUN_MASK) {
+ size_t accumulator = lastRun - RUN_MASK;
+ *op++ = RUN_MASK << ML_BITS;
+ for (; accumulator >= 255; accumulator -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)accumulator;
+ } else {
+ *op++ = (BYTE)(lastRun << ML_BITS);
+ }
+ memcpy(op, anchor, lastRun);
+ op += lastRun;
+ }
+
+ /* End */
+ return (int)(((char *)op) - dest);
+}
+
+int LZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize,
+ int acceleration)
+{
+ LZ4_resetStream((LZ4_stream_t *)state);
+ if (acceleration < 1)
+ acceleration = ACCELERATION_DEFAULT;
+
+ if (maxOutputSize >= LZ4_compressBound(inputSize)) {
+ if (inputSize < LZ4_64Klimit)
+ return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue,
+ acceleration);
+ else
+ return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr,
+ noDict, noDictIssue, acceleration);
+ } else {
+ if (inputSize < LZ4_64Klimit)
+ return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict,
+ noDictIssue, acceleration);
+ else
+ return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput,
+ LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
+ }
+}
+
+int LZ4_compress_fast(const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
+{
+#if (HEAPMODE)
+ void *ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
+#else
+ LZ4_stream_t ctx;
+ void *ctxPtr = &ctx;
+#endif
+
+ int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
+
+#if (HEAPMODE)
+ FREEMEM(ctxPtr);
+#endif
+ return result;
+}
+
+int LZ4_compress_default(const char *source, char *dest, int inputSize, int maxOutputSize)
+{
+ return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
+}
+
+/* hidden debug function */
+/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
+int LZ4_compress_fast_force(const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
+{
+ LZ4_stream_t ctx;
+
+ LZ4_resetStream(&ctx);
+
+ if (inputSize < LZ4_64Klimit)
+ return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict,
+ noDictIssue, acceleration);
+ else
+ return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput,
+ LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
+}
+
+/********************************
+ * destSize variant
+ ********************************/
+
+static int LZ4_compress_destSize_generic(void *const ctx, const char *const src, char *const dst, int *const srcSizePtr,
+ const int targetDstSize, const tableType_t tableType)
+{
+ const BYTE *ip = (const BYTE *)src;
+ const BYTE *base = (const BYTE *)src;
+ const BYTE *lowLimit = (const BYTE *)src;
+ const BYTE *anchor = ip;
+ const BYTE *const iend = ip + *srcSizePtr;
+ const BYTE *const mflimit = iend - MFLIMIT;
+ const BYTE *const matchlimit = iend - LASTLITERALS;
+
+ BYTE *op = (BYTE *)dst;
+ BYTE *const oend = op + targetDstSize;
+ BYTE *const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
+ BYTE *const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
+ BYTE *const oMaxSeq = oMaxLit - 1 /* token */;
+
+ U32 forwardH;
+
+ /* Init conditions */
+ if (targetDstSize < 1)
+ return 0; /* Impossible to store anything */
+ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE)
+ return 0; /* Unsupported input size, too large (or negative) */
+ if ((tableType == byU16) && (*srcSizePtr >= LZ4_64Klimit))
+ return 0; /* Size too large (not within 64K limit) */
+ if (*srcSizePtr < LZ4_minLength)
+ goto _last_literals; /* Input too small, no compression (all literals) */
+
+ /* First Byte */
+ *srcSizePtr = 0;
+ LZ4_putPosition(ip, ctx, tableType, base);
+ ip++;
+ forwardH = LZ4_hashPosition(ip, tableType);
+
+ /* Main Loop */
+ for (;;) {
+ const BYTE *match;
+ BYTE *token;
+ {
+ const BYTE *forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = 1 << LZ4_skipTrigger;
+
+ /* Find a match */
+ do {
+ U32 h = forwardH;
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimit))
+ goto _last_literals;
+
+ match = LZ4_getPositionOnHash(h, ctx, tableType, base);
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
+
+ } while (((tableType == byU16) ? 0 : (match + MAX_DISTANCE < ip)) || (LZ4_read32(match) != LZ4_read32(ip)));
+ }
+
+ /* Catch up */
+ while ((ip > anchor) && (match > lowLimit) && (unlikely(ip[-1] == match[-1]))) {
+ ip--;
+ match--;
+ }
+
+ {
+ /* Encode Literal length */
+ unsigned litLength = (unsigned)(ip - anchor);
+ token = op++;
+ if (op + ((litLength + 240) / 255) + litLength > oMaxLit) {
+ /* Not enough space for a last match */
+ op--;
+ goto _last_literals;
+ }
+ if (litLength >= RUN_MASK) {
+ unsigned len = litLength - RUN_MASK;
+ *token = (RUN_MASK << ML_BITS);
+ for (; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)len;
+ } else
+ *token = (BYTE)(litLength << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_wildCopy(op, anchor, op + litLength);
+ op += litLength;
+ }
+
+ _next_match:
+ /* Encode Offset */
+ LZ4_writeLE16(op, (U16)(ip - match));
+ op += 2;
+
+ /* Encode MatchLength */
+ {
+ size_t matchLength;
+
+ matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
+
+ if (op + ((matchLength + 240) / 255) > oMaxMatch) {
+ /* Match description too long : reduce it */
+ matchLength = (15 - 1) + (oMaxMatch - op) * 255;
+ }
+ /*printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);*/
+ ip += MINMATCH + matchLength;
+
+ if (matchLength >= ML_MASK) {
+ *token += ML_MASK;
+ matchLength -= ML_MASK;
+ while (matchLength >= 255) {
+ matchLength -= 255;
+ *op++ = 255;
+ }
+ *op++ = (BYTE)matchLength;
+ } else
+ *token += (BYTE)(matchLength);
+ }
+
+ anchor = ip;
+
+ /* Test end of block */
+ if (ip > mflimit)
+ break;
+ if (op > oMaxSeq)
+ break;
+
+ /* Fill table */
+ LZ4_putPosition(ip - 2, ctx, tableType, base);
+
+ /* Test next position */
+ match = LZ4_getPosition(ip, ctx, tableType, base);
+ LZ4_putPosition(ip, ctx, tableType, base);
+ if ((match + MAX_DISTANCE >= ip) && (LZ4_read32(match) == LZ4_read32(ip))) {
+ token = op++;
+ *token = 0;
+ goto _next_match;
+ }
+
+ /* Prepare next loop */
+ forwardH = LZ4_hashPosition(++ip, tableType);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ {
+ size_t lastRunSize = (size_t)(iend - anchor);
+ if (op + 1 /* token */ + ((lastRunSize + 240) / 255) /* litLength */ + lastRunSize /* literals */ > oend) {
+ /* adapt lastRunSize to fill 'dst' */
+ lastRunSize = (oend - op) - 1;
+ lastRunSize -= (lastRunSize + 240) / 255;
+ }
+ ip = anchor + lastRunSize;
+
+ if (lastRunSize >= RUN_MASK) {
+ size_t accumulator = lastRunSize - RUN_MASK;
+ *op++ = RUN_MASK << ML_BITS;
+ for (; accumulator >= 255; accumulator -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)accumulator;
+ } else {
+ *op++ = (BYTE)(lastRunSize << ML_BITS);
+ }
+ memcpy(op, anchor, lastRunSize);
+ op += lastRunSize;
+ }
+
+ /* End */
+ *srcSizePtr = (int)(((const char *)ip) - src);
+ return (int)(((char *)op) - dst);
+}
+
+static int LZ4_compress_destSize_extState(void *state, const char *src, char *dst, int *srcSizePtr, int targetDstSize)
+{
+ LZ4_resetStream((LZ4_stream_t *)state);
+
+ if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */
+ {
+ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
+ } else {
+ if (*srcSizePtr < LZ4_64Klimit)
+ return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
+ else
+ return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize,
+ LZ4_64bits() ? byU32 : byPtr);
+ }
+}
+
+int LZ4_compress_destSize(const char *src, char *dst, int *srcSizePtr, int targetDstSize)
+{
+#if (HEAPMODE)
+ void *ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
+#else
+ LZ4_stream_t ctxBody;
+ void *ctx = &ctxBody;
+#endif
+
+ int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
+
+#if (HEAPMODE)
+ FREEMEM(ctx);
+#endif
+ return result;
+}
+
+/********************************
+ * Streaming functions
+ ********************************/
+
+LZ4_stream_t *LZ4_createStream(void)
+{
+ LZ4_stream_t *lz4s = (LZ4_stream_t *)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
+ LZ4_STATIC_ASSERT(
+ LZ4_STREAMSIZE >=
+ sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
+ LZ4_resetStream(lz4s);
+ return lz4s;
+}
+
+void LZ4_resetStream(LZ4_stream_t *LZ4_stream) { MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); }
+
+int LZ4_freeStream(LZ4_stream_t *LZ4_stream)
+{
+ FREEMEM(LZ4_stream);
+ return (0);
+}
+
+#define HASH_UNIT sizeof(size_t)
+int LZ4_loadDict(LZ4_stream_t *LZ4_dict, const char *dictionary, int dictSize)
+{
+ LZ4_stream_t_internal *dict = (LZ4_stream_t_internal *)LZ4_dict;
+ const BYTE *p = (const BYTE *)dictionary;
+ const BYTE *const dictEnd = p + dictSize;
+ const BYTE *base;
+
+ if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */
+ LZ4_resetStream(LZ4_dict);
+
+ if (dictSize < (int)HASH_UNIT) {
+ dict->dictionary = NULL;
+ dict->dictSize = 0;
+ return 0;
+ }
+
+ if ((dictEnd - p) > 64 KB)
+ p = dictEnd - 64 KB;
+ dict->currentOffset += 64 KB;
+ base = p - dict->currentOffset;
+ dict->dictionary = p;
+ dict->dictSize = (U32)(dictEnd - p);
+ dict->currentOffset += dict->dictSize;
+
+ while (p <= dictEnd - HASH_UNIT) {
+ LZ4_putPosition(p, dict->hashTable, byU32, base);
+ p += 3;
+ }
+
+ return dict->dictSize;
+}
+
+static void LZ4_renormDictT(LZ4_stream_t_internal *LZ4_dict, const BYTE *src)
+{
+ if ((LZ4_dict->currentOffset > 0x80000000) ||
+ ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */
+ {
+ /* rescale hash table */
+ U32 delta = LZ4_dict->currentOffset - 64 KB;
+ const BYTE *dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
+ int i;
+ for (i = 0; i < HASH_SIZE_U32; i++) {
+ if (LZ4_dict->hashTable[i] < delta)
+ LZ4_dict->hashTable[i] = 0;
+ else
+ LZ4_dict->hashTable[i] -= delta;
+ }
+ LZ4_dict->currentOffset = 64 KB;
+ if (LZ4_dict->dictSize > 64 KB)
+ LZ4_dict->dictSize = 64 KB;
+ LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
+ }
+}
+
+int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source, char *dest, int inputSize,
+ int maxOutputSize, int acceleration)
+{
+ LZ4_stream_t_internal *streamPtr = (LZ4_stream_t_internal *)LZ4_stream;
+ const BYTE *const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+
+ const BYTE *smallest = (const BYTE *)source;
+ if (streamPtr->initCheck)
+ return 0; /* Uninitialized structure detected */
+ if ((streamPtr->dictSize > 0) && (smallest > dictEnd))
+ smallest = dictEnd;
+ LZ4_renormDictT(streamPtr, smallest);
+ if (acceleration < 1)
+ acceleration = ACCELERATION_DEFAULT;
+
+ /* Check overlapping input/dictionary space */
+ {
+ const BYTE *sourceEnd = (const BYTE *)source + inputSize;
+ if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
+ streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
+ if (streamPtr->dictSize > 64 KB)
+ streamPtr->dictSize = 64 KB;
+ if (streamPtr->dictSize < 4)
+ streamPtr->dictSize = 0;
+ streamPtr->dictionary = dictEnd - streamPtr->dictSize;
+ }
+ }
+
+ /* prefix mode : source data follows dictionary */
+ if (dictEnd == (const BYTE *)source) {
+ int result;
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ withPrefix64k, dictSmall, acceleration);
+ else
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ withPrefix64k, noDictIssue, acceleration);
+ streamPtr->dictSize += (U32)inputSize;
+ streamPtr->currentOffset += (U32)inputSize;
+ return result;
+ }
+
+ /* external dictionary mode */
+ {
+ int result;
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ usingExtDict, dictSmall, acceleration);
+ else
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ usingExtDict, noDictIssue, acceleration);
+ streamPtr->dictionary = (const BYTE *)source;
+ streamPtr->dictSize = (U32)inputSize;
+ streamPtr->currentOffset += (U32)inputSize;
+ return result;
+ }
+}
+
+/* Hidden debug function, to force external dictionary mode */
+int LZ4_compress_forceExtDict(LZ4_stream_t *LZ4_dict, const char *source, char *dest, int inputSize)
+{
+ LZ4_stream_t_internal *streamPtr = (LZ4_stream_t_internal *)LZ4_dict;
+ int result;
+ const BYTE *const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+
+ const BYTE *smallest = dictEnd;
+ if (smallest > (const BYTE *)source)
+ smallest = (const BYTE *)source;
+ LZ4_renormDictT((LZ4_stream_t_internal *)LZ4_dict, smallest);
+
+ result =
+ LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
+
+ streamPtr->dictionary = (const BYTE *)source;
+ streamPtr->dictSize = (U32)inputSize;
+ streamPtr->currentOffset += (U32)inputSize;
+
+ return result;
+}
+
+int LZ4_saveDict(LZ4_stream_t *LZ4_dict, char *safeBuffer, int dictSize)
+{
+ LZ4_stream_t_internal *dict = (LZ4_stream_t_internal *)LZ4_dict;
+ const BYTE *previousDictEnd = dict->dictionary + dict->dictSize;
+
+ if ((U32)dictSize > 64 KB)
+ dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
+ if ((U32)dictSize > dict->dictSize)
+ dictSize = dict->dictSize;
+
+ memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
+
+ dict->dictionary = (const BYTE *)safeBuffer;
+ dict->dictSize = (U32)dictSize;
+
+ return dictSize;
+}
+
+/*******************************
+ * Decompression functions
+ *******************************/
+/*
+ * This generic decompression function cover all use cases.
+ * It shall be instantiated several times, using different sets of directives
+ * Note that it is essential this generic function is really inlined,
+ * in order to remove useless branches during compilation optimization.
+ */
+FORCE_INLINE int
+LZ4_decompress_generic(const char *const source, char *const dest, int inputSize,
+ int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
+
+ int endOnInput, /* endOnOutputSize, endOnInputSize */
+ int partialDecoding, /* full, partial */
+ int targetOutputSize, /* only used if partialDecoding==partial */
+ int dict, /* noDict, withPrefix64k, usingExtDict */
+ const BYTE *const lowPrefix, /* == dest if dict == noDict */
+ const BYTE *const dictStart, /* only if dict==usingExtDict */
+ const size_t dictSize /* note : = 0 if noDict */
+)
+{
+ /* Local Variables */
+ const BYTE *ip = (const BYTE *)source;
+ const BYTE *const iend = ip + inputSize;
+
+ BYTE *op = (BYTE *)dest;
+ BYTE *const oend = op + outputSize;
+ BYTE *cpy;
+ BYTE *oexit = op + targetOutputSize;
+ const BYTE *const lowLimit = lowPrefix - dictSize;
+
+ const BYTE *const dictEnd = (const BYTE *)dictStart + dictSize;
+ const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
+ const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
+
+ const int safeDecode = (endOnInput == endOnInputSize);
+ const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
+
+ /* Special cases */
+ if ((partialDecoding) && (oexit > oend - MFLIMIT))
+ oexit = oend - MFLIMIT; /* targetOutputSize too high => decode everything */
+ if ((endOnInput) && (unlikely(outputSize == 0)))
+ return ((inputSize == 1) && (*ip == 0)) ? 0 : -1; /* Empty output buffer */
+ if ((!endOnInput) && (unlikely(outputSize == 0)))
+ return (*ip == 0 ? 1 : -1);
+
+ /* Main Loop */
+ while (1) {
+ unsigned token;
+ size_t length;
+ const BYTE *match;
+
+ /* get literal length */
+ token = *ip++;
+ if ((length = (token >> ML_BITS)) == RUN_MASK) {
+ unsigned s;
+ do {
+ s = *ip++;
+ length += s;
+ } while (likely((endOnInput) ? ip < iend - RUN_MASK : 1) && (s == 255));
+ if ((safeDecode) && unlikely((size_t)(op + length) < (size_t)(op)))
+ goto _output_error; /* overflow detection */
+ if ((safeDecode) && unlikely((size_t)(ip + length) < (size_t)(ip)))
+ goto _output_error; /* overflow detection */
+ }
+
+ /* copy literals */
+ cpy = op + length;
+ if (((endOnInput) &&
+ ((cpy > (partialDecoding ? oexit : oend - MFLIMIT)) || (ip + length > iend - (2 + 1 + LASTLITERALS)))) ||
+ ((!endOnInput) && (cpy > oend - COPYLENGTH))) {
+ if (partialDecoding) {
+ if (cpy > oend)
+ goto _output_error; /* Error : write attempt beyond end of output buffer */
+ if ((endOnInput) && (ip + length > iend))
+ goto _output_error; /* Error : read attempt beyond end of input buffer */
+ } else {
+ if ((!endOnInput) && (cpy != oend))
+ goto _output_error; /* Error : block decoding must stop exactly there */
+ if ((endOnInput) && ((ip + length != iend) || (cpy > oend)))
+ goto _output_error; /* Error : input must be consumed */
+ }
+ memcpy(op, ip, length);
+ ip += length;
+ op += length;
+ break; /* Necessarily EOF, due to parsing restrictions */
+ }
+ LZ4_wildCopy(op, ip, cpy);
+ ip += length;
+ op = cpy;
+
+ /* get offset */
+ match = cpy - LZ4_readLE16(ip);
+ ip += 2;
+ if ((checkOffset) && (unlikely(match < lowLimit)))
+ goto _output_error; /* Error : offset outside destination buffer */
+
+ /* get matchlength */
+ length = token & ML_MASK;
+ if (length == ML_MASK) {
+ unsigned s;
+ do {
+ if ((endOnInput) && (ip > iend - LASTLITERALS))
+ goto _output_error;
+ s = *ip++;
+ length += s;
+ } while (s == 255);
+ if ((safeDecode) && unlikely((size_t)(op + length) < (size_t)op))
+ goto _output_error; /* overflow detection */
+ }
+ length += MINMATCH;
+
+ /* check external dictionary */
+ if ((dict == usingExtDict) && (match < lowPrefix)) {
+ if (unlikely(op + length > oend - LASTLITERALS))
+ goto _output_error; /* doesn't respect parsing restriction */
+
+ if (length <= (size_t)(lowPrefix - match)) {
+ /* match can be copied as a single segment from external dictionary */
+ match = dictEnd - (lowPrefix - match);
+ memmove(op, match, length);
+ op += length;
+ } else {
+ /* match encompass external dictionary and current segment */
+ size_t copySize = (size_t)(lowPrefix - match);
+ memcpy(op, dictEnd - copySize, copySize);
+ op += copySize;
+ copySize = length - copySize;
+ if (copySize > (size_t)(op - lowPrefix)) /* overlap within current segment */
+ {
+ BYTE *const endOfMatch = op + copySize;
+ const BYTE *copyFrom = lowPrefix;
+ while (op < endOfMatch)
+ *op++ = *copyFrom++;
+ } else {
+ memcpy(op, lowPrefix, copySize);
+ op += copySize;
+ }
+ }
+ continue;
+ }
+
+ /* copy repeated sequence */
+ cpy = op + length;
+ if (unlikely((op - match) < 8)) {
+ const size_t dec64 = dec64table[op - match];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[op - match];
+ LZ4_copy4(op + 4, match);
+ op += 8;
+ match -= dec64;
+ } else {
+ LZ4_copy8(op, match);
+ op += 8;
+ match += 8;
+ }
+
+ if (unlikely(cpy > oend - 12)) {
+ if (cpy > oend - LASTLITERALS)
+ goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
+ if (op < oend - 8) {
+ LZ4_wildCopy(op, match, oend - 8);
+ match += (oend - 8) - op;
+ op = oend - 8;
+ }
+ while (op < cpy)
+ *op++ = *match++;
+ } else
+ LZ4_wildCopy(op, match, cpy);
+ op = cpy; /* correction */
+ }
+
+ /* end of decoding */
+ if (endOnInput)
+ return (int)(((char *)op) - dest); /* Nb of output bytes decoded */
+ else
+ return (int)(((const char *)ip) - source); /* Nb of input bytes read */
+
+ /* Overflow error detected */
+_output_error:
+ return (int)(-(((const char *)ip) - source)) - 1;
+}
+
+int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict,
+ (BYTE *)dest, NULL, 0);
+}
+
+int LZ4_decompress_safe_partial(const char *source, char *dest, int compressedSize, int targetOutputSize,
+ int maxDecompressedSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial,
+ targetOutputSize, noDict, (BYTE *)dest, NULL, 0);
+}
+
+int LZ4_decompress_fast(const char *source, char *dest, int originalSize)
+{
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k,
+ (BYTE *)(dest - 64 KB), NULL, 64 KB);
+}
+
+/* streaming decompression functions */
+
+typedef struct
+{
+ const BYTE *externalDict;
+ size_t extDictSize;
+ const BYTE *prefixEnd;
+ size_t prefixSize;
+} LZ4_streamDecode_t_internal;
+
+/*
+ * If you prefer dynamic allocation methods,
+ * LZ4_createStreamDecode()
+ * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
+ */
+LZ4_streamDecode_t *LZ4_createStreamDecode(void)
+{
+ LZ4_streamDecode_t *lz4s = (LZ4_streamDecode_t *)ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
+ return lz4s;
+}
+
+int LZ4_freeStreamDecode(LZ4_streamDecode_t *LZ4_stream)
+{
+ FREEMEM(LZ4_stream);
+ return 0;
+}
+
+/*
+ * LZ4_setStreamDecode
+ * Use this function to instruct where to find the dictionary
+ * This function is not necessary if previous data is still available where it was decoded.
+ * Loading a size of 0 is allowed (same effect as no dictionary).
+ * Return : 1 if OK, 0 if error
+ */
+int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize)
+{
+ LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *)LZ4_streamDecode;
+ lz4sd->prefixSize = (size_t)dictSize;
+ lz4sd->prefixEnd = (const BYTE *)dictionary + dictSize;
+ lz4sd->externalDict = NULL;
+ lz4sd->extDictSize = 0;
+ return 1;
+}
+
+/*
+*_continue() :
+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
+ Previously decoded blocks must still be available at the memory position where they were decoded.
+ If it's not possible, save the relevant part of decoded data into a safe buffer,
+ and indicate where it stands using LZ4_setStreamDecode()
+*/
+int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
+ int compressedSize, int maxOutputSize)
+{
+ LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *)LZ4_streamDecode;
+ int result;
+
+ if (lz4sd->prefixEnd == (BYTE *)dest) {
+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0,
+ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict,
+ lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize += result;
+ lz4sd->prefixEnd += result;
+ } else {
+ lz4sd->extDictSize = lz4sd->prefixSize;
+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0,
+ usingExtDict, (BYTE *)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize = result;
+ lz4sd->prefixEnd = (BYTE *)dest + result;
+ }
+
+ return result;
+}
+
+int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest, int originalSize)
+{
+ LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *)LZ4_streamDecode;
+ int result;
+
+ if (lz4sd->prefixEnd == (BYTE *)dest) {
+ result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict,
+ lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize += originalSize;
+ lz4sd->prefixEnd += originalSize;
+ } else {
+ lz4sd->extDictSize = lz4sd->prefixSize;
+ lz4sd->externalDict = (BYTE *)dest - lz4sd->extDictSize;
+ result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict,
+ (BYTE *)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize = originalSize;
+ lz4sd->prefixEnd = (BYTE *)dest + originalSize;
+ }
+
+ return result;
+}
+
+/*
+Advanced decoding functions :
+*_usingDict() :
+ These decoding functions work the same as "_continue" ones,
+ the dictionary must be explicitly provided within parameters
+*/
+
+FORCE_INLINE int LZ4_decompress_usingDict_generic(const char *source, char *dest, int compressedSize, int maxOutputSize,
+ int safe, const char *dictStart, int dictSize)
+{
+ if (dictSize == 0)
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE *)dest,
+ NULL, 0);
+ if (dictStart + dictSize == dest) {
+ if (dictSize >= (int)(64 KB - 1))
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k,
+ (BYTE *)dest - 64 KB, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict,
+ (BYTE *)dest - dictSize, NULL, 0);
+ }
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict,
+ (BYTE *)dest, (const BYTE *)dictStart, dictSize);
+}
+
+int LZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxOutputSize,
+ const char *dictStart, int dictSize)
+{
+ return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
+}
+
+int LZ4_decompress_fast_usingDict(const char *source, char *dest, int originalSize, const char *dictStart, int dictSize)
+{
+ return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
+}
+
+/* debug function */
+int LZ4_decompress_safe_forceExtDict(const char *source, char *dest, int compressedSize, int maxOutputSize,
+ const char *dictStart, int dictSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict,
+ (BYTE *)dest, (const BYTE *)dictStart, dictSize);
+}
+
+/***************************************************
+ * Obsolete Functions
+ ***************************************************/
+/* obsolete compression functions */
+int LZ4_compress_limitedOutput(const char *source, char *dest, int inputSize, int maxOutputSize)
+{
+ return LZ4_compress_default(source, dest, inputSize, maxOutputSize);
+}
+int LZ4_compress(const char *source, char *dest, int inputSize)
+{
+ return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize));
+}
+int LZ4_compress_limitedOutput_withState(void *state, const char *src, char *dst, int srcSize, int dstSize)
+{
+ return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1);
+}
+int LZ4_compress_withState(void *state, const char *src, char *dst, int srcSize)
+{
+ return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1);
+}
+int LZ4_compress_limitedOutput_continue(LZ4_stream_t *LZ4_stream, const char *src, char *dst, int srcSize,
+ int maxDstSize)
+{
+ return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1);
+}
+int LZ4_compress_continue(LZ4_stream_t *LZ4_stream, const char *source, char *dest, int inputSize)
+{
+ return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1);
+}
+
+/*
+These function names are deprecated and should no longer be used.
+They are only provided here for compatibility with older user programs.
+- LZ4_uncompress is totally equivalent to LZ4_decompress_fast
+- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
+*/
+int LZ4_uncompress(const char *source, char *dest, int outputSize)
+{
+ return LZ4_decompress_fast(source, dest, outputSize);
+}
+int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize)
+{
+ return LZ4_decompress_safe(source, dest, isize, maxOutputSize);
+}
+
+/* Obsolete Streaming functions */
+
+int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
+
+static void LZ4_init(LZ4_stream_t_internal *lz4ds, BYTE *base)
+{
+ MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE);
+ lz4ds->bufferStart = base;
+}
+
+int LZ4_resetStreamState(void *state, char *inputBuffer)
+{
+ if ((((size_t)state) & 3) != 0)
+ return 1; /* Error : pointer is not aligned on 4-bytes boundary */
+ LZ4_init((LZ4_stream_t_internal *)state, (BYTE *)inputBuffer);
+ return 0;
+}
+
+void *LZ4_create(char *inputBuffer)
+{
+ void *lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64);
+ LZ4_init((LZ4_stream_t_internal *)lz4ds, (BYTE *)inputBuffer);
+ return lz4ds;
+}
+
+char *LZ4_slideInputBuffer(void *LZ4_Data)
+{
+ LZ4_stream_t_internal *ctx = (LZ4_stream_t_internal *)LZ4_Data;
+ int dictSize = LZ4_saveDict((LZ4_stream_t *)LZ4_Data, (char *)ctx->bufferStart, 64 KB);
+ return (char *)(ctx->bufferStart + dictSize);
+}
+
+/* Obsolete streaming decompression functions */
+
+int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest, int compressedSize, int maxOutputSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k,
+ (BYTE *)dest - 64 KB, NULL, 64 KB);
+}
+
+int LZ4_decompress_fast_withPrefix64k(const char *source, char *dest, int originalSize)
+{
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k,
+ (BYTE *)dest - 64 KB, NULL, 64 KB);
+}
+
+#endif /* LZ4_COMMONDEFS_ONLY */
diff --git a/libs/fst/lz4.h b/libs/fst/lz4.h
new file mode 100644
index 000000000..929cf02ca
--- /dev/null
+++ b/libs/fst/lz4.h
@@ -0,0 +1,367 @@
+/*
+ LZ4 - Fast LZ compression algorithm
+ Header File
+ Copyright (C) 2011-2015, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ SPDX-License-Identifier: BSD-2-Clause
+
+ You can contact the author at :
+ - LZ4 source repository : https://github.com/Cyan4973/lz4
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+#pragma once
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * lz4.h provides block compression functions, and gives full buffer control to programmer.
+ * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
+ * and can let the library handle its own memory, please use lz4frame.h instead.
+ */
+
+/**************************************
+ * Version
+ **************************************/
+#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
+#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
+#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
+#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR * 100 * 100 + LZ4_VERSION_MINOR * 100 + LZ4_VERSION_RELEASE)
+int LZ4_versionNumber(void);
+
+/**************************************
+ * Tuning parameter
+ **************************************/
+/*
+ * LZ4_MEMORY_USAGE :
+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+ * Increasing memory usage improves compression ratio
+ * Reduced memory usage can improve speed, due to cache effect
+ * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
+ */
+#define LZ4_MEMORY_USAGE 14
+
+/**************************************
+ * Simple Functions
+ **************************************/
+
+int LZ4_compress_default(const char *source, char *dest, int sourceSize, int maxDestSize);
+int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize);
+
+/*
+LZ4_compress_default() :
+ Compresses 'sourceSize' bytes from buffer 'source'
+ into already allocated 'dest' buffer of size 'maxDestSize'.
+ Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
+ It also runs faster, so it's a recommended setting.
+ If the function cannot compress 'source' into a more limited 'dest' budget,
+ compression stops *immediately*, and the function result is zero.
+ As a consequence, 'dest' content is not valid.
+ This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
+ sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
+ maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
+ return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
+ or 0 if compression fails
+
+LZ4_decompress_safe() :
+ compressedSize : is the precise full size of the compressed block.
+ maxDecompressedSize : is the size of destination buffer, which must be already allocated.
+ return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
+ If destination buffer is not large enough, decoding will stop and output an error code (<0).
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ This function is protected against buffer overflow exploits, including malicious data packets.
+ It never writes outside output buffer, nor reads outside input buffer.
+*/
+
+/**************************************
+ * Advanced Functions
+ **************************************/
+#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
+#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize) / 255) + 16)
+
+/*
+LZ4_compressBound() :
+ Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
+ This function is primarily useful for memory allocation purposes (destination buffer size).
+ Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
+ Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
+ inputSize : max supported value is LZ4_MAX_INPUT_SIZE
+ return : maximum output size in a "worst case" scenario
+ or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
+*/
+int LZ4_compressBound(int inputSize);
+
+/*
+LZ4_compress_fast() :
+ Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
+ The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
+ It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
+ An acceleration value of "1" is the same as regular LZ4_compress_default()
+ Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
+*/
+int LZ4_compress_fast(const char *source, char *dest, int sourceSize, int maxDestSize, int acceleration);
+
+/*
+LZ4_compress_fast_extState() :
+ Same compression function, just using an externally allocated memory space to store compression state.
+ Use LZ4_sizeofState() to know how much memory must be allocated,
+ and allocate it on 8-bytes boundaries (using malloc() typically).
+ Then, provide it as 'void* state' to compression function.
+*/
+int LZ4_sizeofState(void);
+int LZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxDestSize,
+ int acceleration);
+
+/*
+LZ4_compress_destSize() :
+ Reverse the logic, by compressing as much data as possible from 'source' buffer
+ into already allocated buffer 'dest' of size 'targetDestSize'.
+ This function either compresses the entire 'source' content into 'dest' if it's large enough,
+ or fill 'dest' buffer completely with as much data as possible from 'source'.
+ *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
+ New value is necessarily <= old value.
+ return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
+ or 0 if compression fails
+*/
+int LZ4_compress_destSize(const char *source, char *dest, int *sourceSizePtr, int targetDestSize);
+
+/*
+LZ4_decompress_fast() :
+ originalSize : is the original and therefore uncompressed size
+ return : the number of bytes read from the source buffer (in other words, the compressed size)
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
+ note : This function fully respect memory boundaries for properly formed compressed data.
+ It is a bit faster than LZ4_decompress_safe().
+ However, it does not provide any protection against intentionally modified data stream (malicious input).
+ Use this function in trusted environment only (data to decode comes from a trusted source).
+*/
+int LZ4_decompress_fast(const char *source, char *dest, int originalSize);
+
+/*
+LZ4_decompress_safe_partial() :
+ This function decompress a compressed block of size 'compressedSize' at position 'source'
+ into destination buffer 'dest' of size 'maxDecompressedSize'.
+ The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
+ reducing decompression time.
+ return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
+ Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
+ Always control how many bytes were decoded.
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ This function never writes outside of output buffer, and never reads outside of input buffer. It is
+therefore protected against malicious data packets
+*/
+int LZ4_decompress_safe_partial(const char *source, char *dest, int compressedSize, int targetOutputSize,
+ int maxDecompressedSize);
+
+/***********************************************
+ * Streaming Compression Functions
+ ***********************************************/
+#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE - 3)) + 4)
+#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
+/*
+ * LZ4_stream_t
+ * information structure to track an LZ4 stream.
+ * important : init this structure content before first use !
+ * note : only allocated directly the structure if you are statically linking LZ4
+ * If you are using liblz4 as a DLL, please use below construction methods instead.
+ */
+typedef struct
+{
+ long long table[LZ4_STREAMSIZE_U64];
+} LZ4_stream_t;
+
+/*
+ * LZ4_resetStream
+ * Use this function to init an allocated LZ4_stream_t structure
+ */
+void LZ4_resetStream(LZ4_stream_t *streamPtr);
+
+/*
+ * LZ4_createStream will allocate and initialize an LZ4_stream_t structure
+ * LZ4_freeStream releases its memory.
+ * In the context of a DLL (liblz4), please use these methods rather than the static struct.
+ * They are more future proof, in case of a change of LZ4_stream_t size.
+ */
+LZ4_stream_t *LZ4_createStream(void);
+int LZ4_freeStream(LZ4_stream_t *streamPtr);
+
+/*
+ * LZ4_loadDict
+ * Use this function to load a static dictionary into LZ4_stream.
+ * Any previous data will be forgotten, only 'dictionary' will remain in memory.
+ * Loading a size of 0 is allowed.
+ * Return : dictionary size, in bytes (necessarily <= 64 KB)
+ */
+int LZ4_loadDict(LZ4_stream_t *streamPtr, const char *dictionary, int dictSize);
+
+/*
+ * LZ4_compress_fast_continue
+ * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression
+ * ratio. Important : Previous data blocks are assumed to still be present and unmodified ! 'dst' buffer must be already
+ * allocated. If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. If
+ * not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
+ */
+int LZ4_compress_fast_continue(LZ4_stream_t *streamPtr, const char *src, char *dst, int srcSize, int maxDstSize,
+ int acceleration);
+
+/*
+ * LZ4_saveDict
+ * If previously compressed data block is not guaranteed to remain available at its memory location
+ * save it into a safer place (char* safeBuffer)
+ * Note : you don't need to call LZ4_loadDict() afterwards,
+ * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
+ * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
+ */
+int LZ4_saveDict(LZ4_stream_t *streamPtr, char *safeBuffer, int dictSize);
+
+/************************************************
+ * Streaming Decompression Functions
+ ************************************************/
+
+#define LZ4_STREAMDECODESIZE_U64 4
+#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
+typedef struct
+{
+ unsigned long long table[LZ4_STREAMDECODESIZE_U64];
+} LZ4_streamDecode_t;
+/*
+ * LZ4_streamDecode_t
+ * information structure to track an LZ4 stream.
+ * init this structure content using LZ4_setStreamDecode or memset() before first use !
+ *
+ * In the context of a DLL (liblz4) please prefer usage of construction methods below.
+ * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
+ * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
+ * LZ4_freeStreamDecode releases its memory.
+ */
+LZ4_streamDecode_t *LZ4_createStreamDecode(void);
+int LZ4_freeStreamDecode(LZ4_streamDecode_t *LZ4_stream);
+
+/*
+ * LZ4_setStreamDecode
+ * Use this function to instruct where to find the dictionary.
+ * Setting a size of 0 is allowed (same effect as reset).
+ * Return : 1 if OK, 0 if error
+ */
+int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize);
+
+/*
+*_continue() :
+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
+ Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
+ In the case of a ring buffers, decoding buffer must be either :
+ - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
+ In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
+ - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
+ maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
+ In which case, encoding and decoding buffers do not need to be synchronized,
+ and encoding ring buffer can have any size, including small ones ( < 64 KB).
+ - _At least_ 64 KB + 8 bytes + maxBlockSize.
+ In which case, encoding and decoding buffers do not need to be synchronized,
+ and encoding ring buffer can have any size, including larger than decoding buffer.
+ Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
+ and indicate where it is saved using LZ4_setStreamDecode()
+*/
+int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
+ int compressedSize, int maxDecompressedSize);
+int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
+ int originalSize);
+
+/*
+Advanced decoding functions :
+*_usingDict() :
+ These decoding functions work the same as
+ a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
+ They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
+*/
+int LZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxDecompressedSize,
+ const char *dictStart, int dictSize);
+int LZ4_decompress_fast_usingDict(const char *source, char *dest, int originalSize, const char *dictStart,
+ int dictSize);
+
+/**************************************
+ * Obsolete Functions
+ **************************************/
+/* Deprecate Warnings */
+/* Should these warnings messages be a problem,
+ it is generally possible to disable them,
+ with -Wno-deprecated-declarations for gcc
+ or _CRT_SECURE_NO_WARNINGS in Visual for example.
+ You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
+#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
+#define LZ4_DEPRECATE_WARNING_DEFBLOCK
+#define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
+#define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif (LZ4_GCC_VERSION >= 301)
+#define LZ4_DEPRECATED(message) __attribute__((deprecated))
+#elif defined(_MSC_VER)
+#define LZ4_DEPRECATED(message) __declspec(deprecated(message))
+#else
+#pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
+#define LZ4_DEPRECATED(message)
+#endif
+#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
+
+/* Obsolete compression functions */
+/* These functions are planned to start generate warnings by r131 approximately */
+int LZ4_compress(const char *source, char *dest, int sourceSize);
+int LZ4_compress_limitedOutput(const char *source, char *dest, int sourceSize, int maxOutputSize);
+int LZ4_compress_withState(void *state, const char *source, char *dest, int inputSize);
+int LZ4_compress_limitedOutput_withState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize);
+int LZ4_compress_continue(LZ4_stream_t *LZ4_streamPtr, const char *source, char *dest, int inputSize);
+int LZ4_compress_limitedOutput_continue(LZ4_stream_t *LZ4_streamPtr, const char *source, char *dest, int inputSize,
+ int maxOutputSize);
+
+/* Obsolete decompression functions */
+/* These function names are completely deprecated and must no longer be used.
+ They are only provided here for compatibility with older programs.
+ - LZ4_uncompress is the same as LZ4_decompress_fast
+ - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
+ These function prototypes are now disabled; uncomment them only if you really need them.
+ It is highly recommended to stop using these prototypes and migrate to maintained ones */
+/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
+/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
+
+/* Obsolete streaming functions; use new streaming interface whenever possible */
+LZ4_DEPRECATED("use LZ4_createStream() instead") void *LZ4_create(char *inputBuffer);
+LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
+LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void *state, char *inputBuffer);
+LZ4_DEPRECATED("use LZ4_saveDict() instead") char *LZ4_slideInputBuffer(void *state);
+
+/* Obsolete streaming decoding functions */
+LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead")
+int LZ4_decompress_safe_withPrefix64k(const char *src, char *dst, int compressedSize, int maxDstSize);
+LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead")
+int LZ4_decompress_fast_withPrefix64k(const char *src, char *dst, int originalSize);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/manual/PRESENTATION_Prog/Makefile b/manual/PRESENTATION_Prog/Makefile
index 7e3cf814b..2ac8e5bed 100644
--- a/manual/PRESENTATION_Prog/Makefile
+++ b/manual/PRESENTATION_Prog/Makefile
@@ -16,6 +16,6 @@ test1.log: my_cmd.so
mv test1.log_new test1.log
test2.log: my_cmd.so
- ../../yosys -Ql test2.log_new -m ./my_cmd.so -p 'test2' sigmap_test.v
+ ../../yosys -Ql test2.log_new -m ./my_cmd.so -p 'hierarchy -top test; test2' sigmap_test.v
mv test2.log_new test2.log
diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex
index 2d5f55749..e3055c0bc 100644
--- a/manual/command-reference-manual.tex
+++ b/manual/command-reference-manual.tex
@@ -671,6 +671,14 @@ Convert modules into blackbox modules (remove contents and set the blackbox
module attribute).
\end{lstlisting}
+\section{bmuxmap -- transform \$bmux cells to trees of \$mux cells}
+\label{cmd:bmuxmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ bmuxmap [selection]
+
+This pass transforms $bmux cells to trees of $mux cells.
+\end{lstlisting}
+
\section{bugpoint -- minimize testcases}
\label{cmd:bugpoint}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1133,6 +1141,14 @@ selected wires, thus 'deleting' module ports.
"Demote" inout ports to input or output ports, if possible.
\end{lstlisting}
+\section{demuxmap -- transform \$demux cells to \$eq + \$mux cells}
+\label{cmd:demuxmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ demuxmap [selection]
+
+This pass transforms $demux cells to a bunch of equality comparisons.
+\end{lstlisting}
+
\section{design -- save, restore and reset current design}
\label{cmd:design}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2206,6 +2222,89 @@ one-hot encoding and binary encoding is supported.
.map <old_bitpattern> <new_bitpattern>
\end{lstlisting}
+\section{glift -- create GLIFT models and optimization problems}
+\label{cmd:glift}
+\begin{lstlisting}[numbers=left,frame=single]
+ glift <command> [options] [selection]
+
+Augments the current or specified module with gate-level information flow tracking
+(GLIFT) logic using the "constructive mapping" approach. Also can set up QBF-SAT
+optimization problems in order to optimize GLIFT models or trade off precision and
+complexity.
+
+
+Commands:
+
+ -create-precise-model
+ Replaces the current or specified module with one that has corresponding "taint"
+ inputs, outputs, and internal nets along with precise taint tracking logic.
+ For example, precise taint tracking logic for an AND gate is:
+
+ y_t = a & b_t | b & a_t | a_t & b_t
+
+
+ -create-imprecise-model
+ Replaces the current or specified module with one that has corresponding "taint"
+ inputs, outputs, and internal nets along with imprecise "All OR" taint tracking
+ logic:
+
+ y_t = a_t | b_t
+
+
+ -create-instrumented-model
+ Replaces the current or specified module with one that has corresponding "taint"
+ inputs, outputs, and internal nets along with 4 varying-precision versions of taint
+ tracking logic. Which version of taint tracking logic is used for a given gate is
+ determined by a MUX selected by an $anyconst cell. By default, unless the
+ `-no-cost-model` option is provided, an additional wire named `__glift_weight` with
+ the `keep` and `minimize` attributes is added to the module along with pmuxes and
+ adders to calculate a rough estimate of the number of logic gates in the GLIFT model
+ given an assignment for the $anyconst cells. The four versions of taint tracking logic
+ for an AND gate are:
+ y_t = a & b_t | b & a_t | a_t & b_t (like `-create-precise-model`)
+ y_t = a_t | a & b_t
+ y_t = b_t | b & a_t
+ y_t = a_t | b_t (like `-create-imprecise-model`)
+
+
+Options:
+
+ -taint-constants
+ Constant values in the design are labeled as tainted.
+ (default: label constants as un-tainted)
+
+ -keep-outputs
+ Do not remove module outputs. Taint tracking outputs will appear in the module ports
+ alongside the orignal outputs.
+ (default: original module outputs are removed)
+
+ -simple-cost-model
+ Do not model logic area. Instead model the number of non-zero assignments to $anyconsts.
+ Taint tracking logic versions vary in their size, but all reduced-precision versions are
+ significantly smaller than the fully-precise version. A non-zero $anyconst assignment means
+ that reduced-precision taint tracking logic was chosen for some gate.
+ Only applicable in combination with `-create-instrumented-model`.
+ (default: use a complex model and give that wire the "keep" and "minimize" attributes)
+
+ -no-cost-model
+ Do not model taint tracking logic area and do not create a `__glift_weight` wire.
+ Only applicable in combination with `-create-instrumented-model`.
+ (default: model area and give that wire the "keep" and "minimize" attributes)
+
+ -instrument-more
+ Allow choice from more versions of (even simpler) taint tracking logic. A total
+ of 8 versions of taint tracking logic will be added per gate, including the 4
+ versions from `-create-instrumented-model` and these additional versions:
+
+ y_t = a_t
+ y_t = b_t
+ y_t = 1
+ y_t = 0
+
+ Only applicable in combination with `-create-instrumented-model`.
+ (default: do not add more versions of taint tracking logic.
+\end{lstlisting}
+
\section{greenpak4\_dffinv -- merge greenpak4 inverters and DFF/latches}
\label{cmd:greenpak4_dffinv}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2420,7 +2519,7 @@ the resulting cells to more sophisticated PAD cells.
-inpad <celltype> <in_port>[:<ext_port>]
Map module input ports to the given cell type with the
given output port name. if a 2nd portname is given, the
- signal is passed through the pad call, using the 2nd
+ signal is passed through the pad cell, using the 2nd
portname as the port facing the module port.
-outpad <celltype> <out_port>[:<ext_port>]
@@ -4815,6 +4914,16 @@ This command simulates the circuit using the given top-level module.
-vcd <filename>
write the simulation results to the given VCD file
+ -fst <filename>
+ write the simulation results to the given FST file
+
+ -aiw <filename>
+ write the simulation results to an AIGER witness file
+ (requires a *.aim file via -map)
+
+ -x
+ ignore constant x outputs in simulation file.
+
-clock <portname>
name of top-level clock input
@@ -4837,14 +4946,44 @@ This command simulates the circuit using the given top-level module.
include the specified timescale declaration in the vcd
-n <integer>
- number of cycles to simulate (default: 20)
+ number of clock cycles to simulate (default: 20)
-a
- include all nets in VCD output, not just those with public names
+ use all nets in VCD/FST operations, not just those with public names
-w
writeback mode: use final simulation state as new init state
+ -r
+ read simulation results file (file formats supported: FST)
+
+ -map <filename>
+ read file with port and latch symbols, needed for AIGER witness input
+
+ -scope
+ scope of simulation top model
+
+ -at <time>
+ sets start and stop time
+
+ -start <time>
+ start co-simulation in arbitary time (default 0)
+
+ -stop <time>
+ stop co-simulation in arbitary time (default END)
+
+ -sim
+ simulation with stimulus from FST (default)
+
+ -sim-cmp
+ co-simulation expect exact match
+
+ -sim-gold
+ co-simulation, x in simulation can match any value in FST
+
+ -sim-gate
+ co-simulation, x in FST can match any value in simulation
+
-d
enable debug output
\end{lstlisting}
@@ -5197,6 +5336,9 @@ This command runs synthesis for Anlogic FPGAs.
-nolutram
do not use EG_LOGIC_DRAM16X4 cells in output netlist
+ -nobram
+ do not use EG_PHY_BRAM or EG_PHY_BRAM32K cells in output netlist
+
The following commands are executed by this synthesis command:
@@ -5213,6 +5355,12 @@ The following commands are executed by this synthesis command:
coarse:
synth -run coarse
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/anlogic/brams.txt
+ techmap -map +/anlogic/brams_map.v
+ setundef -zero -params t:EG_PHY_BRAM
+ setundef -zero -params t:EG_PHY_BRAM32K
+
map_lutram: (skip if -nolutram)
memory_bram -rules +/anlogic/lutrams.txt
techmap -map +/anlogic/lutrams_map.v
@@ -6781,6 +6929,7 @@ The following commands are executed by this synthesis command:
write_blif -attr -param -auto-top
verilog:
+ write_verilog -noattr -nohex <file-name>
\end{lstlisting}
\section{synth\_sf2 -- synthesis for SmartFusion2 and IGLOO2 FPGAs}
@@ -7495,9 +7644,11 @@ Like -sv, but define FORMAL instead of SYNTHESIS.
Load the specified VHDL files into Verific.
- verific {-f|-F} <command-file>
+ verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal] <command-file>
Load and execute the specified command file.
+Override verilog parsing mode can be set.
+The macros YOSYS, SYNTHESIS/FORMAL, and VERIFIC are defined implicitly.
Command file parser supports following commands:
+define - defines macro
@@ -8193,6 +8344,8 @@ Inside a script the input file can also can a here-document:
Write a FIRRTL netlist of the current design.
The following commands are executed by this command:
pmuxtree
+ bmuxmap
+ demuxmap
\end{lstlisting}
\section{write\_ilang -- (deprecated) alias of write\_rtlil}
diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh
index dc4ac13e0..8b39d59e3 100644
--- a/misc/create_vcxsrc.sh
+++ b/misc/create_vcxsrc.sh
@@ -7,11 +7,20 @@ gitsha="$3"
rm -rf YosysVS-Tpl-v2.zip YosysVS
wget https://yosyshq.net/yosys/nogit/YosysVS-Tpl-v2.zip
+wget https://www.zlib.net/fossils/zlib-1.2.11.tar.gz
unzip YosysVS-Tpl-v2.zip
rm -f YosysVS-Tpl-v2.zip
-mv YosysVS "$vcxsrc"
+tar xvfz zlib-1.2.11.tar.gz
+mv YosysVS "$vcxsrc"
+mkdir -p "$vcxsrc"/yosys
+mkdir -p "$vcxsrc"/yosys/libs/zlib
+mv zlib-1.2.11/* "$vcxsrc"/yosys/libs/zlib/.
+rm -rf zlib-1.2.11
+pushd "$vcxsrc"/yosys
+ls libs/zlib/*.c | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' >> ../../srcfiles.txt
+popd
{
n=$(grep -B999 '<ItemGroup>' "$vcxsrc"/YosysVS/YosysVS.vcxproj | wc -l)
head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 917856767..16a38b511 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -18,6 +18,7 @@ OBJS += passes/cmds/setattr.o
OBJS += passes/cmds/copy.o
OBJS += passes/cmds/splice.o
OBJS += passes/cmds/scc.o
+OBJS += passes/cmds/glift.o
OBJS += passes/cmds/torder.o
OBJS += passes/cmds/logcmd.o
OBJS += passes/cmds/tee.o
diff --git a/passes/cmds/clean_zerowidth.cc b/passes/cmds/clean_zerowidth.cc
index 4e7c68093..bac6b1521 100644
--- a/passes/cmds/clean_zerowidth.cc
+++ b/passes/cmds/clean_zerowidth.cc
@@ -80,7 +80,7 @@ struct CleanZeroWidthPass : public Pass {
if (GetSize(cell->getPort(ID::Q)) == 0) {
module->remove(cell);
}
- } else if (cell->type == ID($pmux)) {
+ } else if (cell->type.in(ID($pmux), ID($bmux), ID($demux))) {
// Remove altogether if WIDTH is 0, replace with
// a connection if S_WIDTH is 0.
if (cell->getParam(ID::WIDTH).as_int() == 0) {
diff --git a/passes/cmds/glift.cc b/passes/cmds/glift.cc
new file mode 100644
index 000000000..b398c3e04
--- /dev/null
+++ b/passes/cmds/glift.cc
@@ -0,0 +1,599 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Alberto Gonzalez <boqwxp@airmail.cc>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
+#include "kernel/utils.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct GliftWorker {
+private:
+ bool is_top_module = false;
+ bool opt_create_precise_model = false, opt_create_imprecise_model = false, opt_create_instrumented_model = false;
+ bool opt_taintconstants = false, opt_keepoutputs = false, opt_simplecostmodel = false, opt_nocostmodel = false;
+ bool opt_instrumentmore = false;
+ std::vector<RTLIL::Wire *> new_taint_outputs;
+ std::vector<std::pair<RTLIL::SigSpec, RTLIL::IdString>> meta_mux_selects;
+ RTLIL::Module *module = nullptr;
+
+ const RTLIL::IdString cost_model_wire_name = ID(__glift_weight);
+ const RTLIL::IdString glift_attribute_name = ID(glift);
+
+
+ RTLIL::SigSpec get_corresponding_taint_signal(RTLIL::SigSpec sig) {
+ RTLIL::SigSpec ret;
+
+ //Get the connected wire for the cell port:
+ log_assert(sig.is_wire() || sig.is_fully_const());
+ log_assert(sig.is_wire() || sig.is_fully_const());
+
+ //Get a SigSpec for the corresponding taint signal for the cell port, creating one if necessary:
+ if (sig.is_wire()) {
+ RTLIL::Wire *w = module->wire(sig.as_wire()->name.str() + "_t");
+ if (w == nullptr) w = module->addWire(sig.as_wire()->name.str() + "_t", 1);
+ ret = w;
+ }
+ else if (sig.is_fully_const() && opt_taintconstants)
+ ret = RTLIL::State::S1;
+ else if (sig.is_fully_const())
+ ret = RTLIL::State::S0;
+ else
+ log_cmd_error("Cell port SigSpec has unexpected type.\n");
+
+ //Finally, if the cell port was a module input or output, make sure the corresponding taint signal is marked, too:
+ if(sig.is_wire() && sig.as_wire()->port_input)
+ ret.as_wire()->port_input = true;
+ if(sig.is_wire() && sig.as_wire()->port_output)
+ new_taint_outputs.push_back(ret.as_wire());
+
+ return ret;
+ }
+
+ void add_precise_GLIFT_logic(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH2 or OR2_SH2
+ bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
+ RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_1_1", port_a, false, cell->get_src_attribute());
+ RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_1_2", port_b, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_1_3", is_and? port_a : n_port_a, port_b_taint, false, cell->get_src_attribute());
+ auto subexpr2 = module->And(cell->name.str() + "_t_1_4", is_and? port_b : n_port_b, port_a_taint, false, cell->get_src_attribute());
+ auto subexpr3 = module->And(cell->name.str() + "_t_1_5", port_a_taint, port_b_taint, false, cell->get_src_attribute());
+ auto subexpr4 = module->Or(cell->name.str() + "_t_1_6", subexpr1, subexpr2, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_1_7", subexpr4, subexpr3, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_1(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH3 or OR2_SH3
+ bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
+ RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_2_1", port_a, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_2_2", is_and? port_b : n_port_a, is_and? port_a_taint : port_b_taint, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_2_3", is_and? port_b_taint : port_a_taint, subexpr1, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_2(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH4 or OR2_SH4
+ bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
+ RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_3_1", port_b, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_3_2", is_and? port_a : n_port_b, is_and? port_b_taint : port_a_taint, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_3_3", is_and? port_a_taint : port_b_taint, subexpr1, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_3(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH5 or OR2_SH5 or XR2_SH2
+ module->addOr(cell->name.str() + "_t_4_1", port_a_taint, port_b_taint, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_4(RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, port_a_taint);
+ }
+
+ void add_imprecise_GLIFT_logic_5(RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, port_b_taint);
+ }
+
+ void add_imprecise_GLIFT_logic_6(RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, RTLIL::Const(1, 1));
+ }
+
+ void add_imprecise_GLIFT_logic_7(RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, RTLIL::Const(0, 1));
+ }
+
+ void add_precise_GLIFT_mux(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_s, RTLIL::SigSpec &port_s_taint, RTLIL::SigSpec &port_y_taint) {
+ //S&At | ~S&Bt | ~A&B&St | A&~B&St | At&St | Bt&St
+ RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_4_1", port_a, false, cell->get_src_attribute());
+ RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_4_2", port_b, false, cell->get_src_attribute());
+ RTLIL::SigSpec n_port_s = module->LogicNot(cell->name.str() + "_t_4_3", port_s, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_4_4", port_s, port_a_taint, false, cell->get_src_attribute());
+ auto subexpr2 = module->And(cell->name.str() + "_t_4_5", n_port_s, port_b_taint, false, cell->get_src_attribute());
+ auto subexpr3 = module->And(cell->name.str() + "_t_4_6", n_port_a, port_b, false, cell->get_src_attribute());
+ auto subexpr4 = module->And(cell->name.str() + "_t_4_7", subexpr3, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr5 = module->And(cell->name.str() + "_t_4_8", port_a, n_port_b, false, cell->get_src_attribute());
+ auto subexpr6 = module->And(cell->name.str() + "_t_4_9", subexpr5, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr7 = module->And(cell->name.str() + "_t_4_10", port_a_taint, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr8 = module->And(cell->name.str() + "_t_4_11", port_b_taint, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr9 = module->Or(cell->name.str() + "_t_4_12", subexpr1, subexpr2, false, cell->get_src_attribute());
+ auto subexpr10 = module->Or(cell->name.str() + "_t_4_13", subexpr4, subexpr6, false, cell->get_src_attribute());
+ auto subexpr11 = module->Or(cell->name.str() + "_t_4_14", subexpr7, subexpr8, false, cell->get_src_attribute());
+ auto subexpr12 = module->Or(cell->name.str() + "_t_4_15", subexpr9, subexpr10, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_4_16", subexpr11, subexpr12, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ RTLIL::SigSpec score_metamux_select(const RTLIL::SigSpec &metamux_select, const RTLIL::IdString celltype) {
+ log_assert(metamux_select.is_wire());
+
+ if (opt_simplecostmodel) {
+ //The complex model is an area model, so a lower score should mean smaller.
+ //In this case, a nonzero hole metamux select value means less logic.
+ //Thus we should invert the ReduceOr over the metamux_select signal.
+ RTLIL::SigSpec pmux_select = module->ReduceOr(metamux_select.as_wire()->name.str() + "_nonzero", metamux_select);
+ return module->Pmux(NEW_ID, RTLIL::Const(1), RTLIL::Const(0), pmux_select, metamux_select.as_wire()->get_src_attribute());
+ } else {
+ auto select_width = metamux_select.as_wire()->width;
+
+ std::vector<RTLIL::Const> costs;
+ if (celltype == ID($_AND_) || celltype == ID($_OR_)) {
+ costs = {5, 2, 2, 1, 0, 0, 0, 0};
+ log_assert(select_width == 2 || select_width == 3);
+ log_assert(opt_instrumentmore || select_width == 2);
+ log_assert(!opt_instrumentmore || select_width == 3);
+ }
+ else if (celltype == ID($_XOR_) || celltype == ID($_XNOR_)) {
+ costs = {1, 0, 0, 0};
+ log_assert(select_width == 2);
+ }
+
+ std::vector<RTLIL::SigSpec> next_pmux_y_ports, pmux_y_ports(costs.begin(), costs.begin() + exp2(select_width));
+ for (auto i = 0; pmux_y_ports.size() > 1; ++i) {
+ for (auto j = 0; j+1 < GetSize(pmux_y_ports); j += 2) {
+ next_pmux_y_ports.emplace_back(module->Pmux(stringf("%s_mux_%d_%d", metamux_select.as_wire()->name.c_str(), i, j), pmux_y_ports[j], pmux_y_ports[j+1], metamux_select[GetSize(metamux_select) - 1 - i], metamux_select.as_wire()->get_src_attribute()));
+ }
+ if (GetSize(pmux_y_ports) % 2 == 1)
+ next_pmux_y_ports.push_back(pmux_y_ports[GetSize(pmux_y_ports) - 1]);
+ pmux_y_ports.swap(next_pmux_y_ports);
+ next_pmux_y_ports.clear();
+ }
+
+ log_assert(pmux_y_ports.size() == 1);
+ return pmux_y_ports[0];
+ }
+ }
+
+ void create_glift_logic() {
+ if (module->get_bool_attribute(glift_attribute_name))
+ return;
+
+ std::vector<RTLIL::SigSig> connections(module->connections());
+
+ for(auto &cell : module->cells().to_vector()) {
+ if (!cell->type.in({ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_MUX_), ID($_NMUX_), ID($_NOT_), ID($anyconst), ID($allconst), ID($assume), ID($assert)}) && module->design->module(cell->type) == nullptr) {
+ log_cmd_error("Unsupported cell type \"%s\" found. Run `techmap` first.\n", cell->type.c_str());
+ }
+ if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_))) {
+ const unsigned int A = 0, B = 1, Y = 2;
+ const unsigned int NUM_PORTS = 3;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::B), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[B].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ if (opt_create_precise_model)
+ add_precise_GLIFT_logic(cell, ports[A], port_taints[A], ports[B], port_taints[B], port_taints[Y]);
+ else if (opt_create_imprecise_model)
+ add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], port_taints[Y]);
+ else if (opt_create_instrumented_model) {
+ std::vector<RTLIL::SigSpec> taint_version;
+ int num_versions = opt_instrumentmore? 8 : 4;
+
+ for (auto i = 1; i <= num_versions; ++i)
+ taint_version.emplace_back(RTLIL::SigSpec(module->addWire(stringf("%s_y%d", cell->name.c_str(), i), 1)));
+
+ for (auto i = 0; i < num_versions; ++i) {
+ switch(i) {
+ case 0: add_precise_GLIFT_logic(cell, ports[A], port_taints[A], ports[B], port_taints[B], taint_version[i]);
+ break;
+ case 1: add_imprecise_GLIFT_logic_1(cell, ports[A], port_taints[A], ports[B], port_taints[B], taint_version[i]);
+ break;
+ case 2: add_imprecise_GLIFT_logic_2(cell, ports[A], port_taints[A], ports[B], port_taints[B], taint_version[i]);
+ break;
+ case 3: add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], taint_version[i]);
+ break;
+ case 4: add_imprecise_GLIFT_logic_4(port_taints[A], taint_version[i]);
+ break;
+ case 5: add_imprecise_GLIFT_logic_5(port_taints[B], taint_version[i]);
+ break;
+ case 6: add_imprecise_GLIFT_logic_6(taint_version[i]);
+ break;
+ case 7: add_imprecise_GLIFT_logic_7(taint_version[i]);
+ break;
+ default: log_assert(false);
+ }
+ }
+
+ auto select_width = log2(num_versions);
+ log_assert(exp2(select_width) == num_versions);
+ RTLIL::SigSpec meta_mux_select(module->addWire(cell->name.str() + "_sel", select_width));
+ meta_mux_selects.push_back(make_pair(meta_mux_select, cell->type));
+ module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->get_src_attribute()));
+
+ std::vector<RTLIL::SigSpec> next_meta_mux_y_ports, meta_mux_y_ports(taint_version);
+ for (auto i = 0; meta_mux_y_ports.size() > 1; ++i) {
+ for (auto j = 0; j+1 < GetSize(meta_mux_y_ports); j += 2) {
+ next_meta_mux_y_ports.emplace_back(module->Mux(stringf("%s_mux_%d_%d", cell->name.c_str(), i, j), meta_mux_y_ports[j], meta_mux_y_ports[j+1], meta_mux_select[GetSize(meta_mux_select) - 1 - i]));
+ }
+ if (GetSize(meta_mux_y_ports) % 2 == 1)
+ next_meta_mux_y_ports.push_back(meta_mux_y_ports[GetSize(meta_mux_y_ports) - 1]);
+ meta_mux_y_ports.swap(next_meta_mux_y_ports);
+ next_meta_mux_y_ports.clear();
+ }
+ log_assert(meta_mux_y_ports.size() == 1);
+ module->connect(port_taints[Y], meta_mux_y_ports[0]);
+ }
+ else log_cmd_error("This is a bug (1).\n");
+ }
+ else if (cell->type.in(ID($_XOR_), ID($_XNOR_))) {
+ const unsigned int A = 0, B = 1, Y = 2;
+ const unsigned int NUM_PORTS = 3;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::B), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[B].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ if (opt_create_precise_model || opt_create_imprecise_model)
+ add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], port_taints[Y]);
+ else if (opt_create_instrumented_model) {
+ std::vector<RTLIL::SigSpec> taint_version;
+ int num_versions = 4;
+ auto select_width = log2(num_versions);
+ log_assert(exp2(select_width) == num_versions);
+
+ for (auto i = 1; i <= num_versions; ++i)
+ taint_version.emplace_back(RTLIL::SigSpec(module->addWire(stringf("%s_y%d", cell->name.c_str(), i), 1)));
+
+ for (auto i = 0; i < num_versions; ++i) {
+ switch(i) {
+ case 0: add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], taint_version[i]);
+ break;
+ case 1: add_imprecise_GLIFT_logic_4(port_taints[A], taint_version[i]);
+ break;
+ case 2: add_imprecise_GLIFT_logic_5(port_taints[B], taint_version[i]);
+ break;
+ case 3: add_imprecise_GLIFT_logic_6(taint_version[i]);
+ break;
+ default: log_assert(false);
+ }
+ }
+
+ RTLIL::SigSpec meta_mux_select(module->addWire(cell->name.str() + "_sel", select_width));
+ meta_mux_selects.push_back(make_pair(meta_mux_select, cell->type));
+ module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->get_src_attribute()));
+
+ std::vector<RTLIL::SigSpec> next_meta_mux_y_ports, meta_mux_y_ports(taint_version);
+ for (auto i = 0; meta_mux_y_ports.size() > 1; ++i) {
+ for (auto j = 0; j+1 < GetSize(meta_mux_y_ports); j += 2) {
+ next_meta_mux_y_ports.emplace_back(module->Mux(stringf("%s_mux_%d_%d", cell->name.c_str(), i, j), meta_mux_y_ports[j], meta_mux_y_ports[j+1], meta_mux_select[GetSize(meta_mux_select) - 1 - i]));
+ }
+ if (GetSize(meta_mux_y_ports) % 2 == 1)
+ next_meta_mux_y_ports.push_back(meta_mux_y_ports[GetSize(meta_mux_y_ports) - 1]);
+ meta_mux_y_ports.swap(next_meta_mux_y_ports);
+ next_meta_mux_y_ports.clear();
+ }
+ log_assert(meta_mux_y_ports.size() == 1);
+ module->connect(port_taints[Y], meta_mux_y_ports[0]);
+ }
+ else log_cmd_error("This is a bug (2).\n");
+
+ }
+ else if (cell->type.in(ID($_MUX_), ID($_NMUX_))) {
+ const unsigned int A = 0, B = 1, S = 2, Y = 3;
+ const unsigned int NUM_PORTS = 4;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::B), cell->getPort(ID::S), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[B].size() != 1 || ports[S].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ add_precise_GLIFT_mux(cell, ports[A], port_taints[A], ports[B], port_taints[B], ports[S], port_taints[S], port_taints[Y]);
+ }
+ else if (cell->type.in(ID($_NOT_))) {
+ const unsigned int A = 0, Y = 1;
+ const unsigned int NUM_PORTS = 2;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ if (cell->type == ID($_NOT_)) {
+ module->connect(port_taints[Y], port_taints[A]);
+ }
+ else log_cmd_error("This is a bug (3).\n");
+ }
+ else if (module->design->module(cell->type) != nullptr) {
+ //User cell type
+ //This function is called on modules according to topological order, so we do not need to
+ //recurse to GLIFT model the child module. However, we need to augment the ports list
+ //with taint signals and connect the new ports to the corresponding taint signals.
+ RTLIL::Module *cell_module_def = module->design->module(cell->type);
+ dict<RTLIL::IdString, RTLIL::SigSpec> orig_ports = cell->connections();
+ log("Adding cell %s\n", cell_module_def->name.c_str());
+ for (auto &it : orig_ports) {
+ RTLIL::SigSpec port = it.second;
+ RTLIL::SigSpec port_taint = get_corresponding_taint_signal(port);
+
+ log_assert(port_taint.is_wire());
+ log_assert(std::find(cell_module_def->ports.begin(), cell_module_def->ports.end(), port_taint.as_wire()->name) != cell_module_def->ports.end());
+ cell->setPort(port_taint.as_wire()->name, port_taint);
+ }
+ }
+ else log_cmd_error("This is a bug (4).\n");
+ } //end foreach cell in cells
+
+ for (auto &conn : connections) {
+ RTLIL::SigSpec first = get_corresponding_taint_signal(conn.first);
+ RTLIL::SigSpec second = get_corresponding_taint_signal(conn.second);
+
+ module->connect(first, second);
+
+ if(conn.second.is_wire() && conn.second.as_wire()->port_input)
+ second.as_wire()->port_input = true;
+ if(conn.first.is_wire() && conn.first.as_wire()->port_output)
+ new_taint_outputs.push_back(first.as_wire());
+ } //end foreach conn in connections
+
+ //Create a rough model of area by summing the (potentially simplified) "weight" score of each meta-mux select:
+ if (!opt_nocostmodel) {
+ std::vector<RTLIL::SigSpec> meta_mux_select_sums;
+ std::vector<RTLIL::SigSpec> meta_mux_select_sums_buf;
+ for (auto &it : meta_mux_selects) {
+ meta_mux_select_sums.emplace_back(score_metamux_select(it.first, it.second));
+ }
+ for (unsigned int i = 0; meta_mux_select_sums.size() > 1; ) {
+ meta_mux_select_sums_buf.clear();
+ for (i = 0; i + 1 < meta_mux_select_sums.size(); i += 2) {
+ meta_mux_select_sums_buf.push_back(module->Add(meta_mux_select_sums[i].as_wire()->name.str() + "_add", meta_mux_select_sums[i], meta_mux_select_sums[i+1], false));
+ }
+ if (meta_mux_select_sums.size() % 2 == 1)
+ meta_mux_select_sums_buf.push_back(meta_mux_select_sums[meta_mux_select_sums.size()-1]);
+ meta_mux_select_sums.swap(meta_mux_select_sums_buf);
+ }
+ if (meta_mux_select_sums.size() > 0) {
+ meta_mux_select_sums[0].as_wire()->set_bool_attribute("\\minimize");
+ meta_mux_select_sums[0].as_wire()->set_bool_attribute("\\keep");
+ module->rename(meta_mux_select_sums[0].as_wire(), cost_model_wire_name);
+ }
+ }
+
+ //Mark new module outputs:
+ for (auto &port_name : module->ports) {
+ RTLIL::Wire *port = module->wire(port_name);
+ log_assert(port != nullptr);
+ if (is_top_module && port->port_output && !opt_keepoutputs)
+ port->port_output = false;
+ }
+ for (auto &output : new_taint_outputs)
+ output->port_output = true;
+ module->fixup_ports(); //we have some new taint signals in the module interface
+ module->set_bool_attribute(glift_attribute_name, true);
+ }
+
+public:
+ GliftWorker(RTLIL::Module *_module, bool _is_top_module, bool _opt_create_precise_model, bool _opt_create_imprecise_model, bool _opt_create_instrumented_model, bool _opt_taintconstants, bool _opt_keepoutputs, bool _opt_simplecostmodel, bool _opt_nocostmodel, bool _opt_instrumentmore) {
+ module = _module;
+ is_top_module = _is_top_module;
+ opt_create_precise_model = _opt_create_precise_model;
+ opt_create_imprecise_model = _opt_create_imprecise_model;
+ opt_create_instrumented_model = _opt_create_instrumented_model;
+ opt_taintconstants = _opt_taintconstants;
+ opt_keepoutputs = _opt_keepoutputs;
+ opt_simplecostmodel = _opt_simplecostmodel;
+ opt_nocostmodel = _opt_nocostmodel;
+ opt_instrumentmore = _opt_instrumentmore;
+
+ create_glift_logic();
+ }
+};
+
+struct GliftPass : public Pass {
+ GliftPass() : Pass("glift", "create GLIFT models and optimization problems") {}
+
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" glift <command> [options] [selection]\n");
+ log("\n");
+ log("Augments the current or specified module with gate-level information flow tracking\n");
+ log("(GLIFT) logic using the \"constructive mapping\" approach. Also can set up QBF-SAT\n");
+ log("optimization problems in order to optimize GLIFT models or trade off precision and\n");
+ log("complexity.\n");
+ log("\n");
+ log("\n");
+ log("Commands:\n");
+ log("\n");
+ log(" -create-precise-model\n");
+ log(" Replaces the current or specified module with one that has corresponding \"taint\"\n");
+ log(" inputs, outputs, and internal nets along with precise taint tracking logic.\n");
+ log(" For example, precise taint tracking logic for an AND gate is:\n");
+ log("\n");
+ log(" y_t = a & b_t | b & a_t | a_t & b_t\n");
+ log("\n");
+ log("\n");
+ log(" -create-imprecise-model\n");
+ log(" Replaces the current or specified module with one that has corresponding \"taint\"\n");
+ log(" inputs, outputs, and internal nets along with imprecise \"All OR\" taint tracking\n");
+ log(" logic:\n");
+ log("\n");
+ log(" y_t = a_t | b_t\n");
+ log("\n");
+ log("\n");
+ log(" -create-instrumented-model\n");
+ log(" Replaces the current or specified module with one that has corresponding \"taint\"\n");
+ log(" inputs, outputs, and internal nets along with 4 varying-precision versions of taint\n");
+ log(" tracking logic. Which version of taint tracking logic is used for a given gate is\n");
+ log(" determined by a MUX selected by an $anyconst cell. By default, unless the\n");
+ log(" `-no-cost-model` option is provided, an additional wire named `__glift_weight` with\n");
+ log(" the `keep` and `minimize` attributes is added to the module along with pmuxes and\n");
+ log(" adders to calculate a rough estimate of the number of logic gates in the GLIFT model\n");
+ log(" given an assignment for the $anyconst cells. The four versions of taint tracking logic\n");
+ log(" for an AND gate are:");
+ log("\n");
+ log(" y_t = a & b_t | b & a_t | a_t & b_t (like `-create-precise-model`)\n");
+ log(" y_t = a_t | a & b_t\n");
+ log(" y_t = b_t | b & a_t\n");
+ log(" y_t = a_t | b_t (like `-create-imprecise-model`)\n");
+ log("\n");
+ log("\n");
+ log("Options:\n");
+ log("\n");
+ log(" -taint-constants\n");
+ log(" Constant values in the design are labeled as tainted.\n");
+ log(" (default: label constants as un-tainted)\n");
+ log("\n");
+ log(" -keep-outputs\n");
+ log(" Do not remove module outputs. Taint tracking outputs will appear in the module ports\n");
+ log(" alongside the orignal outputs.\n");
+ log(" (default: original module outputs are removed)\n");
+ log("\n");
+ log(" -simple-cost-model\n");
+ log(" Do not model logic area. Instead model the number of non-zero assignments to $anyconsts.\n");
+ log(" Taint tracking logic versions vary in their size, but all reduced-precision versions are\n");
+ log(" significantly smaller than the fully-precise version. A non-zero $anyconst assignment means\n");
+ log(" that reduced-precision taint tracking logic was chosen for some gate.\n");
+ log(" Only applicable in combination with `-create-instrumented-model`.\n");
+ log(" (default: use a complex model and give that wire the \"keep\" and \"minimize\" attributes)\n");
+ log("\n");
+ log(" -no-cost-model\n");
+ log(" Do not model taint tracking logic area and do not create a `__glift_weight` wire.\n");
+ log(" Only applicable in combination with `-create-instrumented-model`.\n");
+ log(" (default: model area and give that wire the \"keep\" and \"minimize\" attributes)\n");
+ log("\n");
+ log(" -instrument-more\n");
+ log(" Allow choice from more versions of (even simpler) taint tracking logic. A total\n");
+ log(" of 8 versions of taint tracking logic will be added per gate, including the 4\n");
+ log(" versions from `-create-instrumented-model` and these additional versions:\n");
+ log("\n");
+ log(" y_t = a_t\n");
+ log(" y_t = b_t\n");
+ log(" y_t = 1\n");
+ log(" y_t = 0\n");
+ log("\n");
+ log(" Only applicable in combination with `-create-instrumented-model`.\n");
+ log(" (default: do not add more versions of taint tracking logic.\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ bool opt_create_precise_model = false, opt_create_imprecise_model = false, opt_create_instrumented_model = false;
+ bool opt_taintconstants = false, opt_keepoutputs = false, opt_simplecostmodel = false, opt_nocostmodel = false;
+ bool opt_instrumentmore = false;
+ log_header(design, "Executing GLIFT pass (creating and manipulating GLIFT models).\n");
+ std::vector<std::string>::size_type argidx;
+
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-create-precise-model") {
+ opt_create_precise_model = true;
+ continue;
+ }
+ if (args[argidx] == "-create-imprecise-model") {
+ opt_create_imprecise_model = true;
+ continue;
+ }
+ if (args[argidx] == "-create-instrumented-model") {
+ opt_create_instrumented_model = true;
+ continue;
+ }
+ if (args[argidx] == "-taint-constants") {
+ opt_taintconstants = true;
+ continue;
+ }
+ if (args[argidx] == "-keep-outputs") {
+ opt_keepoutputs = true;
+ continue;
+ }
+ if (args[argidx] == "-simple-cost-model") {
+ opt_simplecostmodel = true;
+ continue;
+ }
+ if (args[argidx] == "-no-cost-model") {
+ opt_nocostmodel = true;
+ continue;
+ }
+ if (args[argidx] == "-instrument-more") {
+ opt_instrumentmore = true;
+ continue;
+ }
+ break;
+ }
+ if(!opt_create_precise_model && !opt_create_imprecise_model && !opt_create_instrumented_model)
+ log_cmd_error("No command provided. See help for usage.\n");
+ if(static_cast<int>(opt_create_precise_model) + static_cast<int>(opt_create_imprecise_model) + static_cast<int>(opt_create_instrumented_model) != 1)
+ log_cmd_error("Only one command may be specified. See help for usage.\n");
+ if(opt_simplecostmodel && opt_nocostmodel)
+ log_cmd_error("Only one of `-simple-cost-model` and `-no-cost-model` may be specified. See help for usage.\n");
+ if((opt_simplecostmodel || opt_nocostmodel) && !opt_create_instrumented_model)
+ log_cmd_error("Options `-simple-cost-model` and `-no-cost-model` may only be used with `-create-instrumented-model`. See help for usage.\n");
+ extra_args(args, argidx, design);
+
+ if (GetSize(design->selected_modules()) == 0)
+ log_cmd_error("Can't operate on an empty selection!\n");
+
+ TopoSort<RTLIL::Module*, IdString::compare_ptr_by_name<RTLIL::Module>> topo_modules; //cribbed from passes/techmap/flatten.cc
+ auto worklist = design->selected_modules();
+ pool<RTLIL::IdString> non_top_modules;
+ while (!worklist.empty()) {
+ RTLIL::Module *module = *(worklist.begin());
+ worklist.erase(worklist.begin());
+ topo_modules.node(module);
+
+ for (auto cell : module->selected_cells()) {
+ RTLIL::Module *tpl = design->module(cell->type);
+ if (tpl != nullptr) {
+ if (topo_modules.database.count(tpl) == 0)
+ worklist.push_back(tpl);
+ topo_modules.edge(tpl, module);
+ non_top_modules.insert(cell->type);
+ }
+ }
+ }
+
+ if (!topo_modules.sort())
+ log_cmd_error("Cannot handle recursive module instantiations.\n");
+
+ for (auto i = 0; i < GetSize(topo_modules.sorted); ++i) {
+ RTLIL::Module *module = topo_modules.sorted[i];
+ GliftWorker(module, !non_top_modules[module->name], opt_create_precise_model, opt_create_imprecise_model, opt_create_instrumented_model, opt_taintconstants, opt_keepoutputs, opt_simplecostmodel, opt_nocostmodel, opt_instrumentmore);
+ }
+ }
+} GliftPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 14a27ed99..fffdda48e 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -117,6 +117,10 @@ struct statdata_t
}
else if (cell_type.in(ID($mux), ID($pmux)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)));
+ else if (cell_type == ID($bmux))
+ cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S)));
+ else if (cell_type == ID($demux))
+ cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S)));
else if (cell_type.in(
ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre),
ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce),
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index fed9d60c0..b1f45d5fc 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -644,22 +644,6 @@ grow_read_ports:;
log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
}
- if (port.en != State::S1 && pi.enable == 0) {
- log(" Bram port %c%d.%d has no read enable input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
- goto skip_bram_rport;
- }
- if (port.arst != State::S0) {
- log(" Bram port %c%d.%d has no async reset input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
- goto skip_bram_rport;
- }
- if (port.srst != State::S0) {
- log(" Bram port %c%d.%d has no sync reset input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
- goto skip_bram_rport;
- }
- if (!port.init_value.is_fully_undef()) {
- log(" Bram port %c%d.%d has no initial value support.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
- goto skip_bram_rport;
- }
if (non_transp && read_transp.count(pi.transp) && read_transp.at(pi.transp)) {
log(" Bram port %c%d.%d has incompatible read transparency.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
@@ -794,10 +778,18 @@ grow_read_ports:;
// Apply make_outreg and make_transp where necessary.
for (auto &pi : portinfos) {
- if (pi.make_outreg)
+ if (pi.mapped_port == -1 || pi.wrmode)
+ continue;
+ auto &port = mem.rd_ports[pi.mapped_port];
+ if (pi.make_outreg) {
mem.extract_rdff(pi.mapped_port, initvals);
+ } else if (port.clk_enable) {
+ if (!pi.enable && port.en != State::S1)
+ mem.emulate_rden(pi.mapped_port, initvals);
+ else
+ mem.emulate_reset(pi.mapped_port, true, true, true, initvals);
+ }
if (pi.make_transp) {
- auto &port = mem.rd_ports[pi.mapped_port];
for (int i = 0; i < GetSize(mem.wr_ports); i++)
if (port.transparency_mask[i])
mem.emulate_transparency(i, pi.mapped_port, initvals);
diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc
index 98b66dee3..73d674c8d 100644
--- a/passes/opt/opt_dff.cc
+++ b/passes/opt/opt_dff.cc
@@ -58,13 +58,10 @@ struct OptDffWorker
typedef std::pair<RTLIL::SigBit, bool> ctrl_t;
typedef std::set<ctrl_t> ctrls_t;
- ModWalker modwalker;
- QuickConeSat qcsat;
-
// Used as a queue.
std::vector<Cell *> dff_cells;
- OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod), modwalker(module->design, module), qcsat(modwalker) {
+ OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod) {
// Gathering two kinds of information here for every sigmapped SigBit:
//
// - bitusers: how many users it has (muxes will only be merged into FFs if this is 1, making the FF the only user)
@@ -569,100 +566,6 @@ struct OptDffWorker
changed = true;
}
- // Now check if any bit can be replaced by a constant.
- pool<int> removed_sigbits;
- for (int i = 0; i < ff.width; i++) {
- State val = ff.val_init[i];
- if (ff.has_arst)
- val = combine_const(val, ff.val_arst[i]);
- if (ff.has_srst)
- val = combine_const(val, ff.val_srst[i]);
- if (ff.has_sr) {
- if (ff.sig_clr[i] != (ff.pol_clr ? State::S0 : State::S1))
- val = combine_const(val, State::S0);
- if (ff.sig_set[i] != (ff.pol_set ? State::S0 : State::S1))
- val = combine_const(val, State::S1);
- }
- if (val == State::Sm)
- continue;
- if (ff.has_clk || ff.has_gclk) {
- if (!ff.sig_d[i].wire) {
- val = combine_const(val, ff.sig_d[i].data);
- if (val == State::Sm)
- continue;
- } else {
- if (!opt.sat)
- continue;
- // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
- if (!modwalker.has_drivers(ff.sig_d.extract(i)))
- continue;
- if (val != State::S0 && val != State::S1)
- continue;
-
- int init_sat_pi = qcsat.importSigBit(val);
- int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
- int d_sat_pi = qcsat.importSigBit(ff.sig_d[i]);
-
- qcsat.prepare();
-
- // Try to find out whether the register bit can change under some circumstances
- bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
-
- // If the register bit cannot change, we can replace it with a constant
- if (counter_example_found)
- continue;
- }
- }
- if (ff.has_aload) {
- if (!ff.sig_ad[i].wire) {
- val = combine_const(val, ff.sig_ad[i].data);
- if (val == State::Sm)
- continue;
- } else {
- if (!opt.sat)
- continue;
- // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
- if (!modwalker.has_drivers(ff.sig_ad.extract(i)))
- continue;
- if (val != State::S0 && val != State::S1)
- continue;
-
- int init_sat_pi = qcsat.importSigBit(val);
- int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
- int d_sat_pi = qcsat.importSigBit(ff.sig_ad[i]);
-
- qcsat.prepare();
-
- // Try to find out whether the register bit can change under some circumstances
- bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
-
- // If the register bit cannot change, we can replace it with a constant
- if (counter_example_found)
- continue;
- }
- }
- log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", val ? 1 : 0,
- i, log_id(cell), log_id(cell->type), log_id(module));
-
- initvals.remove_init(ff.sig_q[i]);
- module->connect(ff.sig_q[i], val);
- removed_sigbits.insert(i);
- }
- if (!removed_sigbits.empty()) {
- std::vector<int> keep_bits;
- for (int i = 0; i < ff.width; i++)
- if (!removed_sigbits.count(i))
- keep_bits.push_back(i);
- if (keep_bits.empty()) {
- module->remove(cell);
- did_something = true;
- continue;
- }
- ff = ff.slice(keep_bits);
- ff.cell = cell;
- changed = true;
- }
-
// 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_arst && !ff.has_sr && (!ff.has_srst || !ff.has_ce || ff.ce_over_srst) && !opt.nosdff) {
@@ -818,6 +721,115 @@ struct OptDffWorker
}
return did_something;
}
+
+ bool run_constbits() {
+ ModWalker modwalker(module->design, module);
+ QuickConeSat qcsat(modwalker);
+
+ // Run as a separate sub-pass, so that we don't mutate (non-FF) cells under ModWalker.
+ bool did_something = false;
+ for (auto cell : module->selected_cells()) {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+ FfData ff(&initvals, cell);
+
+ // Now check if any bit can be replaced by a constant.
+ pool<int> removed_sigbits;
+ for (int i = 0; i < ff.width; i++) {
+ State val = ff.val_init[i];
+ if (ff.has_arst)
+ val = combine_const(val, ff.val_arst[i]);
+ if (ff.has_srst)
+ val = combine_const(val, ff.val_srst[i]);
+ if (ff.has_sr) {
+ if (ff.sig_clr[i] != (ff.pol_clr ? State::S0 : State::S1))
+ val = combine_const(val, State::S0);
+ if (ff.sig_set[i] != (ff.pol_set ? State::S0 : State::S1))
+ val = combine_const(val, State::S1);
+ }
+ if (val == State::Sm)
+ continue;
+ if (ff.has_clk || ff.has_gclk) {
+ if (!ff.sig_d[i].wire) {
+ val = combine_const(val, ff.sig_d[i].data);
+ if (val == State::Sm)
+ continue;
+ } else {
+ if (!opt.sat)
+ continue;
+ // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
+ if (!modwalker.has_drivers(ff.sig_d.extract(i)))
+ continue;
+ if (val != State::S0 && val != State::S1)
+ continue;
+
+ int init_sat_pi = qcsat.importSigBit(val);
+ int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
+ int d_sat_pi = qcsat.importSigBit(ff.sig_d[i]);
+
+ qcsat.prepare();
+
+ // Try to find out whether the register bit can change under some circumstances
+ bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
+
+ // If the register bit cannot change, we can replace it with a constant
+ if (counter_example_found)
+ continue;
+ }
+ }
+ if (ff.has_aload) {
+ if (!ff.sig_ad[i].wire) {
+ val = combine_const(val, ff.sig_ad[i].data);
+ if (val == State::Sm)
+ continue;
+ } else {
+ if (!opt.sat)
+ continue;
+ // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
+ if (!modwalker.has_drivers(ff.sig_ad.extract(i)))
+ continue;
+ if (val != State::S0 && val != State::S1)
+ continue;
+
+ int init_sat_pi = qcsat.importSigBit(val);
+ int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
+ int d_sat_pi = qcsat.importSigBit(ff.sig_ad[i]);
+
+ qcsat.prepare();
+
+ // Try to find out whether the register bit can change under some circumstances
+ bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
+
+ // If the register bit cannot change, we can replace it with a constant
+ if (counter_example_found)
+ continue;
+ }
+ }
+ log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", val ? 1 : 0,
+ i, log_id(cell), log_id(cell->type), log_id(module));
+
+ initvals.remove_init(ff.sig_q[i]);
+ module->connect(ff.sig_q[i], val);
+ removed_sigbits.insert(i);
+ }
+ if (!removed_sigbits.empty()) {
+ std::vector<int> keep_bits;
+ for (int i = 0; i < ff.width; i++)
+ if (!removed_sigbits.count(i))
+ keep_bits.push_back(i);
+ if (keep_bits.empty()) {
+ module->remove(cell);
+ did_something = true;
+ continue;
+ }
+ ff = ff.slice(keep_bits);
+ ff.cell = cell;
+ ff.emit();
+ did_something = true;
+ }
+ }
+ return did_something;
+ }
};
struct OptDffPass : public Pass {
@@ -894,6 +906,8 @@ struct OptDffPass : public Pass {
OptDffWorker worker(opt, mod);
if (worker.run())
did_something = true;
+ if (worker.run_constbits())
+ did_something = true;
}
if (did_something)
diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc
index b558f547e..1a7c93fbd 100644
--- a/passes/opt/opt_reduce.cc
+++ b/passes/opt/opt_reduce.cc
@@ -100,7 +100,7 @@ struct OptReduceWorker
return;
}
- void opt_mux(RTLIL::Cell *cell)
+ void opt_pmux(RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
@@ -141,20 +141,20 @@ struct OptReduceWorker
handled_sig.insert(this_b);
}
- if (new_sig_s.size() != sig_s.size()) {
- log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
- did_something = true;
- total_count++;
- }
-
if (new_sig_s.size() == 0)
{
- module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A)));
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
module->remove(cell);
+ did_something = true;
+ total_count++;
+ return;
}
- else
- {
+
+ if (new_sig_s.size() != sig_s.size() || (new_sig_s.size() == 1 && cell->type == ID($pmux))) {
+ log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
+ did_something = true;
+ total_count++;
cell->setPort(ID::B, new_sig_b);
cell->setPort(ID::S, new_sig_s);
if (new_sig_s.size() > 1) {
@@ -166,81 +166,347 @@ struct OptReduceWorker
}
}
- void opt_mux_bits(RTLIL::Cell *cell)
+ void opt_bmux(RTLIL::Cell *cell)
{
- std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID::A)).to_sigbit_vector();
- std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID::B)).to_sigbit_vector();
- std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID::Y)).to_sigbit_vector();
+ RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
+ int width = cell->getParam(ID::WIDTH).as_int();
+
+ RTLIL::SigSpec new_sig_a, new_sig_s;
+ dict<RTLIL::SigBit, int> handled_bits;
+
+ // 0 and up: index of new_sig_s bit
+ // -1: const 0
+ // -2: const 1
+ std::vector<int> swizzle;
+
+ for (int i = 0; i < sig_s.size(); i++)
+ {
+ SigBit bit = sig_s[i];
+ if (bit == State::S0) {
+ swizzle.push_back(-1);
+ } else if (bit == State::S1) {
+ swizzle.push_back(-2);
+ } else {
+ auto it = handled_bits.find(bit);
+ if (it == handled_bits.end()) {
+ int new_idx = GetSize(new_sig_s);
+ new_sig_s.append(bit);
+ handled_bits[bit] = new_idx;
+ swizzle.push_back(new_idx);
+ } else {
+ swizzle.push_back(it->second);
+ }
+ }
+ }
+
+ for (int i = 0; i < (1 << GetSize(new_sig_s)); i++) {
+ int idx = 0;
+ for (int j = 0; j < GetSize(sig_s); j++) {
+ if (swizzle[j] == -1) {
+ // const 0.
+ } else if (swizzle[j] == -2) {
+ // const 1.
+ idx |= 1 << j;
+ } else {
+ if (i & 1 << swizzle[j])
+ idx |= 1 << j;
+ }
+ }
+ new_sig_a.append(sig_a.extract(idx * width, width));
+ }
+
+ if (new_sig_s.size() == 0)
+ {
+ module->connect(cell->getPort(ID::Y), new_sig_a);
+ assign_map.add(cell->getPort(ID::Y), new_sig_a);
+ module->remove(cell);
+ did_something = true;
+ total_count++;
+ return;
+ }
+
+ if (new_sig_s.size() == 1)
+ {
+ cell->type = ID($mux);
+ cell->setPort(ID::A, new_sig_a.extract(0, width));
+ cell->setPort(ID::B, new_sig_a.extract(width, width));
+ cell->setPort(ID::S, new_sig_s);
+ cell->parameters.erase(ID::S_WIDTH);
+ did_something = true;
+ total_count++;
+ return;
+ }
+
+ if (new_sig_s.size() != sig_s.size()) {
+ log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
+ did_something = true;
+ total_count++;
+ cell->setPort(ID::A, new_sig_a);
+ cell->setPort(ID::S, new_sig_s);
+ cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size());
+ }
+ }
+
+ void opt_demux(RTLIL::Cell *cell)
+ {
+ RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
+ int width = cell->getParam(ID::WIDTH).as_int();
+
+ RTLIL::SigSpec new_sig_y, new_sig_s;
+ dict<RTLIL::SigBit, int> handled_bits;
+
+ // 0 and up: index of new_sig_s bit
+ // -1: const 0
+ // -2: const 1
+ std::vector<int> swizzle;
+
+ for (int i = 0; i < sig_s.size(); i++)
+ {
+ SigBit bit = sig_s[i];
+ if (bit == State::S0) {
+ swizzle.push_back(-1);
+ } else if (bit == State::S1) {
+ swizzle.push_back(-2);
+ } else {
+ auto it = handled_bits.find(bit);
+ if (it == handled_bits.end()) {
+ int new_idx = GetSize(new_sig_s);
+ new_sig_s.append(bit);
+ handled_bits[bit] = new_idx;
+ swizzle.push_back(new_idx);
+ } else {
+ swizzle.push_back(it->second);
+ }
+ }
+ }
+
+ pool<int> nonzero_idx;
+
+ for (int i = 0; i < (1 << GetSize(new_sig_s)); i++) {
+ int idx = 0;
+ for (int j = 0; j < GetSize(sig_s); j++) {
+ if (swizzle[j] == -1) {
+ // const 0.
+ } else if (swizzle[j] == -2) {
+ // const 1.
+ idx |= 1 << j;
+ } else {
+ if (i & 1 << swizzle[j])
+ idx |= 1 << j;
+ }
+ }
+ log_assert(!nonzero_idx.count(idx));
+ nonzero_idx.insert(idx);
+ new_sig_y.append(sig_y.extract(idx * width, width));
+ }
+
+ if (new_sig_s.size() == sig_s.size() && sig_s.size() > 0)
+ return;
+
+ log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
+ did_something = true;
+ total_count++;
+
+ for (int i = 0; i < (1 << GetSize(sig_s)); i++) {
+ if (!nonzero_idx.count(i)) {
+ SigSpec slice = sig_y.extract(i * width, width);
+ module->connect(slice, Const(State::S0, width));
+ assign_map.add(slice, Const(State::S0, width));
+ }
+ }
+
+ if (new_sig_s.size() == 0)
+ {
+ module->connect(new_sig_y, cell->getPort(ID::A));
+ assign_map.add(new_sig_y, cell->getPort(ID::A));
+ module->remove(cell);
+ }
+ else
+ {
+ cell->setPort(ID::S, new_sig_s);
+ cell->setPort(ID::Y, new_sig_y);
+ cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size());
+ }
+ }
+
+ bool opt_mux_bits(RTLIL::Cell *cell)
+ {
+ SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ SigSpec sig_b;
+ SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ int width = GetSize(sig_y);
+
+ if (cell->type != ID($bmux))
+ sig_b = assign_map(cell->getPort(ID::B));
- std::vector<RTLIL::SigBit> new_sig_y;
RTLIL::SigSig old_sig_conn;
- std::vector<std::vector<RTLIL::SigBit>> consolidated_in_tuples;
- std::map<std::vector<RTLIL::SigBit>, RTLIL::SigBit> consolidated_in_tuples_map;
+ dict<SigSpec, SigBit> consolidated_in_tuples;
+ std::vector<int> swizzle;
- for (int i = 0; i < int(sig_y.size()); i++)
+ for (int i = 0; i < width; i++)
{
- std::vector<RTLIL::SigBit> in_tuple;
+ SigSpec in_tuple;
bool all_tuple_bits_same = true;
- in_tuple.push_back(sig_a.at(i));
- for (int j = i; j < int(sig_b.size()); j += int(sig_a.size())) {
- if (sig_b.at(j) != sig_a.at(i))
+ in_tuple.append(sig_a[i]);
+ for (int j = i; j < GetSize(sig_a); j += width) {
+ in_tuple.append(sig_a[j]);
+ if (sig_a[j] != in_tuple[0])
+ all_tuple_bits_same = false;
+ }
+ for (int j = i; j < GetSize(sig_b); j += width) {
+ in_tuple.append(sig_b[j]);
+ if (sig_b[j] != in_tuple[0])
all_tuple_bits_same = false;
- in_tuple.push_back(sig_b.at(j));
}
if (all_tuple_bits_same)
{
- old_sig_conn.first.append(sig_y.at(i));
- old_sig_conn.second.append(sig_a.at(i));
+ old_sig_conn.first.append(sig_y[i]);
+ old_sig_conn.second.append(sig_a[i]);
+ continue;
}
- else if (consolidated_in_tuples_map.count(in_tuple))
+
+ auto it = consolidated_in_tuples.find(in_tuple);
+ if (it == consolidated_in_tuples.end())
{
- old_sig_conn.first.append(sig_y.at(i));
- old_sig_conn.second.append(consolidated_in_tuples_map.at(in_tuple));
+ consolidated_in_tuples[in_tuple] = sig_y[i];
+ swizzle.push_back(i);
}
else
{
- consolidated_in_tuples_map[in_tuple] = sig_y.at(i);
- consolidated_in_tuples.push_back(in_tuple);
- new_sig_y.push_back(sig_y.at(i));
+ old_sig_conn.first.append(sig_y[i]);
+ old_sig_conn.second.append(it->second);
}
}
- if (new_sig_y.size() != sig_y.size())
+ if (GetSize(swizzle) != width)
{
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
- log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
- log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
-
- cell->setPort(ID::A, RTLIL::SigSpec());
- for (auto &in_tuple : consolidated_in_tuples) {
- RTLIL::SigSpec new_a = cell->getPort(ID::A);
- new_a.append(in_tuple.at(0));
- cell->setPort(ID::A, new_a);
+ if (cell->type != ID($bmux)) {
+ log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
+ } else {
+ log(" Old ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
}
- cell->setPort(ID::B, RTLIL::SigSpec());
- for (int i = 1; i <= cell->getPort(ID::S).size(); i++)
- for (auto &in_tuple : consolidated_in_tuples) {
- RTLIL::SigSpec new_b = cell->getPort(ID::B);
- new_b.append(in_tuple.at(i));
- cell->setPort(ID::B, new_b);
+ if (swizzle.empty()) {
+ module->remove(cell);
+ } else {
+ SigSpec new_sig_a;
+ for (int i = 0; i < GetSize(sig_a); i += width)
+ for (int j: swizzle)
+ new_sig_a.append(sig_a[i+j]);
+ cell->setPort(ID::A, new_sig_a);
+
+ if (cell->type != ID($bmux)) {
+ SigSpec new_sig_b;
+ for (int i = 0; i < GetSize(sig_b); i += width)
+ for (int j: swizzle)
+ new_sig_b.append(sig_b[i+j]);
+ cell->setPort(ID::B, new_sig_b);
}
- cell->parameters[ID::WIDTH] = RTLIL::Const(new_sig_y.size());
- cell->setPort(ID::Y, new_sig_y);
+ SigSpec new_sig_y;
+ for (int j: swizzle)
+ new_sig_y.append(sig_y[j]);
+ cell->setPort(ID::Y, new_sig_y);
+
+ cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
+
+ if (cell->type != ID($bmux)) {
+ log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
+ } else {
+ log(" New ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
+ }
+ }
- log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
- log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
+ module->connect(old_sig_conn);
+
+ did_something = true;
+ total_count++;
+ }
+ return swizzle.empty();
+ }
+
+ bool opt_demux_bits(RTLIL::Cell *cell) {
+ SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ int width = GetSize(sig_a);
+
+ RTLIL::SigSig old_sig_conn;
+
+ dict<SigBit, int> handled_bits;
+ std::vector<int> swizzle;
+
+ for (int i = 0; i < width; i++)
+ {
+ if (sig_a[i] == State::S0)
+ {
+ for (int j = i; j < GetSize(sig_y); j += width)
+ {
+ old_sig_conn.first.append(sig_y[j]);
+ old_sig_conn.second.append(State::S0);
+ }
+ continue;
+ }
+ auto it = handled_bits.find(sig_a[i]);
+ if (it == handled_bits.end())
+ {
+ handled_bits[sig_a[i]] = i;
+ swizzle.push_back(i);
+ }
+ else
+ {
+ for (int j = 0; j < GetSize(sig_y); j += width)
+ {
+ old_sig_conn.first.append(sig_y[i+j]);
+ old_sig_conn.second.append(sig_y[it->second+j]);
+ }
+ }
+ }
+
+ if (GetSize(swizzle) != width)
+ {
+ log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
+ log(" Old ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
+
+ if (swizzle.empty()) {
+ module->remove(cell);
+ } else {
+ SigSpec new_sig_a;
+ for (int j: swizzle)
+ new_sig_a.append(sig_a[j]);
+ cell->setPort(ID::A, new_sig_a);
+
+ SigSpec new_sig_y;
+ for (int i = 0; i < GetSize(sig_y); i += width)
+ for (int j: swizzle)
+ new_sig_y.append(sig_y[i+j]);
+ cell->setPort(ID::Y, new_sig_y);
+
+ cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
+
+ log(" New ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
+ }
+
+ log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
module->connect(old_sig_conn);
did_something = true;
total_count++;
}
+ return swizzle.empty();
}
OptReduceWorker(RTLIL::Design *design, RTLIL::Module *module, bool do_fine) :
@@ -309,20 +575,31 @@ struct OptReduceWorker
// merge identical inputs on $mux and $pmux cells
- std::vector<RTLIL::Cell*> cells;
-
- for (auto &it : module->cells_)
- if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
- cells.push_back(it.second);
-
- for (auto cell : cells)
+ for (auto cell : module->selected_cells())
{
+ if (!cell->type.in(ID($mux), ID($pmux), ID($bmux), ID($demux)))
+ continue;
+
// this optimization is to aggressive for most coarse-grain applications.
// but we always want it for multiplexers driving write enable ports.
- if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y))))
- opt_mux_bits(cell);
+ if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) {
+ if (cell->type == ID($demux)) {
+ if (opt_demux_bits(cell))
+ continue;
+ } else {
+ if (opt_mux_bits(cell))
+ continue;
+ }
+ }
+
+ if (cell->type.in(ID($mux), ID($pmux)))
+ opt_pmux(cell);
+
+ if (cell->type == ID($bmux))
+ opt_bmux(cell);
- opt_mux(cell);
+ if (cell->type == ID($demux))
+ opt_demux(cell);
}
}
diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg
index 7a01cbd51..4de479122 100644
--- a/passes/pmgen/ice40_dsp.pmg
+++ b/passes/pmgen/ice40_dsp.pmg
@@ -28,9 +28,8 @@ code sigA sigB sigH
for (i = GetSize(sig)-1; i > 0; i--)
if (sig[i] != sig[i-1])
break;
- // Do not remove non-const sign bit
- if (sig[i].wire)
- ++i;
+ // Do not remove sign bit
+ ++i;
return sig.extract(0, i);
};
sigA = unextend(port(mul, \A));
diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc
index a292941c8..f37e07a89 100644
--- a/passes/sat/clk2fflogic.cc
+++ b/passes/sat/clk2fflogic.cc
@@ -40,7 +40,10 @@ struct Clk2fflogicPass : public Pass {
log("\n");
}
SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity) {
- Wire *past_sig = module->addWire(NEW_ID, GetSize(sig));
+ return wrap_async_control(module, sig, polarity, NEW_ID);
+ }
+ SigSpec wrap_async_control(Module *module, SigSpec sig, bool polarity, IdString past_sig_id) {
+ Wire *past_sig = module->addWire(past_sig_id, GetSize(sig));
module->addFf(NEW_ID, sig, past_sig);
if (polarity)
sig = module->Or(NEW_ID, sig, past_sig);
@@ -105,7 +108,7 @@ struct Clk2fflogicPass : public Pass {
i, log_id(module), log_id(mem.memid), log_signal(port.clk),
log_signal(port.addr), log_signal(port.data));
- Wire *past_clk = module->addWire(NEW_ID);
+ Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#past_clk#%s", log_id(mem.memid), i, log_signal(port.clk))));
past_clk->attributes[ID::init] = port.clk_polarity ? State::S1 : State::S0;
module->addFf(NEW_ID, port.clk, past_clk);
@@ -121,13 +124,13 @@ struct Clk2fflogicPass : public Pass {
SigSpec clock_edge = module->Eqx(NEW_ID, {port.clk, SigSpec(past_clk)}, clock_edge_pattern);
- SigSpec en_q = module->addWire(NEW_ID, GetSize(port.en));
+ SigSpec en_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#en_q", log_id(mem.memid), i)), GetSize(port.en));
module->addFf(NEW_ID, port.en, en_q);
- SigSpec addr_q = module->addWire(NEW_ID, GetSize(port.addr));
+ SigSpec addr_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#addr_q", log_id(mem.memid), i)), GetSize(port.addr));
module->addFf(NEW_ID, port.addr, addr_q);
- SigSpec data_q = module->addWire(NEW_ID, GetSize(port.data));
+ SigSpec data_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#%d#data_q", log_id(mem.memid), i)), GetSize(port.data));
module->addFf(NEW_ID, port.data, data_q);
port.clk = State::S0;
@@ -170,7 +173,14 @@ struct Clk2fflogicPass : public Pass {
ff.remove();
- Wire *past_q = module->addWire(NEW_ID, ff.width);
+ // Strip spaces from signal name, since Yosys IDs can't contain spaces
+ // Spaces only occur when we have a signal that's a slice of a larger bus,
+ // e.g. "\myreg [5:0]", so removing spaces shouldn't result in loss of uniqueness
+ std::string sig_q_str = log_signal(ff.sig_q);
+ sig_q_str.erase(std::remove(sig_q_str.begin(), sig_q_str.end(), ' '), sig_q_str.end());
+
+ Wire *past_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_q_wire", sig_q_str.c_str())), ff.width);
+
if (!ff.is_fine) {
module->addFf(NEW_ID, ff.sig_q, past_q);
} else {
@@ -182,7 +192,7 @@ struct Clk2fflogicPass : public Pass {
if (ff.has_clk) {
ff.unmap_ce_srst();
- Wire *past_clk = module->addWire(NEW_ID);
+ Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_clk#%s", sig_q_str.c_str(), log_signal(ff.sig_clk))));
initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0);
if (!ff.is_fine)
@@ -202,7 +212,7 @@ struct Clk2fflogicPass : public Pass {
SigSpec clock_edge = module->Eqx(NEW_ID, {ff.sig_clk, SigSpec(past_clk)}, clock_edge_pattern);
- Wire *past_d = module->addWire(NEW_ID, ff.width);
+ Wire *past_d = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_d_wire", sig_q_str.c_str())), ff.width);
if (!ff.is_fine)
module->addFf(NEW_ID, ff.sig_d, past_d);
else
@@ -241,7 +251,8 @@ struct Clk2fflogicPass : public Pass {
module->addAndGate(NEW_ID, qval, clrval, ff.sig_q);
}
} else if (ff.has_arst) {
- SigSpec arst = wrap_async_control(module, ff.sig_arst, ff.pol_arst);
+ IdString id = NEW_ID_SUFFIX(stringf("%s#past_arst#%s", sig_q_str.c_str(), log_signal(ff.sig_arst)));
+ SigSpec arst = wrap_async_control(module, ff.sig_arst, ff.pol_arst, id);
if (!ff.is_fine)
module->addMux(NEW_ID, qval, ff.val_arst, arst, ff.sig_q);
else
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index 4e158da62..8081ffffe 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -21,19 +21,76 @@
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/mem.h"
+#include "kernel/fstdata.h"
+#include "kernel/ff.h"
#include <ctime>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+enum class SimulationMode {
+ sim,
+ cmp,
+ gold,
+ gate,
+};
+
+static const std::map<std::string, int> g_units =
+{
+ { "", -9 }, // default is ns
+ { "s", 0 },
+ { "ms", -3 },
+ { "us", -6 },
+ { "ns", -9 },
+ { "ps", -12 },
+ { "fs", -15 },
+ { "as", -18 },
+ { "zs", -21 },
+};
+
+static double stringToTime(std::string str)
+{
+ if (str=="END") return -1;
+
+ char *endptr;
+ long value = strtol(str.c_str(), &endptr, 10);
+
+ if (g_units.find(endptr)==g_units.end())
+ log_error("Cannot parse '%s', bad unit '%s'\n", str.c_str(), endptr);
+
+ if (value < 0)
+ log_error("Time value '%s' must be positive\n", str.c_str());
+
+ return value * pow(10.0, g_units.at(endptr));
+}
+
+struct SimWorker;
+struct OutputWriter
+{
+ OutputWriter(SimWorker *w) { worker = w;};
+ virtual ~OutputWriter() {};
+ virtual void write(std::map<int, bool> &use_signal) = 0;
+ SimWorker *worker;
+};
+
struct SimShared
{
bool debug = false;
+ bool verbose = true;
bool hide_internal = true;
bool writeback = false;
bool zinit = false;
int rstlen = 1;
+ FstData *fst = nullptr;
+ double start_time = 0;
+ double stop_time = -1;
+ SimulationMode sim_mode = SimulationMode::sim;
+ bool cycles_set = false;
+ std::vector<std::unique_ptr<OutputWriter>> outputfiles;
+ std::vector<std::pair<int,std::map<int,Const>>> output_data;
+ bool ignore_x = false;
+ bool date = false;
};
void zinit(State &v)
@@ -51,7 +108,8 @@ void zinit(Const &v)
struct SimInstance
{
SimShared *shared;
-
+
+ std::string scope;
Module *module;
Cell *instance;
@@ -70,8 +128,13 @@ struct SimInstance
struct ff_state_t
{
- State past_clock;
Const past_d;
+ Const past_ad;
+ State past_clk;
+ State past_ce;
+ State past_srst;
+
+ FfData data;
};
struct mem_state_t
@@ -91,10 +154,11 @@ struct SimInstance
std::vector<Mem> memories;
- dict<Wire*, pair<int, Const>> vcd_database;
+ dict<Wire*, pair<int, Const>> signal_database;
+ dict<Wire*, fstHandle> fst_handles;
- SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
- shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
+ SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
+ shared(shared), scope(scope), module(module), instance(instance), parent(parent), sigmap(module)
{
log_assert(module);
@@ -116,6 +180,13 @@ struct SimInstance
}
}
+ if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) {
+ fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
+ if (id==0 && wire->name.isPublic())
+ log_warning("Unable to find wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name)).c_str());
+ fst_handles[wire] = id;
+ }
+
if (wire->attributes.count(ID::init)) {
Const initval = wire->attributes.at(ID::init);
for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
@@ -144,7 +215,7 @@ struct SimInstance
Module *mod = module->design->module(cell->type);
if (mod != nullptr) {
- dirty_children.insert(new SimInstance(shared, mod, cell, this));
+ dirty_children.insert(new SimInstance(shared, scope + "." + RTLIL::unescape_id(cell->name), mod, cell, this));
}
for (auto &port : cell->connections()) {
@@ -157,10 +228,15 @@ struct SimInstance
}
}
- if (cell->type.in(ID($dff))) {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ FfData ff_data(nullptr, cell);
ff_state_t ff;
- ff.past_clock = State::Sx;
- ff.past_d = Const(State::Sx, cell->getParam(ID::WIDTH).as_int());
+ ff.past_d = Const(State::Sx, ff_data.width);
+ ff.past_ad = Const(State::Sx, ff_data.width);
+ ff.past_clk = State::Sx;
+ ff.past_ce = State::Sx;
+ ff.past_srst = State::Sx;
+ ff.data = ff_data;
ff_database[cell] = ff;
}
@@ -177,11 +253,10 @@ struct SimInstance
{
for (auto &it : ff_database)
{
- Cell *cell = it.first;
ff_state_t &ff = it.second;
zinit(ff.past_d);
- SigSpec qsig = cell->getPort(ID::Q);
+ SigSpec qsig = it.second.data.sig_q;
Const qdata = get_state(qsig);
zinit(qdata);
set_state(qsig, qdata);
@@ -253,6 +328,16 @@ struct SimInstance
return did_something;
}
+ void set_memory_state(IdString memid, Const addr, Const data)
+ {
+ auto &state = mem_database[memid];
+
+ int offset = (addr.as_int() - state.mem->start_offset) * state.mem->width;
+ for (int i = 0; i < GetSize(data); i++)
+ if (0 <= i+offset && i+offset < GetSize(data))
+ state.data.bits[i+offset] = data.bits[i];
+ }
+
void update_cell(Cell *cell)
{
if (ff_database.count(cell))
@@ -313,6 +398,12 @@ struct SimInstance
return;
}
+ // (A,S -> Y) cells
+ if (has_a && !has_b && !has_c && !has_d && has_s && has_y) {
+ set_state(sig_y, CellTypes::eval(cell, get_state(sig_a), get_state(sig_s)));
+ return;
+ }
+
// (A,B,S -> Y) cells
if (has_a && has_b && !has_c && !has_d && has_s && has_y) {
set_state(sig_y, CellTypes::eval(cell, get_state(sig_a), get_state(sig_b), get_state(sig_s)));
@@ -408,21 +499,62 @@ struct SimInstance
for (auto &it : ff_database)
{
- Cell *cell = it.first;
ff_state_t &ff = it.second;
-
- if (cell->type.in(ID($dff)))
- {
- bool clkpol = cell->getParam(ID::CLK_POLARITY).as_bool();
- State current_clock = get_state(cell->getPort(ID::CLK))[0];
-
- if (clkpol ? (ff.past_clock == State::S1 || current_clock != State::S1) :
- (ff.past_clock == State::S0 || current_clock != State::S0))
- continue;
-
- if (set_state(cell->getPort(ID::Q), ff.past_d))
- did_something = true;
+ FfData &ff_data = ff.data;
+
+ Const current_q = get_state(ff.data.sig_q);
+
+ if (ff_data.has_clk) {
+ // flip-flops
+ State current_clk = get_state(ff_data.sig_clk)[0];
+ if (ff_data.pol_clk ? (ff.past_clk == State::S0 && current_clk != State::S0) :
+ (ff.past_clk == State::S1 && current_clk != State::S1)) {
+ bool ce = ff.past_ce == (ff_data.pol_ce ? State::S1 : State::S0);
+ // set if no ce, or ce is enabled
+ if (!ff_data.has_ce || (ff_data.has_ce && ce)) {
+ current_q = ff.past_d;
+ }
+ // override if sync reset
+ if ((ff_data.has_srst) && (ff.past_srst == (ff_data.pol_srst ? State::S1 : State::S0)) &&
+ ((!ff_data.ce_over_srst) || (ff_data.ce_over_srst && ce))) {
+ current_q = ff_data.val_srst;
+ }
+ }
+ }
+ // async load
+ if (ff_data.has_aload) {
+ State current_aload = get_state(ff_data.sig_aload)[0];
+ if (current_aload == (ff_data.pol_aload ? State::S1 : State::S0)) {
+ current_q = ff_data.has_clk ? ff.past_ad : get_state(ff.data.sig_ad);
+ }
+ }
+ // async reset
+ if (ff_data.has_arst) {
+ State current_arst = get_state(ff_data.sig_arst)[0];
+ if (current_arst == (ff_data.pol_arst ? State::S1 : State::S0)) {
+ current_q = ff_data.val_arst;
+ }
+ }
+ // handle set/reset
+ if (ff.data.has_sr) {
+ Const current_clr = get_state(ff.data.sig_clr);
+ Const current_set = get_state(ff.data.sig_set);
+
+ for(int i=0;i<ff.past_d.size();i++) {
+ if (current_clr[i] == (ff_data.pol_clr ? State::S1 : State::S0)) {
+ current_q[i] = State::S0;
+ }
+ else if (current_set[i] == (ff_data.pol_set ? State::S1 : State::S0)) {
+ current_q[i] = State::S1;
+ }
+ }
+ }
+ if (ff_data.has_gclk) {
+ // $ff
+ current_q = ff.past_d;
}
+ if (set_state(ff_data.sig_q, current_q))
+ did_something = true;
}
for (auto &it : mem_database)
@@ -480,13 +612,22 @@ struct SimInstance
{
for (auto &it : ff_database)
{
- Cell *cell = it.first;
ff_state_t &ff = it.second;
- if (cell->type.in(ID($dff))) {
- ff.past_clock = get_state(cell->getPort(ID::CLK))[0];
- ff.past_d = get_state(cell->getPort(ID::D));
- }
+ if (ff.data.has_aload)
+ ff.past_ad = get_state(ff.data.sig_ad);
+
+ if (ff.data.has_clk || ff.data.has_gclk)
+ ff.past_d = get_state(ff.data.sig_d);
+
+ if (ff.data.has_clk)
+ ff.past_clk = get_state(ff.data.sig_clk)[0];
+
+ if (ff.data.has_ce)
+ ff.past_ce = get_state(ff.data.sig_ce)[0];
+
+ if (ff.data.has_srst)
+ ff.past_srst = get_state(ff.data.sig_srst)[0];
}
for (auto &it : mem_database)
@@ -537,8 +678,7 @@ struct SimInstance
for (auto &it : ff_database)
{
- Cell *cell = it.first;
- SigSpec sig_q = cell->getPort(ID::Q);
+ SigSpec sig_q = it.second.data.sig_q;
Const initval = get_state(sig_q);
for (int i = 0; i < GetSize(sig_q); i++)
@@ -568,28 +708,51 @@ struct SimInstance
it.second->writeback(wbmods);
}
- void write_vcd_header(std::ofstream &f, int &id)
+ void register_signals(int &id)
{
- f << stringf("$scope module %s $end\n", log_id(name()));
-
for (auto wire : module->wires())
{
if (shared->hide_internal && wire->name[0] == '$')
continue;
- f << stringf("$var wire %d n%d %s%s $end\n", GetSize(wire), id, wire->name[0] == '$' ? "\\" : "", log_id(wire));
- vcd_database[wire] = make_pair(id++, Const());
+ signal_database[wire] = make_pair(id, Const());
+ id++;
+ }
+
+ for (auto child : children)
+ child.second->register_signals(id);
+ }
+
+ void write_output_header(std::function<void(IdString)> enter_scope, std::function<void()> exit_scope, std::function<void(Wire*, int, bool)> register_signal)
+ {
+ enter_scope(name());
+
+ dict<Wire*,bool> registers;
+ for (auto cell : module->cells())
+ {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ FfData ff_data(nullptr, cell);
+ SigSpec q = sigmap(ff_data.sig_q);
+ if (q.is_wire() && signal_database.count(q.as_wire()) != 0) {
+ registers[q.as_wire()] = true;
+ }
+ }
+ }
+
+ for (auto signal : signal_database)
+ {
+ register_signal(signal.first, signal.second.first, registers.count(signal.first)!=0);
}
for (auto child : children)
- child.second->write_vcd_header(f, id);
+ child.second->write_output_header(enter_scope, exit_scope, register_signal);
- f << stringf("$upscope $end\n");
+ exit_scope();
}
- void write_vcd_step(std::ofstream &f)
+ void register_output_step_values(std::map<int,Const> *data)
{
- for (auto &it : vcd_database)
+ for (auto &it : signal_database)
{
Wire *wire = it.first;
Const value = get_state(wire);
@@ -599,66 +762,134 @@ struct SimInstance
continue;
it.second.second = value;
+ data->emplace(id, value);
+ }
- f << "b";
- for (int i = GetSize(value)-1; i >= 0; i--) {
- switch (value[i]) {
- case State::S0: f << "0"; break;
- case State::S1: f << "1"; break;
- case State::Sx: f << "x"; break;
- default: f << "z";
+ for (auto child : children)
+ child.second->register_output_step_values(data);
+ }
+
+ void setInitState()
+ {
+ for (auto &it : ff_database)
+ {
+ SigSpec qsig = it.second.data.sig_q;
+ if (qsig.is_wire()) {
+ IdString name = qsig.as_wire()->name;
+ fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(name));
+ if (id==0 && name.isPublic())
+ log_warning("Unable to find wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(name)).c_str());
+ if (id!=0) {
+ Const fst_val = Const::from_string(shared->fst->valueOf(id));
+ set_state(qsig, fst_val);
}
}
+ }
+ for (auto child : children)
+ child.second->setInitState();
+ }
- f << stringf(" n%d\n", id);
+ void setState(dict<int, std::pair<SigBit,bool>> bits, std::string values)
+ {
+ for(auto bit : bits) {
+ if (bit.first >= GetSize(values))
+ log_error("Too few input data bits in file.\n");
+ switch(values.at(bit.first)) {
+ case '0': set_state(bit.second.first, bit.second.second ? State::S1 : State::S0); break;
+ case '1': set_state(bit.second.first, bit.second.second ? State::S0 : State::S1); break;
+ default: set_state(bit.second.first, State::Sx); break;
+ }
}
+ }
+ bool checkSignals()
+ {
+ bool retVal = false;
+ for(auto &item : fst_handles) {
+ if (item.second==0) continue; // Ignore signals not found
+ Const fst_val = Const::from_string(shared->fst->valueOf(item.second));
+ Const sim_val = get_state(item.first);
+ if (sim_val.size()!=fst_val.size()) {
+ log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope.c_str(), log_id(item.first));
+ continue;
+ }
+ if (shared->sim_mode == SimulationMode::sim) {
+ // No checks performed when using stimulus
+ } else if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X
+ for(int i=0;i<fst_val.size();i++) {
+ if (fst_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
+ log_warning("Signal '%s.%s' in file %s in simulation %s\n", scope.c_str(), log_id(item.first), log_signal(fst_val), log_signal(sim_val));
+ retVal = true;
+ break;
+ }
+ }
+ } else if (shared->sim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X
+ for(int i=0;i<sim_val.size();i++) {
+ if (sim_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
+ log_warning("Signal '%s.%s' in file %s in simulation %s\n", scope.c_str(), log_id(item.first), log_signal(fst_val), log_signal(sim_val));
+ retVal = true;
+ break;
+ }
+ }
+ } else {
+ if (fst_val!=sim_val) {
+ log_warning("Signal '%s.%s' in file %s in simulation '%s'\n", scope.c_str(), log_id(item.first), log_signal(fst_val), log_signal(sim_val));
+ retVal = true;
+ }
+ }
+ }
for (auto child : children)
- child.second->write_vcd_step(f);
+ retVal |= child.second->checkSignals();
+ return retVal;
}
};
struct SimWorker : SimShared
{
SimInstance *top = nullptr;
- std::ofstream vcdfile;
pool<IdString> clock, clockn, reset, resetn;
std::string timescale;
+ std::string sim_filename;
+ std::string map_filename;
+ std::string scope;
~SimWorker()
{
+ outputfiles.clear();
delete top;
}
- void write_vcd_header()
+ void register_signals()
{
- if (!vcdfile.is_open())
- return;
-
- vcdfile << stringf("$version %s $end\n", yosys_version_str);
-
- std::time_t t = std::time(nullptr);
- char mbstr[255];
- if (std::strftime(mbstr, sizeof(mbstr), "%c", std::localtime(&t))) {
- vcdfile << stringf("$date ") << mbstr << stringf(" $end\n");
- }
-
- if (!timescale.empty())
- vcdfile << stringf("$timescale %s $end\n", timescale.c_str());
-
int id = 1;
- top->write_vcd_header(vcdfile, id);
-
- vcdfile << stringf("$enddefinitions $end\n");
+ top->register_signals(id);
}
- void write_vcd_step(int t)
+ void register_output_step(int t)
{
- if (!vcdfile.is_open())
- return;
+ std::map<int,Const> data;
+ top->register_output_step_values(&data);
+ output_data.emplace_back(t, data);
+ }
- vcdfile << stringf("#%d\n", t);
- top->write_vcd_step(vcdfile);
+ void write_output_files()
+ {
+ std::map<int, bool> use_signal;
+ bool first = ignore_x;
+ for(auto& d : output_data)
+ {
+ if (first) {
+ for (auto &data : d.second)
+ use_signal[data.first] = !data.second.is_fully_undef();
+ first = false;
+ } else {
+ for (auto &data : d.second)
+ use_signal[data.first] = true;
+ }
+ if (!ignore_x) break;
+ }
+ for(auto& writer : outputfiles)
+ writer->write(use_signal);
}
void update()
@@ -699,11 +930,12 @@ struct SimWorker : SimShared
void run(Module *topmod, int numcycles)
{
log_assert(top == nullptr);
- top = new SimInstance(this, topmod);
+ top = new SimInstance(this, scope, topmod);
+ register_signals();
if (debug)
log("\n===== 0 =====\n");
- else
+ else if (verbose)
log("Simulating cycle 0.\n");
set_inports(reset, State::S1);
@@ -714,24 +946,24 @@ struct SimWorker : SimShared
update();
- write_vcd_header();
- write_vcd_step(0);
+ register_output_step(0);
for (int cycle = 0; cycle < numcycles; cycle++)
{
if (debug)
log("\n===== %d =====\n", 10*cycle + 5);
-
+ else if (verbose)
+ log("Simulating cycle %d.\n", (cycle*2)+1);
set_inports(clock, State::S0);
set_inports(clockn, State::S1);
update();
- write_vcd_step(10*cycle + 5);
+ register_output_step(10*cycle + 5);
if (debug)
log("\n===== %d =====\n", 10*cycle + 10);
- else
- log("Simulating cycle %d.\n", cycle+1);
+ else if (verbose)
+ log("Simulating cycle %d.\n", (cycle*2)+2);
set_inports(clock, State::S1);
set_inports(clockn, State::S0);
@@ -742,16 +974,812 @@ struct SimWorker : SimShared
}
update();
- write_vcd_step(10*cycle + 10);
+ register_output_step(10*cycle + 10);
}
- write_vcd_step(10*numcycles + 2);
+ register_output_step(10*numcycles + 2);
+
+ write_output_files();
if (writeback) {
pool<Module*> wbmods;
top->writeback(wbmods);
}
}
+
+ void run_cosim_fst(Module *topmod, int numcycles)
+ {
+ log_assert(top == nullptr);
+ fst = new FstData(sim_filename);
+
+ if (scope.empty())
+ log_error("Scope must be defined for co-simulation.\n");
+
+ top = new SimInstance(this, scope, topmod);
+ register_signals();
+
+ std::vector<fstHandle> fst_clock;
+
+ for (auto portname : clock)
+ {
+ Wire *w = topmod->wire(portname);
+ if (!w)
+ log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
+ if (!w->port_input)
+ log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
+ if (id==0)
+ log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
+ fst_clock.push_back(id);
+ }
+ for (auto portname : clockn)
+ {
+ Wire *w = topmod->wire(portname);
+ if (!w)
+ log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
+ if (!w->port_input)
+ log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
+ if (id==0)
+ log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
+ fst_clock.push_back(id);
+ }
+
+ SigMap sigmap(topmod);
+ std::map<Wire*,fstHandle> inputs;
+
+ for (auto wire : topmod->wires()) {
+ if (wire->port_input) {
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
+ if (id==0)
+ log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(wire->name)).c_str());
+ inputs[wire] = id;
+ }
+ }
+
+ uint64_t startCount = 0;
+ uint64_t stopCount = 0;
+ if (start_time==0) {
+ if (start_time < fst->getStartTime())
+ log_warning("Start time is before simulation file start time\n");
+ startCount = fst->getStartTime();
+ } else if (start_time==-1)
+ startCount = fst->getEndTime();
+ else {
+ startCount = start_time / fst->getTimescale();
+ if (startCount > fst->getEndTime()) {
+ startCount = fst->getEndTime();
+ log_warning("Start time is after simulation file end time\n");
+ }
+ }
+ if (stop_time==0) {
+ if (stop_time < fst->getStartTime())
+ log_warning("Stop time is before simulation file start time\n");
+ stopCount = fst->getStartTime();
+ } else if (stop_time==-1)
+ stopCount = fst->getEndTime();
+ else {
+ stopCount = stop_time / fst->getTimescale();
+ if (stopCount > fst->getEndTime()) {
+ stopCount = fst->getEndTime();
+ log_warning("Stop time is after simulation file end time\n");
+ }
+ }
+ if (stopCount<startCount) {
+ log_error("Stop time is before start time\n");
+ }
+
+ bool initial = true;
+ int cycle = 0;
+ log("Co-simulation from %lu%s to %lu%s", (unsigned long)startCount, fst->getTimescaleString(), (unsigned long)stopCount, fst->getTimescaleString());
+ if (cycles_set)
+ log(" for %d clock cycle(s)",numcycles);
+ log("\n");
+ bool all_samples = fst_clock.empty();
+
+ try {
+ fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) {
+ if (verbose)
+ log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString());
+ bool did_something = false;
+ for(auto &item : inputs) {
+ std::string v = fst->valueOf(item.second);
+ did_something |= top->set_state(item.first, Const::from_string(v));
+ }
+
+ if (initial) {
+ top->setInitState();
+ initial = false;
+ }
+ if (did_something)
+ update();
+ register_output_step(time);
+
+ bool status = top->checkSignals();
+ if (status)
+ log_error("Signal difference\n");
+ cycle++;
+
+ // Limit to number of cycles if provided
+ if (cycles_set && cycle > numcycles *2)
+ throw fst_end_of_data_exception();
+ if (time==stopCount)
+ throw fst_end_of_data_exception();
+ });
+ } catch(fst_end_of_data_exception) {
+ // end of data detected
+ }
+
+ write_output_files();
+
+ if (writeback) {
+ pool<Module*> wbmods;
+ top->writeback(wbmods);
+ }
+ delete fst;
+ }
+
+ void run_cosim_aiger_witness(Module *topmod)
+ {
+ log_assert(top == nullptr);
+ if ((clock.size()+clockn.size())==0)
+ log_error("Clock signal must be specified.\n");
+ std::ifstream mf(map_filename);
+ std::string type, symbol;
+ int variable, index;
+ dict<int, std::pair<SigBit,bool>> inputs, inits, latches;
+ if (mf.fail())
+ log_cmd_error("Not able to read AIGER witness map file.\n");
+ while (mf >> type >> variable >> index >> symbol) {
+ RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
+ Wire *w = topmod->wire(escaped_s);
+ if (!w)
+ log_error("Wire %s not present in module %s\n",log_signal(w),log_id(topmod));
+ if (index < w->start_offset || index > w->start_offset + w->width)
+ log_error("Index %d for wire %s is out of range\n", index, log_signal(w));
+ if (type == "input") {
+ inputs[variable] = {SigBit(w,index-w->start_offset), false};
+ } else if (type == "init") {
+ inits[variable] = {SigBit(w,index-w->start_offset), false};
+ } else if (type == "latch") {
+ latches[variable] = {SigBit(w,index-w->start_offset), false};
+ } else if (type == "invlatch") {
+ latches[variable] = {SigBit(w,index-w->start_offset), true};
+ }
+ }
+
+ std::ifstream f;
+ f.open(sim_filename.c_str());
+ if (f.fail() || GetSize(sim_filename) == 0)
+ log_error("Can not open file `%s`\n", sim_filename.c_str());
+
+ int state = 0;
+ std::string status;
+ int cycle = 0;
+ top = new SimInstance(this, scope, topmod);
+ register_signals();
+
+ while (!f.eof())
+ {
+ std::string line;
+ std::getline(f, line);
+ if (line.size()==0 || line[0]=='#') continue;
+ if (line[0]=='.') break;
+ if (state==0 && line.size()!=1) {
+ // old format detected, latch data
+ state = 2;
+ }
+ if (state==1 && line[0]!='b' && line[0]!='c') {
+ // was old format but with 1 bit latch
+ top->setState(latches, status);
+ state = 3;
+ }
+
+ switch(state)
+ {
+ case 0:
+ status = line;
+ state = 1;
+ break;
+ case 1:
+ state = 2;
+ break;
+ case 2:
+ top->setState(latches, line);
+ state = 3;
+ break;
+ default:
+ if (verbose)
+ log("Simulating cycle %d.\n", cycle);
+ top->setState(inputs, line);
+ if (cycle) {
+ set_inports(clock, State::S1);
+ set_inports(clockn, State::S0);
+ } else {
+ top->setState(inits, line);
+ set_inports(clock, State::S0);
+ set_inports(clockn, State::S1);
+ }
+ update();
+ register_output_step(10*cycle);
+ if (cycle) {
+ set_inports(clock, State::S0);
+ set_inports(clockn, State::S1);
+ update();
+ register_output_step(10*cycle + 5);
+ }
+ cycle++;
+ break;
+ }
+ }
+ register_output_step(10*cycle);
+ write_output_files();
+ }
+
+ std::vector<std::string> split(std::string text, const char *delim)
+ {
+ std::vector<std::string> list;
+ char *p = strdup(text.c_str());
+ char *t = strtok(p, delim);
+ while (t != NULL) {
+ list.push_back(t);
+ t = strtok(NULL, delim);
+ }
+ free(p);
+ return list;
+ }
+
+ std::string signal_name(std::string const & name)
+ {
+ size_t pos = name.find_first_of("@");
+ if (pos==std::string::npos) {
+ pos = name.find_first_of("#");
+ if (pos==std::string::npos)
+ log_error("Line does not contain proper signal name `%s`\n", name.c_str());
+ }
+ return name.substr(0, pos);
+ }
+
+ void run_cosim_btor2_witness(Module *topmod)
+ {
+ log_assert(top == nullptr);
+ if ((clock.size()+clockn.size())==0)
+ log_error("Clock signal must be specified.\n");
+ std::ifstream f;
+ f.open(sim_filename.c_str());
+ if (f.fail() || GetSize(sim_filename) == 0)
+ log_error("Can not open file `%s`\n", sim_filename.c_str());
+
+ int state = 0;
+ int cycle = 0;
+ top = new SimInstance(this, scope, topmod);
+ register_signals();
+ int prev_cycle = 0;
+ int curr_cycle = 0;
+ std::vector<std::string> parts;
+ size_t len = 0;
+ while (!f.eof())
+ {
+ std::string line;
+ std::getline(f, line);
+ if (line.size()==0) continue;
+
+ if (line[0]=='#' || line[0]=='@' || line[0]=='.') {
+ if (line[0]!='.')
+ curr_cycle = atoi(line.c_str()+1);
+ else
+ curr_cycle = -1; // force detect change
+
+ if (curr_cycle != prev_cycle) {
+ if (verbose)
+ log("Simulating cycle %d.\n", cycle);
+ set_inports(clock, State::S1);
+ set_inports(clockn, State::S0);
+ update();
+ register_output_step(10*cycle+0);
+ set_inports(clock, State::S0);
+ set_inports(clockn, State::S1);
+ update();
+ register_output_step(10*cycle+5);
+ cycle++;
+ prev_cycle = curr_cycle;
+ }
+ if (line[0]=='.') break;
+ continue;
+ }
+
+ switch(state)
+ {
+ case 0:
+ if (line=="sat")
+ state = 1;
+ break;
+ case 1:
+ if (line[0]=='b' || line[0]=='j')
+ state = 2;
+ else
+ log_error("Line does not contain property.\n");
+ break;
+ default: // set state or inputs
+ parts = split(line, " ");
+ len = parts.size();
+ if (len<3 || len>4)
+ log_error("Invalid set state line content.\n");
+
+ RTLIL::IdString escaped_s = RTLIL::escape_id(signal_name(parts[len-1]));
+ if (len==3) {
+ Wire *w = topmod->wire(escaped_s);
+ if (!w) {
+ Cell *c = topmod->cell(escaped_s);
+ if (!c)
+ log_warning("Wire/cell %s not present in module %s\n",log_id(escaped_s),log_id(topmod));
+ else if (c->type.in(ID($anyconst), ID($anyseq))) {
+ SigSpec sig_y= c->getPort(ID::Y);
+ if ((int)parts[1].size() != GetSize(sig_y))
+ log_error("Size of wire %s is different than provided data.\n", log_signal(sig_y));
+ top->set_state(sig_y, Const::from_string(parts[1]));
+ }
+ } else {
+ if ((int)parts[1].size() != w->width)
+ log_error("Size of wire %s is different than provided data.\n", log_signal(w));
+ top->set_state(w, Const::from_string(parts[1]));
+ }
+ } else {
+ Cell *c = topmod->cell(escaped_s);
+ if (!c)
+ log_error("Cell %s not present in module %s\n",log_id(escaped_s),log_id(topmod));
+ if (!c->is_mem_cell())
+ log_error("Cell %s is not memory cell in module %s\n",log_id(escaped_s),log_id(topmod));
+
+ Const addr = Const::from_string(parts[1].substr(1,parts[1].size()-2));
+ Const data = Const::from_string(parts[2]);
+ top->set_memory_state(c->parameters.at(ID::MEMID).decode_string(), addr, data);
+ }
+ break;
+ }
+ }
+ register_output_step(10*cycle);
+ write_output_files();
+ }
+
+ std::string define_signal(Wire *wire)
+ {
+ std::stringstream f;
+
+ if (wire->width==1)
+ f << stringf("%s", RTLIL::unescape_id(wire->name).c_str());
+ else
+ if (wire->upto)
+ f << stringf("[%d:%d] %s", wire->start_offset, wire->width - 1 + wire->start_offset, RTLIL::unescape_id(wire->name).c_str());
+ else
+ f << stringf("[%d:%d] %s", wire->width - 1 + wire->start_offset, wire->start_offset, RTLIL::unescape_id(wire->name).c_str());
+ return f.str();
+ }
+
+ std::string signal_list(std::map<Wire*,fstHandle> &signals)
+ {
+ std::stringstream f;
+ for(auto item=signals.begin();item!=signals.end();item++)
+ f << stringf("%c%s", (item==signals.begin() ? ' ' : ','), RTLIL::unescape_id(item->first->name).c_str());
+ return f.str();
+ }
+
+ void generate_tb(Module *topmod, std::string tb_filename, int numcycles)
+ {
+ fst = new FstData(sim_filename);
+
+ if (scope.empty())
+ log_error("Scope must be defined for co-simulation.\n");
+
+ if ((clock.size()+clockn.size())==0)
+ log_error("Clock signal must be specified.\n");
+
+ std::vector<fstHandle> fst_clock;
+ std::map<Wire*,fstHandle> clocks;
+
+ for (auto portname : clock)
+ {
+ Wire *w = topmod->wire(portname);
+ if (!w)
+ log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
+ if (!w->port_input)
+ log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
+ if (id==0)
+ log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
+ fst_clock.push_back(id);
+ clocks[w] = id;
+ }
+ for (auto portname : clockn)
+ {
+ Wire *w = topmod->wire(portname);
+ if (!w)
+ log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
+ if (!w->port_input)
+ log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
+ if (id==0)
+ log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
+ fst_clock.push_back(id);
+ clocks[w] = id;
+ }
+
+ SigMap sigmap(topmod);
+ std::map<Wire*,fstHandle> inputs;
+ std::map<Wire*,fstHandle> outputs;
+
+ for (auto wire : topmod->wires()) {
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
+ if (id==0 && (wire->port_input || wire->port_output))
+ log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(wire->name)).c_str());
+ if (wire->port_input)
+ if (clocks.find(wire)==clocks.end())
+ inputs[wire] = id;
+ if (wire->port_output)
+ outputs[wire] = id;
+ }
+
+ uint64_t startCount = 0;
+ uint64_t stopCount = 0;
+ if (start_time==0) {
+ if (start_time < fst->getStartTime())
+ log_warning("Start time is before simulation file start time\n");
+ startCount = fst->getStartTime();
+ } else if (start_time==-1)
+ startCount = fst->getEndTime();
+ else {
+ startCount = start_time / fst->getTimescale();
+ if (startCount > fst->getEndTime()) {
+ startCount = fst->getEndTime();
+ log_warning("Start time is after simulation file end time\n");
+ }
+ }
+ if (stop_time==0) {
+ if (stop_time < fst->getStartTime())
+ log_warning("Stop time is before simulation file start time\n");
+ stopCount = fst->getStartTime();
+ } else if (stop_time==-1)
+ stopCount = fst->getEndTime();
+ else {
+ stopCount = stop_time / fst->getTimescale();
+ if (stopCount > fst->getEndTime()) {
+ stopCount = fst->getEndTime();
+ log_warning("Stop time is after simulation file end time\n");
+ }
+ }
+ if (stopCount<startCount) {
+ log_error("Stop time is before start time\n");
+ }
+
+ int cycle = 0;
+ log("Generate testbench data from %lu%s to %lu%s", (unsigned long)startCount, fst->getTimescaleString(), (unsigned long)stopCount, fst->getTimescaleString());
+ if (cycles_set)
+ log(" for %d clock cycle(s)",numcycles);
+ log("\n");
+
+ std::stringstream f;
+ f << stringf("`timescale 1%s/1%s\n", fst->getTimescaleString(),fst->getTimescaleString());
+ f << stringf("module %s();\n",tb_filename.c_str());
+ int clk_len = 0;
+ int inputs_len = 0;
+ int outputs_len = 0;
+ for(auto &item : clocks) {
+ clk_len += item.first->width;
+ f << "\treg " << define_signal(item.first) << ";\n";
+ }
+ for(auto &item : inputs) {
+ inputs_len += item.first->width;
+ f << "\treg " << define_signal(item.first) << ";\n";
+ }
+ for(auto &item : outputs) {
+ outputs_len += item.first->width;
+ f << "\twire " << define_signal(item.first) << ";\n";
+ }
+ int data_len = clk_len + inputs_len + outputs_len + 32;
+ f << "\n";
+ f << stringf("\t%s uut(",RTLIL::unescape_id(topmod->name).c_str());
+ for(auto item=clocks.begin();item!=clocks.end();item++)
+ f << stringf("%c.%s(%s)", (item==clocks.begin() ? ' ' : ','), RTLIL::unescape_id(item->first->name).c_str(), RTLIL::unescape_id(item->first->name).c_str());
+ for(auto &item : inputs)
+ f << stringf(",.%s(%s)", RTLIL::unescape_id(item.first->name).c_str(), RTLIL::unescape_id(item.first->name).c_str());
+ for(auto &item : outputs)
+ f << stringf(",.%s(%s)", RTLIL::unescape_id(item.first->name).c_str(), RTLIL::unescape_id(item.first->name).c_str());
+ f << ");\n";
+ f << "\n";
+ f << "\tinteger i;\n";
+ uint64_t prev_time = startCount;
+ log("Writing data to `%s`\n", (tb_filename+".txt").c_str());
+ std::ofstream data_file(tb_filename+".txt");
+ std::stringstream initstate;
+ try {
+ fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) {
+ for(auto &item : clocks)
+ data_file << stringf("%s",fst->valueOf(item.second).c_str());
+ for(auto &item : inputs)
+ data_file << stringf("%s",fst->valueOf(item.second).c_str());
+ for(auto &item : outputs)
+ data_file << stringf("%s",fst->valueOf(item.second).c_str());
+ data_file << stringf("%s\n",Const(time-prev_time).as_string().c_str());
+
+ if (time==startCount) {
+ // initial state
+ for(auto var : fst->getVars()) {
+ if (var.is_reg && !Const::from_string(fst->valueOf(var.id).c_str()).is_fully_undef()) {
+ if (var.scope == scope) {
+ initstate << stringf("\t\tuut.%s = %d'b%s;\n", var.name.c_str(), var.width, fst->valueOf(var.id).c_str());
+ } else if (var.scope.find(scope+".")==0) {
+ initstate << stringf("\t\tuut.%s.%s = %d'b%s;\n",var.scope.substr(scope.size()+1).c_str(), var.name.c_str(), var.width, fst->valueOf(var.id).c_str());
+ }
+ }
+ }
+ }
+ cycle++;
+ prev_time = time;
+
+ // Limit to number of cycles if provided
+ if (cycles_set && cycle > numcycles *2)
+ throw fst_end_of_data_exception();
+ if (time==stopCount)
+ throw fst_end_of_data_exception();
+ });
+ } catch(fst_end_of_data_exception) {
+ // end of data detected
+ }
+
+ f << stringf("\treg [0:%d] data [0:%d];\n", data_len-1, cycle-1);
+ f << "\tinitial begin;\n";
+ f << stringf("\t\t$dumpfile(\"%s\");\n",tb_filename.c_str());
+ f << stringf("\t\t$dumpvars(0,%s);\n",tb_filename.c_str());
+ f << initstate.str();
+ f << stringf("\t\t$readmemb(\"%s.txt\", data);\n",tb_filename.c_str());
+
+ f << stringf("\t\t#(data[0][%d:%d]);\n", data_len-32, data_len-1);
+ f << stringf("\t\t{%s } = data[0][%d:%d];\n", signal_list(clocks).c_str(), 0, clk_len-1);
+ f << stringf("\t\t{%s } <= data[0][%d:%d];\n", signal_list(inputs).c_str(), clk_len, clk_len+inputs_len-1);
+
+ f << stringf("\t\tfor (i = 1; i < %d; i++) begin\n",cycle);
+
+ f << stringf("\t\t\t#(data[i][%d:%d]);\n", data_len-32, data_len-1);
+ f << stringf("\t\t\t{%s } = data[i][%d:%d];\n", signal_list(clocks).c_str(), 0, clk_len-1);
+ f << stringf("\t\t\t{%s } <= data[i][%d:%d];\n", signal_list(inputs).c_str(), clk_len, clk_len+inputs_len-1);
+
+ f << stringf("\t\t\tif ({%s } != data[i-1][%d:%d]) begin\n", signal_list(outputs).c_str(), clk_len+inputs_len, clk_len+inputs_len+outputs_len-1);
+ f << "\t\t\t\t$error(\"Signal difference detected\\n\");\n";
+ f << "\t\t\tend\n";
+
+ f << "\t\tend\n";
+
+ f << "\t\t$finish;\n";
+ f << "\tend\n";
+ f << "endmodule\n";
+
+ log("Writing testbench to `%s`\n", (tb_filename+".v").c_str());
+ std::ofstream tb_file(tb_filename+".v");
+ tb_file << f.str();
+
+ delete fst;
+ }
+};
+
+struct VCDWriter : public OutputWriter
+{
+ VCDWriter(SimWorker *worker, std::string filename) : OutputWriter(worker) {
+ vcdfile.open(filename.c_str());
+ }
+
+ void write(std::map<int, bool> &use_signal) override
+ {
+ if (!vcdfile.is_open()) return;
+ vcdfile << stringf("$version %s $end\n", worker->date ? yosys_version_str : "Yosys");
+
+ if (worker->date) {
+ std::time_t t = std::time(nullptr);
+ char mbstr[255];
+ if (std::strftime(mbstr, sizeof(mbstr), "%c", std::localtime(&t))) {
+ vcdfile << stringf("$date ") << mbstr << stringf(" $end\n");
+ }
+ }
+
+ if (!worker->timescale.empty())
+ vcdfile << stringf("$timescale %s $end\n", worker->timescale.c_str());
+
+ worker->top->write_output_header(
+ [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); },
+ [this]() { vcdfile << stringf("$upscope $end\n");},
+ [this,use_signal](Wire *wire, int id, bool is_reg) { if (use_signal.at(id)) vcdfile << stringf("$var %s %d n%d %s%s $end\n", is_reg ? "reg" : "wire", GetSize(wire), id, wire->name[0] == '$' ? "\\" : "", log_id(wire)); }
+ );
+
+ vcdfile << stringf("$enddefinitions $end\n");
+
+ for(auto& d : worker->output_data)
+ {
+ vcdfile << stringf("#%d\n", d.first);
+ for (auto &data : d.second)
+ {
+ if (!use_signal.at(data.first)) continue;
+ Const value = data.second;
+ vcdfile << "b";
+ for (int i = GetSize(value)-1; i >= 0; i--) {
+ switch (value[i]) {
+ case State::S0: vcdfile << "0"; break;
+ case State::S1: vcdfile << "1"; break;
+ case State::Sx: vcdfile << "x"; break;
+ default: vcdfile << "z";
+ }
+ }
+ vcdfile << stringf(" n%d\n", data.first);
+ }
+ }
+ }
+
+ std::ofstream vcdfile;
+};
+
+struct FSTWriter : public OutputWriter
+{
+ FSTWriter(SimWorker *worker, std::string filename) : OutputWriter(worker) {
+ fstfile = (struct fstContext *)fstWriterCreate(filename.c_str(),1);
+ }
+
+ virtual ~FSTWriter()
+ {
+ fstWriterClose(fstfile);
+ }
+
+ void write(std::map<int, bool> &use_signal) override
+ {
+ if (!fstfile) return;
+ std::time_t t = std::time(nullptr);
+ fstWriterSetVersion(fstfile, worker->date ? yosys_version_str : "Yosys");
+ if (worker->date)
+ fstWriterSetDate(fstfile, asctime(std::localtime(&t)));
+ else
+ fstWriterSetDate(fstfile, "");
+ if (!worker->timescale.empty())
+ fstWriterSetTimescaleFromString(fstfile, worker->timescale.c_str());
+
+ fstWriterSetPackType(fstfile, FST_WR_PT_FASTLZ);
+ fstWriterSetRepackOnClose(fstfile, 1);
+
+ worker->top->write_output_header(
+ [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",log_id(name)).c_str(), nullptr); },
+ [this]() { fstWriterSetUpscope(fstfile); },
+ [this,use_signal](Wire *wire, int id, bool is_reg) {
+ if (!use_signal.at(id)) return;
+ fstHandle fst_id = fstWriterCreateVar(fstfile, is_reg ? FST_VT_VCD_REG : FST_VT_VCD_WIRE, FST_VD_IMPLICIT, GetSize(wire),
+ stringf("%s%s", wire->name[0] == '$' ? "\\" : "", log_id(wire)).c_str(), 0);
+
+ mapping.emplace(id, fst_id);
+ }
+ );
+
+ for(auto& d : worker->output_data)
+ {
+ fstWriterEmitTimeChange(fstfile, d.first);
+ for (auto &data : d.second)
+ {
+ if (!use_signal.at(data.first)) continue;
+ Const value = data.second;
+ std::stringstream ss;
+ for (int i = GetSize(value)-1; i >= 0; i--) {
+ switch (value[i]) {
+ case State::S0: ss << "0"; break;
+ case State::S1: ss << "1"; break;
+ case State::Sx: ss << "x"; break;
+ default: ss << "z";
+ }
+ }
+ fstWriterEmitValueChange(fstfile, mapping[data.first], ss.str().c_str());
+ }
+ }
+ }
+
+ struct fstContext *fstfile = nullptr;
+ std::map<int,fstHandle> mapping;
+};
+
+struct AIWWriter : public OutputWriter
+{
+ AIWWriter(SimWorker *worker, std::string filename) : OutputWriter(worker) {
+ aiwfile.open(filename.c_str());
+ }
+
+ virtual ~AIWWriter()
+ {
+ aiwfile << '.' << '\n';
+ }
+
+ void write(std::map<int, bool> &) override
+ {
+ if (!aiwfile.is_open()) return;
+ if (worker->map_filename.empty())
+ log_cmd_error("For AIGER witness file map parameter is mandatory.\n");
+
+ std::ifstream mf(worker->map_filename);
+ std::string type, symbol;
+ int variable, index;
+ if (mf.fail())
+ log_cmd_error("Not able to read AIGER witness map file.\n");
+ while (mf >> type >> variable >> index >> symbol) {
+ RTLIL::IdString escaped_s = RTLIL::escape_id(symbol);
+ Wire *w = worker->top->module->wire(escaped_s);
+ if (!w)
+ log_error("Wire %s not present in module %s\n",log_id(escaped_s),log_id(worker->top->module));
+ if (index < w->start_offset || index > w->start_offset + w->width)
+ log_error("Index %d for wire %s is out of range\n", index, log_signal(w));
+ if (type == "input") {
+ aiw_inputs[variable] = SigBit(w,index-w->start_offset);
+ } else if (type == "init") {
+ aiw_inits[variable] = SigBit(w,index-w->start_offset);
+ } else if (type == "latch") {
+ aiw_latches[variable] = {SigBit(w,index-w->start_offset), false};
+ } else if (type == "invlatch") {
+ aiw_latches[variable] = {SigBit(w,index-w->start_offset), true};
+ }
+ }
+
+ worker->top->write_output_header(
+ [](IdString) {},
+ []() {},
+ [this](Wire *wire, int id, bool) { mapping[wire] = id; }
+ );
+
+ std::map<int, Yosys::RTLIL::Const> current;
+ bool first = true;
+ for(auto& d : worker->output_data)
+ {
+ for (auto &data : d.second)
+ {
+ current[data.first] = data.second;
+ }
+ if (first) {
+ for (int i = 0;; i++)
+ {
+ if (aiw_latches.count(i)) {
+ SigBit bit = aiw_latches.at(i).first;
+ auto v = current[mapping[bit.wire]].bits.at(bit.offset);
+ if (v == State::S1)
+ aiwfile << (aiw_latches.at(i).second ? '0' : '1');
+ else
+ aiwfile << (aiw_latches.at(i).second ? '1' : '0');
+ continue;
+ }
+ aiwfile << '\n';
+ break;
+ }
+ first = false;
+ }
+
+ for (int i = 0;; i++)
+ {
+ if (aiw_inputs.count(i)) {
+ SigBit bit = aiw_inputs.at(i);
+ auto v = current[mapping[bit.wire]].bits.at(bit.offset);
+ if (v == State::S1)
+ aiwfile << '1';
+ else
+ aiwfile << '0';
+ continue;
+ }
+ if (aiw_inits.count(i)) {
+ SigBit bit = aiw_inits.at(i);
+ auto v = current[mapping[bit.wire]].bits.at(bit.offset);
+ if (v == State::S1)
+ aiwfile << '1';
+ else
+ aiwfile << '0';
+ continue;
+ }
+ aiwfile << '\n';
+ break;
+ }
+ }
+ }
+
+ std::ofstream aiwfile;
+ dict<int, std::pair<SigBit, bool>> aiw_latches;
+ dict<int, SigBit> aiw_inputs, aiw_inits;
+ std::map<Wire*,int> mapping;
};
struct SimPass : public Pass {
@@ -767,6 +1795,19 @@ struct SimPass : public Pass {
log(" -vcd <filename>\n");
log(" write the simulation results to the given VCD file\n");
log("\n");
+ log(" -fst <filename>\n");
+ log(" write the simulation results to the given FST file\n");
+ log("\n");
+ log(" -aiw <filename>\n");
+ log(" write the simulation results to an AIGER witness file\n");
+ log(" (requires a *.aim file via -map)\n");
+ log("\n");
+ log(" -x\n");
+ log(" ignore constant x outputs in simulation file.\n");
+ log("\n");
+ log(" -date\n");
+ log(" include date and full version info in output.\n");
+ log("\n");
log(" -clock <portname>\n");
log(" name of top-level clock input\n");
log("\n");
@@ -789,22 +1830,64 @@ struct SimPass : public Pass {
log(" include the specified timescale declaration in the vcd\n");
log("\n");
log(" -n <integer>\n");
- log(" number of cycles to simulate (default: 20)\n");
+ log(" number of clock cycles to simulate (default: 20)\n");
log("\n");
log(" -a\n");
- log(" include all nets in VCD output, not just those with public names\n");
+ log(" use all nets in VCD/FST operations, not just those with public names\n");
log("\n");
log(" -w\n");
log(" writeback mode: use final simulation state as new init state\n");
log("\n");
+ log(" -r\n");
+ log(" read simulation results file (file formats supported: FST, VCD, AIW and WIT)\n");
+ log(" VCD support requires vcd2fst external tool to be present\n");
+ log("\n");
+ log(" -map <filename>\n");
+ log(" read file with port and latch symbols, needed for AIGER witness input\n");
+ log("\n");
+ log(" -scope <name>\n");
+ log(" scope of simulation top model\n");
+ log("\n");
+ log(" -at <time>\n");
+ log(" sets start and stop time\n");
+ log("\n");
+ log(" -start <time>\n");
+ log(" start co-simulation in arbitary time (default 0)\n");
+ log("\n");
+ log(" -stop <time>\n");
+ log(" stop co-simulation in arbitary time (default END)\n");
+ log("\n");
+ log(" -sim\n");
+ log(" simulation with stimulus from FST (default)\n");
+ log("\n");
+ log(" -sim-cmp\n");
+ log(" co-simulation expect exact match\n");
+ log("\n");
+ log(" -sim-gold\n");
+ log(" co-simulation, x in simulation can match any value in FST\n");
+ log("\n");
+ log(" -sim-gate\n");
+ log(" co-simulation, x in FST can match any value in simulation\n");
+ log("\n");
+ log(" -q\n");
+ log(" disable per-cycle/sample log message\n");
+ log("\n");
log(" -d\n");
log(" enable debug output\n");
log("\n");
}
+
+
+ static std::string file_base_name(std::string const & path)
+ {
+ return path.substr(path.find_last_of("/\\") + 1);
+ }
+
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
SimWorker worker;
int numcycles = 20;
+ bool start_set = false, stop_set = false, at_set = false;
log_header(design, "Executing SIM pass (simulate the circuit).\n");
@@ -813,11 +1896,24 @@ struct SimPass : public Pass {
if (args[argidx] == "-vcd" && argidx+1 < args.size()) {
std::string vcd_filename = args[++argidx];
rewrite_filename(vcd_filename);
- worker.vcdfile.open(vcd_filename.c_str());
+ worker.outputfiles.emplace_back(std::unique_ptr<VCDWriter>(new VCDWriter(&worker, vcd_filename.c_str())));
+ continue;
+ }
+ if (args[argidx] == "-fst" && argidx+1 < args.size()) {
+ std::string fst_filename = args[++argidx];
+ rewrite_filename(fst_filename);
+ worker.outputfiles.emplace_back(std::unique_ptr<FSTWriter>(new FSTWriter(&worker, fst_filename.c_str())));
+ continue;
+ }
+ if (args[argidx] == "-aiw" && argidx+1 < args.size()) {
+ std::string aiw_filename = args[++argidx];
+ rewrite_filename(aiw_filename);
+ worker.outputfiles.emplace_back(std::unique_ptr<AIWWriter>(new AIWWriter(&worker, aiw_filename.c_str())));
continue;
}
if (args[argidx] == "-n" && argidx+1 < args.size()) {
numcycles = atoi(args[++argidx].c_str());
+ worker.cycles_set = true;
continue;
}
if (args[argidx] == "-rstlen" && argidx+1 < args.size()) {
@@ -848,6 +1944,10 @@ struct SimPass : public Pass {
worker.hide_internal = false;
continue;
}
+ if (args[argidx] == "-q") {
+ worker.verbose = false;
+ continue;
+ }
if (args[argidx] == "-d") {
worker.debug = true;
continue;
@@ -860,9 +1960,69 @@ struct SimPass : public Pass {
worker.zinit = true;
continue;
}
+ if (args[argidx] == "-r" && argidx+1 < args.size()) {
+ std::string sim_filename = args[++argidx];
+ rewrite_filename(sim_filename);
+ worker.sim_filename = sim_filename;
+ continue;
+ }
+ if (args[argidx] == "-map" && argidx+1 < args.size()) {
+ std::string map_filename = args[++argidx];
+ rewrite_filename(map_filename);
+ worker.map_filename = map_filename;
+ continue;
+ }
+ if (args[argidx] == "-scope" && argidx+1 < args.size()) {
+ worker.scope = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-start" && argidx+1 < args.size()) {
+ worker.start_time = stringToTime(args[++argidx]);
+ start_set = true;
+ continue;
+ }
+ if (args[argidx] == "-stop" && argidx+1 < args.size()) {
+ worker.stop_time = stringToTime(args[++argidx]);
+ stop_set = true;
+ continue;
+ }
+ if (args[argidx] == "-at" && argidx+1 < args.size()) {
+ worker.start_time = stringToTime(args[++argidx]);
+ worker.stop_time = worker.start_time;
+ at_set = true;
+ continue;
+ }
+ if (args[argidx] == "-sim") {
+ worker.sim_mode = SimulationMode::sim;
+ continue;
+ }
+ if (args[argidx] == "-sim-cmp") {
+ worker.sim_mode = SimulationMode::cmp;
+ continue;
+ }
+ if (args[argidx] == "-sim-gold") {
+ worker.sim_mode = SimulationMode::gold;
+ continue;
+ }
+ if (args[argidx] == "-sim-gate") {
+ worker.sim_mode = SimulationMode::gate;
+ continue;
+ }
+ if (args[argidx] == "-x") {
+ worker.ignore_x = true;
+ continue;
+ }
+ if (args[argidx] == "-date") {
+ worker.date = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
+ if (at_set && (start_set || stop_set || worker.cycles_set))
+ log_error("'at' option can only be defined separate of 'start','stop' and 'n'\n");
+ if (stop_set && worker.cycles_set)
+ log_error("'stop' and 'n' can only be used exclusively'\n");
Module *top_mod = nullptr;
@@ -878,8 +2038,139 @@ struct SimPass : public Pass {
top_mod = mods.front();
}
- worker.run(top_mod, numcycles);
+ if (worker.sim_filename.empty())
+ worker.run(top_mod, numcycles);
+ else {
+ std::string filename_trim = file_base_name(worker.sim_filename);
+ if (filename_trim.size() > 4 && ((filename_trim.compare(filename_trim.size()-4, std::string::npos, ".fst") == 0) ||
+ filename_trim.compare(filename_trim.size()-4, std::string::npos, ".vcd") == 0)) {
+ worker.run_cosim_fst(top_mod, numcycles);
+ } else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".aiw") == 0) {
+ if (worker.map_filename.empty())
+ log_cmd_error("For AIGER witness file map parameter is mandatory.\n");
+ worker.run_cosim_aiger_witness(top_mod);
+ } else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".wit") == 0) {
+ worker.run_cosim_btor2_witness(top_mod);
+ } else {
+ log_cmd_error("Unhandled extension for simulation input file `%s`.\n", worker.sim_filename.c_str());
+ }
+ }
}
} SimPass;
+struct Fst2TbPass : public Pass {
+ Fst2TbPass() : Pass("fst2tb", "generate testbench out of fst file") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" fst2tb [options] [top-level]\n");
+ log("\n");
+ log("This command generates testbench for the circuit using the given top-level module\n");
+ log("and simulus signal from FST file\n");
+ log("\n");
+ log(" -tb <name>\n");
+ log(" generated testbench name.\n");
+ log(" files <name>.v and <name>.txt are created as result.\n");
+ log("\n");
+ log(" -r <filename>\n");
+ log(" read simulation FST file\n");
+ log("\n");
+ log(" -clock <portname>\n");
+ log(" name of top-level clock input\n");
+ log("\n");
+ log(" -clockn <portname>\n");
+ log(" name of top-level clock input (inverse polarity)\n");
+ log("\n");
+ log(" -scope <name>\n");
+ log(" scope of simulation top model\n");
+ log("\n");
+ log(" -start <time>\n");
+ log(" start co-simulation in arbitary time (default 0)\n");
+ log("\n");
+ log(" -stop <time>\n");
+ log(" stop co-simulation in arbitary time (default END)\n");
+ log("\n");
+ log(" -n <integer>\n");
+ log(" number of clock cycles to simulate (default: 20)\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ SimWorker worker;
+ int numcycles = 20;
+ bool stop_set = false;
+ std::string tb_filename;
+
+ log_header(design, "Executing FST2FB pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-clock" && argidx+1 < args.size()) {
+ worker.clock.insert(RTLIL::escape_id(args[++argidx]));
+ continue;
+ }
+ if (args[argidx] == "-clockn" && argidx+1 < args.size()) {
+ worker.clockn.insert(RTLIL::escape_id(args[++argidx]));
+ continue;
+ }
+ if (args[argidx] == "-r" && argidx+1 < args.size()) {
+ std::string sim_filename = args[++argidx];
+ rewrite_filename(sim_filename);
+ worker.sim_filename = sim_filename;
+ continue;
+ }
+ if (args[argidx] == "-n" && argidx+1 < args.size()) {
+ numcycles = atoi(args[++argidx].c_str());
+ worker.cycles_set = true;
+ continue;
+ }
+ if (args[argidx] == "-scope" && argidx+1 < args.size()) {
+ worker.scope = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-start" && argidx+1 < args.size()) {
+ worker.start_time = stringToTime(args[++argidx]);
+ continue;
+ }
+ if (args[argidx] == "-stop" && argidx+1 < args.size()) {
+ worker.stop_time = stringToTime(args[++argidx]);
+ stop_set = true;
+ continue;
+ }
+ if (args[argidx] == "-tb" && argidx+1 < args.size()) {
+ tb_filename = args[++argidx];
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+ if (stop_set && worker.cycles_set)
+ log_error("'stop' and 'n' can only be used exclusively'\n");
+
+ Module *top_mod = nullptr;
+
+ if (design->full_selection()) {
+ top_mod = design->top_module();
+
+ if (!top_mod)
+ log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n");
+ } else {
+ auto mods = design->selected_whole_modules();
+ if (GetSize(mods) != 1)
+ log_cmd_error("Only one top module must be selected.\n");
+ top_mod = mods.front();
+ }
+
+ if (tb_filename.empty())
+ log_cmd_error("Testbench name must be defined.\n");
+
+ if (worker.sim_filename.empty())
+ log_cmd_error("Stimulus FST file must be defined.\n");
+
+ worker.generate_tb(top_mod, tb_filename, numcycles);
+ }
+} Fst2TbPass;
+
PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 035699603..98ccfc303 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -29,6 +29,8 @@ OBJS += passes/techmap/extract_reduce.o
OBJS += passes/techmap/alumacc.o
OBJS += passes/techmap/dffinit.o
OBJS += passes/techmap/pmuxtree.o
+OBJS += passes/techmap/bmuxmap.o
+OBJS += passes/techmap/demuxmap.o
OBJS += passes/techmap/muxcover.o
OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 80c6282c4..2c91f3a48 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -757,10 +757,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
- for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
+ for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{I}", pos))
abc_script = abc_script.substr(0, pos) + sop_inputs + abc_script.substr(pos+3);
- for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
+ for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{P}", pos))
abc_script = abc_script.substr(0, pos) + sop_products + abc_script.substr(pos+3);
for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 29fe74ec7..b8975f178 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -167,10 +167,6 @@ void prep_hier(RTLIL::Design *design, bool dff_mode)
derived_module = inst_module;
}
else {
- // Check potential for any one of those three
- // (since its value may depend on a parameter, but not its existence)
- if (!inst_module->has_attribute(ID::abc9_flop) && !inst_module->has_attribute(ID::abc9_box) && !inst_module->get_bool_attribute(ID::abc9_bypass))
- continue;
derived_type = inst_module->derive(design, cell->parameters);
derived_module = design->module(derived_type);
}
@@ -180,7 +176,16 @@ void prep_hier(RTLIL::Design *design, bool dff_mode)
continue;
}
else {
- if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass)) {
+ bool has_timing = false;
+ for (auto derived_cell : derived_module->cells()) {
+ if (derived_cell->type.in(ID($specify2), ID($specify3), ID($specrule))) {
+ // If the module contains timing; then we potentially care about deriving its content too,
+ // as timings (or associated port widths) could be dependent on parameters.
+ has_timing = true;
+ break;
+ }
+ }
+ if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass) && !has_timing) {
if (unmap_design->module(derived_type)) {
// If derived_type is present in unmap_design, it means that it was processed previously, but found to be incompatible -- e.g. if
// it contained a non-zero initial state. In this case, continue to replace the cell type/parameters so that it has the same properties
diff --git a/passes/techmap/bmuxmap.cc b/passes/techmap/bmuxmap.cc
new file mode 100644
index 000000000..03673c278
--- /dev/null
+++ b/passes/techmap/bmuxmap.cc
@@ -0,0 +1,76 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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 BmuxmapPass : public Pass {
+ BmuxmapPass() : Pass("bmuxmap", "transform $bmux cells to trees of $mux cells") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" bmuxmap [selection]\n");
+ log("\n");
+ log("This pass transforms $bmux cells to trees of $mux cells.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing BMUXMAP pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type != ID($bmux))
+ continue;
+
+ SigSpec sel = cell->getPort(ID::S);
+ SigSpec data = cell->getPort(ID::A);
+ int width = GetSize(cell->getPort(ID::Y));
+
+ for (int idx = 0; idx < GetSize(sel); idx++) {
+ SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2);
+ for (int i = 0; i < GetSize(new_data); i += width) {
+ RTLIL::Cell *mux = module->addMux(NEW_ID,
+ data.extract(i*2, width),
+ data.extract(i*2+width, width),
+ sel[idx],
+ new_data.extract(i, width));
+ mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ }
+ data = new_data;
+ }
+
+ module->connect(cell->getPort(ID::Y), data);
+ module->remove(cell);
+ }
+ }
+} BmuxmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/demuxmap.cc b/passes/techmap/demuxmap.cc
new file mode 100644
index 000000000..292b18bad
--- /dev/null
+++ b/passes/techmap/demuxmap.cc
@@ -0,0 +1,80 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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 DemuxmapPass : public Pass {
+ DemuxmapPass() : Pass("demuxmap", "transform $demux cells to $eq + $mux cells") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" demuxmap [selection]\n");
+ log("\n");
+ log("This pass transforms $demux cells to a bunch of equality comparisons.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing DEMUXMAP pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type != ID($demux))
+ continue;
+
+ SigSpec sel = cell->getPort(ID::S);
+ SigSpec data = cell->getPort(ID::A);
+ SigSpec out = cell->getPort(ID::Y);
+ int width = GetSize(cell->getPort(ID::A));
+
+ for (int i = 0; i < 1 << GetSize(sel); i++) {
+ if (width == 1 && data == State::S1) {
+ RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), out[i]);
+ eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ } else {
+ Wire *eq = module->addWire(NEW_ID);
+ RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), eq);
+ eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ RTLIL::Cell *mux = module->addMux(NEW_ID,
+ Const(State::S0, width),
+ data,
+ eq,
+ out.extract(i*width, width));
+ mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ }
+ }
+
+ module->remove(cell);
+ }
+ }
+} DemuxmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 990e28876..437ad5156 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -46,7 +46,7 @@ struct IopadmapPass : public Pass {
log(" -inpad <celltype> <in_port>[:<ext_port>]\n");
log(" Map module input ports to the given cell type with the\n");
log(" given output port name. if a 2nd portname is given, the\n");
- log(" signal is passed through the pad call, using the 2nd\n");
+ log(" signal is passed through the pad cell, using the 2nd\n");
log(" portname as the port facing the module port.\n");
log("\n");
log(" -outpad <celltype> <out_port>[:<ext_port>]\n");
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index 68f44cf6d..7d8dba439 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -299,6 +299,30 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
+void simplemap_bmux(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ SigSpec sel = cell->getPort(ID::S);
+ SigSpec data = cell->getPort(ID::A);
+ int width = GetSize(cell->getPort(ID::Y));
+
+ for (int idx = 0; idx < GetSize(sel); idx++) {
+ SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2);
+ for (int i = 0; i < GetSize(new_data); i += width) {
+ for (int k = 0; k < width; k++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::A, data[i*2+k]);
+ gate->setPort(ID::B, data[i*2+width+k]);
+ gate->setPort(ID::S, sel[idx]);
+ gate->setPort(ID::Y, new_data[i+k]);
+ }
+ }
+ data = new_data;
+ }
+
+ module->connect(cell->getPort(ID::Y), data);
+}
+
void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
{
SigSpec lut_ctrl = cell->getPort(ID::A);
@@ -306,7 +330,6 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
lut_data.extend_u0(1 << cell->getParam(ID::WIDTH).as_int());
for (int idx = 0; GetSize(lut_data) > 1; idx++) {
- SigSpec sig_s = lut_ctrl[idx];
SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);
for (int i = 0; i < GetSize(lut_data); i += 2) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
@@ -400,6 +423,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
mappers[ID($nex)] = simplemap_eqne;
mappers[ID($mux)] = simplemap_mux;
mappers[ID($tribuf)] = simplemap_tribuf;
+ mappers[ID($bmux)] = simplemap_bmux;
mappers[ID($lut)] = simplemap_lut;
mappers[ID($sop)] = simplemap_sop;
mappers[ID($slice)] = simplemap_slice;
diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc
index 4e437e409..e21ec452c 100644
--- a/passes/tests/test_cell.cc
+++ b/passes/tests/test_cell.cc
@@ -69,6 +69,48 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->setPort(ID::Y, wire);
}
+ if (cell_type == ID($bmux))
+ {
+ int width = 1 + xorshift32(8);
+ int swidth = 1 + xorshift32(4);
+
+ wire = module->addWire(ID::A);
+ wire->width = width << swidth;
+ wire->port_input = true;
+ cell->setPort(ID::A, wire);
+
+ wire = module->addWire(ID::S);
+ wire->width = swidth;
+ wire->port_input = true;
+ cell->setPort(ID::S, wire);
+
+ wire = module->addWire(ID::Y);
+ wire->width = width;
+ wire->port_output = true;
+ cell->setPort(ID::Y, wire);
+ }
+
+ if (cell_type == ID($demux))
+ {
+ int width = 1 + xorshift32(8);
+ int swidth = 1 + xorshift32(6);
+
+ wire = module->addWire(ID::A);
+ wire->width = width;
+ wire->port_input = true;
+ cell->setPort(ID::A, wire);
+
+ wire = module->addWire(ID::S);
+ wire->width = swidth;
+ wire->port_input = true;
+ cell->setPort(ID::S, wire);
+
+ wire = module->addWire(ID::Y);
+ wire->width = width << swidth;
+ wire->port_output = true;
+ cell->setPort(ID::Y, wire);
+ }
+
if (cell_type == ID($fa))
{
int width = 1 + xorshift32(8);
@@ -855,8 +897,10 @@ struct TestCellPass : public Pass {
cell_types[ID($logic_and)] = "ABSY";
cell_types[ID($logic_or)] = "ABSY";
+ cell_types[ID($mux)] = "*";
+ cell_types[ID($bmux)] = "*";
+ cell_types[ID($demux)] = "*";
if (edges) {
- cell_types[ID($mux)] = "*";
cell_types[ID($pmux)] = "*";
}
diff --git a/techlibs/anlogic/.gitignore b/techlibs/anlogic/.gitignore
new file mode 100644
index 000000000..d127107db
--- /dev/null
+++ b/techlibs/anlogic/.gitignore
@@ -0,0 +1,2 @@
+brams_init.mk
+brams_init_*.vh
diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc
index 2d8d65e2e..79519c645 100644
--- a/techlibs/anlogic/Makefile.inc
+++ b/techlibs/anlogic/Makefile.inc
@@ -3,6 +3,22 @@ OBJS += techlibs/anlogic/synth_anlogic.o
OBJS += techlibs/anlogic/anlogic_eqn.o
OBJS += techlibs/anlogic/anlogic_fixcarry.o
+GENFILES += techlibs/anlogic/brams_init_16.vh
+GENFILES += techlibs/anlogic/brams_init_9.vh
+GENFILES += techlibs/anlogic/brams_init_8.vh
+
+EXTRA_OBJS += techlibs/anlogic/brams_init.mk
+.SECONDARY: techlibs/anlogic/brams_init.mk
+
+techlibs/anlogic/brams_init.mk: techlibs/anlogic/brams_init.py
+ $(Q) mkdir -p techlibs/anlogic
+ $(P) $(PYTHON_EXECUTABLE) $<
+ $(Q) touch $@
+
+techlibs/anlogic/brams_init_16.vh: techlibs/anlogic/brams_init.mk
+techlibs/anlogic/brams_init_9.vh: techlibs/anlogic/brams_init.mk
+techlibs/anlogic/brams_init_8.vh: techlibs/anlogic/brams_init.mk
+
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v))
@@ -10,3 +26,9 @@ $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams.txt))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutram_init_16x4.vh))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/brams.txt))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/brams_map.v))
+
+$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_16.vh))
+$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_9.vh))
+$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_8.vh))
diff --git a/techlibs/anlogic/brams.txt b/techlibs/anlogic/brams.txt
new file mode 100644
index 000000000..a39701c63
--- /dev/null
+++ b/techlibs/anlogic/brams.txt
@@ -0,0 +1,43 @@
+bram $__ANLOGIC_BRAM9K_TDP
+ init 1
+ abits 13 @a13d1
+ dbits 1 @a13d1
+ abits 12 @a12d2
+ dbits 2 @a12d2
+ abits 11 @a11d4
+ dbits 4 @a11d4
+ abits 10 @a10d9
+ dbits 9 @a10d9
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 1
+ transp 2 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__ANLOGIC_BRAM32K
+ init 1
+ abits 11
+ dbits 16
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 2
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__ANLOGIC_BRAM32K
+ min efficiency 30
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__ANLOGIC_BRAM9K_TDP
+ min efficiency 5
+ make_transp
+endmatch
diff --git a/techlibs/anlogic/brams_init.py b/techlibs/anlogic/brams_init.py
new file mode 100644
index 000000000..8dda0d33e
--- /dev/null
+++ b/techlibs/anlogic/brams_init.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+
+with open("techlibs/anlogic/brams_init_9.vh", "w") as f:
+ for i in range(4):
+ init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+ for k in range(4, 256, 4):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+ for i in range(32):
+ init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+ for k in range(4, 32, 4):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+
+with open("techlibs/anlogic/brams_init_8.vh", "w") as f:
+ for i in range(32):
+ print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
+
+with open("techlibs/anlogic/brams_init_16.vh", "w") as f:
+ for i in range(128):
+ print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
diff --git a/techlibs/anlogic/brams_map.v b/techlibs/anlogic/brams_map.v
new file mode 100644
index 000000000..ee02b6d7c
--- /dev/null
+++ b/techlibs/anlogic/brams_map.v
@@ -0,0 +1,162 @@
+module \$__ANLOGIC_BRAM9K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 9;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [9215:0] INIT = 9216'bx;
+ parameter TRANSP2 = 0;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+ input A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ localparam CLKAMUX = CLKPOL2 ? "SIG" : "INV";
+ localparam CLKBMUX = CLKPOL3 ? "SIG" : "INV";
+
+ localparam WRITEMODE_B = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE";
+
+ localparam DATA_WIDTH = CFG_DBITS == 1 ? "1" :
+ (CFG_DBITS == 2 ? "2" :
+ (CFG_DBITS <= 4 ? "4" : "9"));
+
+ localparam APADBITS = $clog2(CFG_DBITS == 9 ? 8 : CFG_DBITS);
+
+ wire [12:0] addra;
+ wire [12:0] addrb;
+
+ assign addra[12:APADBITS] = A1ADDR;
+ assign addrb[12:APADBITS] = B1ADDR;
+
+ wire [8:0] doa;
+ wire [8:0] dib;
+
+ assign A1DATA[CFG_DBITS-1:0] = doa;
+ assign dib[CFG_DBITS-1:0] = B1DATA;
+
+ generate if (CFG_DBITS == 9) begin
+ EG_PHY_BRAM #(
+ .MODE("DP8K"),
+ .DATA_WIDTH_A(DATA_WIDTH),
+ .DATA_WIDTH_B(DATA_WIDTH),
+ .READBACK("OFF"),
+ .REGMODE_A("NOREG"),
+ .REGMODE_B("NOREG"),
+ .WRITEMODE_A("READBEFOREWRITE"),
+ .WRITEMODE_B(WRITEMODE_B),
+ .RESETMODE("ASYNC"),
+ .CEAMUX("SIG"), .CEBMUX("SIG"),
+ .OCEAMUX("1"), .OCEBMUX("1"),
+ .RSTAMUX("0"), .RSTBMUX("0"),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WEAMUX("0"), .WEBMUX("SIG"),
+ .CSA0("1"), .CSA1("1"),
+ .CSA2("1"), .CSB0("1"),
+ .CSB1("1"), .CSB2("1"),
+ `include "brams_init_9.vh"
+ ) _TECHMAP_REPLACE_ (
+ .doa(doa), .dib(dib),
+ .addra(addra), .addrb(addrb),
+ .clka(CLK2), .clkb(CLK3),
+ .cea(A1EN), .ceb(B1EN),
+ .ocea(1'b1), .oceb(1'b1),
+ .rsta(1'b0), .rstb(1'b0),
+ .wea(1'b0), .web(B1EN),
+ .csa(3'b111), .csb(3'b111)
+ );
+ end else begin
+ EG_PHY_BRAM #(
+ .MODE("DP8K"),
+ .DATA_WIDTH_A(DATA_WIDTH),
+ .DATA_WIDTH_B(DATA_WIDTH),
+ .READBACK("OFF"),
+ .REGMODE_A("NOREG"),
+ .REGMODE_B("NOREG"),
+ .WRITEMODE_A("READBEFOREWRITE"),
+ .WRITEMODE_B(WRITEMODE_B),
+ .RESETMODE("ASYNC"),
+ .CEAMUX("SIG"), .CEBMUX("SIG"),
+ .OCEAMUX("1"), .OCEBMUX("1"),
+ .RSTAMUX("0"), .RSTBMUX("0"),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WEAMUX("0"), .WEBMUX("SIG"),
+ .CSA0("1"), .CSA1("1"),
+ .CSA2("1"), .CSB0("1"),
+ .CSB1("1"), .CSB2("1"),
+ `include "brams_init_8.vh"
+ ) _TECHMAP_REPLACE_ (
+ .doa(doa), .dib(dib),
+ .addra(addra), .addrb(addrb),
+ .clka(CLK2), .clkb(CLK3),
+ .cea(A1EN), .ceb(B1EN),
+ .ocea(1'b1), .oceb(1'b1),
+ .rsta(1'b0), .rstb(1'b0),
+ .wea(1'b0), .web(B1EN),
+ .csa(3'b111), .csb(3'b111)
+ );
+ end endgenerate
+endmodule
+
+module \$__ANLOGIC_BRAM32K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 11;
+ parameter CFG_DBITS = 16;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [32767:0] INIT = 32768'bx;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+ input A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input [1:0] B1EN;
+
+ localparam CLKAMUX = CLKPOL2 ? "SIG" : "INV";
+ localparam CLKBMUX = CLKPOL3 ? "SIG" : "INV";
+
+ wire byteweb = B1EN[1] ^ B1EN[0];
+ wire byteb = B1EN[1];
+
+ EG_PHY_BRAM32K #(
+ .MODE("DP16K"),
+ .DATA_WIDTH_A("16"),
+ .DATA_WIDTH_B("16"),
+ .REGMODE_A("NOREG"),
+ .REGMODE_B("NOREG"),
+ .WRITEMODE_A("NORMAL"),
+ .WRITEMODE_B("NORMAL"),
+ .SRMODE("ASYNC"),
+ .CSAMUX("SIG"), .CSBMUX("SIG"),
+ .OCEAMUX("1"), .OCEBMUX("1"),
+ .RSTAMUX("0"), .RSTBMUX("0"),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WEAMUX("0"), .WEBMUX("SIG"),
+ .READBACK("OFF"),
+ `include "brams_init_16.vh"
+ ) _TECHMAP_REPLACE_ (
+ .doa(A1DATA), .dib(B1DATA),
+ .addra(A1ADDR), .addrb(B1ADDR),
+ .bytea(1'b0), .byteb(byteb),
+ .bytewea(1'b0), .byteweb(byteweb),
+ .csa(A1EN), .csb(|B1EN),
+ .wea(1'b0), .web(|B1EN),
+ .clka(CLK2), .clkb(CLK3),
+ .rsta(1'b0), .rstb(1'b0),
+ .ocea(1'b1), .oceb(1'b1)
+ );
+endmodule
diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc
index 039cae00e..5da14c26b 100644
--- a/techlibs/anlogic/synth_anlogic.cc
+++ b/techlibs/anlogic/synth_anlogic.cc
@@ -63,6 +63,9 @@ struct SynthAnlogicPass : public ScriptPass
log(" -nolutram\n");
log(" do not use EG_LOGIC_DRAM16X4 cells in output netlist\n");
log("\n");
+ log(" -nobram\n");
+ log(" do not use EG_PHY_BRAM or EG_PHY_BRAM32K cells in output netlist\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
@@ -70,7 +73,7 @@ struct SynthAnlogicPass : public ScriptPass
}
string top_opt, edif_file, json_file;
- bool flatten, retime, nolutram;
+ bool flatten, retime, nolutram, nobram;
void clear_flags() override
{
@@ -80,6 +83,7 @@ struct SynthAnlogicPass : public ScriptPass
flatten = true;
retime = false;
nolutram = false;
+ nobram = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -118,6 +122,10 @@ struct SynthAnlogicPass : public ScriptPass
nolutram = true;
continue;
}
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
if (args[argidx] == "-retime") {
retime = true;
continue;
@@ -158,6 +166,14 @@ struct SynthAnlogicPass : public ScriptPass
run("synth -run coarse");
}
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/anlogic/brams.txt");
+ run("techmap -map +/anlogic/brams_map.v");
+ run("setundef -zero -params t:EG_PHY_BRAM");
+ run("setundef -zero -params t:EG_PHY_BRAM32K");
+ }
+
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
{
run("memory_bram -rules +/anlogic/lutrams.txt");
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index e9129f690..b14488ff4 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1292,6 +1292,33 @@ endmodule
// --------------------------------------------------------
+module \$bmux (A, S, Y);
+
+parameter WIDTH = 0;
+parameter S_WIDTH = 0;
+
+input [(WIDTH << S_WIDTH)-1:0] A;
+input [S_WIDTH-1:0] S;
+output [WIDTH-1:0] Y;
+
+wire [WIDTH-1:0] bm0_out, bm1_out;
+
+generate
+ if (S_WIDTH > 1) begin:muxlogic
+ \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm0 (.A(A), .S(S[S_WIDTH-2:0]), .Y(bm0_out));
+ \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm1 (.A(A[(WIDTH << S_WIDTH)-1:WIDTH << (S_WIDTH - 1)]), .S(S[S_WIDTH-2:0]), .Y(bm1_out));
+ assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
+ end else if (S_WIDTH == 1) begin:simple
+ assign Y = S ? A[1] : A[0];
+ end else begin:passthru
+ assign Y = A;
+ end
+endgenerate
+
+endmodule
+
+// --------------------------------------------------------
+
module \$pmux (A, B, S, Y);
parameter WIDTH = 0;
@@ -1318,6 +1345,26 @@ end
endmodule
// --------------------------------------------------------
+
+module \$demux (A, S, Y);
+
+parameter WIDTH = 1;
+parameter S_WIDTH = 1;
+
+input [WIDTH-1:0] A;
+input [S_WIDTH-1:0] S;
+output [(WIDTH << S_WIDTH)-1:0] Y;
+
+genvar i;
+generate
+ for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
+ assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
+ end
+endgenerate
+
+endmodule
+
+// --------------------------------------------------------
`ifndef SIMLIB_NOLUT
module \$lut (A, Y);
@@ -1326,30 +1373,9 @@ parameter WIDTH = 0;
parameter LUT = 0;
input [WIDTH-1:0] A;
-output reg Y;
-
-wire lut0_out, lut1_out;
+output Y;
-generate
- if (WIDTH <= 1) begin:simple
- assign {lut1_out, lut0_out} = LUT;
- end else begin:complex
- \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) );
- \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) );
- end
-
- if (WIDTH > 0) begin:lutlogic
- always @* begin
- casez ({A[WIDTH-1], lut0_out, lut1_out})
- 3'b?11: Y = 1'b1;
- 3'b?00: Y = 1'b0;
- 3'b0??: Y = lut0_out;
- 3'b1??: Y = lut1_out;
- default: Y = 1'bx;
- endcase
- end
- end
-endgenerate
+\$bmux #(.WIDTH(1), .S_WIDTH(WIDTH)) mux(.A(LUT), .S(A), .Y(Y));
endmodule
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
index 667773e1b..91d385b80 100644
--- a/techlibs/common/techmap.v
+++ b/techlibs/common/techmap.v
@@ -59,7 +59,7 @@ module _90_simplemap_compare_ops;
endmodule
(* techmap_simplemap *)
-(* techmap_celltype = "$pos $slice $concat $mux $tribuf" *)
+(* techmap_celltype = "$pos $slice $concat $mux $tribuf $bmux" *)
module _90_simplemap_various;
endmodule
@@ -597,6 +597,43 @@ module _90_pmux (A, B, S, Y);
assign Y = |S ? Y_B : A;
endmodule
+// --------------------------------------------------------
+// Demultiplexers
+// --------------------------------------------------------
+
+(* techmap_celltype = "$demux" *)
+module _90_demux (A, S, Y);
+ parameter WIDTH = 1;
+ parameter S_WIDTH = 1;
+
+ (* force_downto *)
+ input [WIDTH-1:0] A;
+ (* force_downto *)
+ input [S_WIDTH-1:0] S;
+ (* force_downto *)
+ output [(WIDTH << S_WIDTH)-1:0] Y;
+
+ generate
+ if (S_WIDTH == 0) begin
+ assign Y = A;
+ end else if (S_WIDTH == 1) begin
+ assign Y[0+:WIDTH] = S ? 0 : A;
+ assign Y[WIDTH+:WIDTH] = S ? A : 0;
+ end else begin
+ localparam SPLIT = S_WIDTH / 2;
+ wire [(1 << (S_WIDTH-SPLIT))-1:0] YH;
+ wire [(1 << SPLIT)-1:0] YL;
+ $demux #(.WIDTH(1), .S_WIDTH(SPLIT)) lo (.A(1'b1), .S(S[SPLIT-1:0]), .Y(YL));
+ $demux #(.WIDTH(1), .S_WIDTH(S_WIDTH-SPLIT)) hi (.A(1'b1), .S(S[S_WIDTH-1:SPLIT]), .Y(YH));
+ genvar i;
+ for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin
+ localparam [S_WIDTH-1:0] IDX = i;
+ assign Y[i*WIDTH+:WIDTH] = (YL[IDX[SPLIT-1:0]] & YH[IDX[S_WIDTH-1:SPLIT]]) ? A : 0;
+ end
+ end
+ endgenerate
+endmodule
+
// --------------------------------------------------------
// LUTs
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index 357fd9173..76099f493 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -204,7 +204,7 @@ module TRELLIS_DPR16X4 (
integer i;
initial begin
for (i = 0; i < 16; i = i + 1)
- mem[i] <= {INITVAL[i+3], INITVAL[i+2], INITVAL[i+1], INITVAL[i]};
+ mem[i] <= INITVAL[4*i +: 4];
end
wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
@@ -355,37 +355,24 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
end
endgenerate
- generate
- // TODO
- if (CLKMUX == "INV")
- specify
- $setup(DI, negedge CLK, 0);
- $setup(CE, negedge CLK, 0);
- $setup(LSR, negedge CLK, 0);
-`ifndef YOSYS
- if (SRMODE == "ASYNC" && muxlsr) (negedge CLK => (Q : srval)) = 0;
-`else
- if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path
- // but for facilitating a bypass box, let's pretend it's
- // a simple path
-`endif
- if (!muxlsr && muxce) (negedge CLK => (Q : DI)) = 0;
- endspecify
- else
- specify
- $setup(DI, posedge CLK, 0);
- $setup(CE, posedge CLK, 0);
- $setup(LSR, posedge CLK, 0);
+ specify
+ $setup(DI, negedge CLK &&& CLKMUX == "INV", 0);
+ $setup(CE, negedge CLK &&& CLKMUX == "INV", 0);
+ $setup(LSR, negedge CLK &&& CLKMUX == "INV", 0);
+ $setup(DI, posedge CLK &&& CLKMUX != "INV", 0);
+ $setup(CE, posedge CLK &&& CLKMUX != "INV", 0);
+ $setup(LSR, posedge CLK &&& CLKMUX != "INV", 0);
`ifndef YOSYS
- if (SRMODE == "ASYNC" && muxlsr) (posedge CLK => (Q : srval)) = 0;
+ if (SRMODE == "ASYNC" && muxlsr && CLKMUX == "INV") (negedge CLK => (Q : srval)) = 0;
+ if (SRMODE == "ASYNC" && muxlsr && CLKMUX != "INV") (posedge CLK => (Q : srval)) = 0;
`else
- if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path
- // but for facilitating a bypass box, let's pretend it's
- // a simple path
+ if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path
+ // but for facilitating a bypass box, let's pretend it's
+ // a simple path
`endif
- if (!muxlsr && muxce) (posedge CLK => (Q : DI)) = 0;
- endspecify
- endgenerate
+ if (!muxlsr && muxce && CLKMUX == "INV") (negedge CLK => (Q : DI)) = 0;
+ if (!muxlsr && muxce && CLKMUX != "INV") (posedge CLK => (Q : DI)) = 0;
+ endspecify
endmodule
// ---------------------------------------
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 41398409d..736aa0707 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -550,7 +550,6 @@ module GND(output G);
assign G = 0;
endmodule
-(* abc9_box *)
module IBUF(output O, input I);
specify
@@ -560,7 +559,6 @@ module IBUF(output O, input I);
assign O = I;
endmodule
-(* abc9_box *)
module OBUF(output O, input I);
specify
@@ -584,6 +582,39 @@ module IOBUF (O, IO, I, OEN);
assign I = IO;
endmodule
+module TLVDS_OBUF (I, O, OB);
+ input I;
+ output O;
+ output OB;
+ assign O = I;
+ assign OB = ~I;
+endmodule
+
+(* blackbox *)
+module ODDR(D0, D1, TX, CLK, Q0, Q1);
+ input D0;
+ input D1;
+ input TX;
+ input CLK;
+ output Q0;
+ output Q1;
+ parameter TXCLK_POL = 0;
+ parameter INIT = 0;
+endmodule
+
+(* blackbox *)
+module ODDRC(D0, D1, CLEAR, TX, CLK, Q0, Q1);
+ input D0;
+ input D1;
+ input CLEAR;
+ input TX;
+ input CLK;
+ output Q0;
+ output Q1;
+ parameter TXCLK_POL = 0;
+ parameter INIT = 0;
+endmodule
+
module GSR (input GSRI);
wire GSRO = GSRI;
endmodule
@@ -674,134 +705,610 @@ end
endmodule
+
+module RAM16S1 (DO, DI, AD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+
+input [3:0] AD;
+input DI;
+output DO;
+input CLK;
+input WRE;
+
+specify
+ (AD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(AD, posedge CLK, 62);
+ (posedge CLK => (DO : 1'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem;
+
+initial begin
+ mem = INIT_0;
+end
+
+assign DO = mem[AD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem[AD] <= DI;
+ end
+end
+
+endmodule
+
+
+module RAM16S2 (DO, DI, AD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+
+input [3:0] AD;
+input [1:0] DI;
+output [1:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (AD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(AD, posedge CLK, 62);
+ (posedge CLK => (DO : 2'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+end
+
+assign DO[0] = mem0[AD];
+assign DO[1] = mem1[AD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[AD] <= DI[0];
+ mem1[AD] <= DI[1];
+ end
+end
+
+endmodule
+
+
module RAM16S4 (DO, DI, AD, WRE, CLK);
- parameter WIDTH = 4;
- parameter INIT_0 = 16'h0000;
- parameter INIT_1 = 16'h0000;
- parameter INIT_2 = 16'h0000;
- parameter INIT_3 = 16'h0000;
-
- input [WIDTH-1:0] AD;
- input [WIDTH-1:0] DI;
- output [WIDTH-1:0] DO;
- input CLK;
- input WRE;
- specify
- (AD => DO) = (270, 405);
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+parameter INIT_2 = 16'h0000;
+parameter INIT_3 = 16'h0000;
+
+input [3:0] AD;
+input [3:0] DI;
+output [3:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (AD *> DO) = (270, 405);
$setup(DI, posedge CLK, 62);
$setup(WRE, posedge CLK, 62);
$setup(AD, posedge CLK, 62);
- (posedge CLK => (DO : {WIDTH{1'bx}})) = (474, 565);
- endspecify
+ (posedge CLK => (DO : 4'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1, mem2, mem3;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+ mem2 = INIT_2;
+ mem3 = INIT_3;
+end
+
+assign DO[0] = mem0[AD];
+assign DO[1] = mem1[AD];
+assign DO[2] = mem2[AD];
+assign DO[3] = mem3[AD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[AD] <= DI[0];
+ mem1[AD] <= DI[1];
+ mem2[AD] <= DI[2];
+ mem3[AD] <= DI[3];
+ end
+end
+
+endmodule
+
+
+module RAM16SDP1 (DO, DI, WAD, RAD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+
+input [3:0] WAD;
+input [3:0] RAD;
+input DI;
+output DO;
+input CLK;
+input WRE;
+
+specify
+ (RAD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(WAD, posedge CLK, 62);
+ (posedge CLK => (DO : 1'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem;
+
+initial begin
+ mem = INIT_0;
+end
+
+assign DO = mem[RAD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem[WAD] <= DI;
+ end
+end
+
+endmodule
+
+
+module RAM16SDP2 (DO, DI, WAD, RAD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+
+input [3:0] WAD;
+input [3:0] RAD;
+input [1:0] DI;
+output [1:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (RAD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(WAD, posedge CLK, 62);
+ (posedge CLK => (DO : 2'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+end
+
+assign DO[0] = mem0[RAD];
+assign DO[1] = mem1[RAD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[WAD] <= DI[0];
+ mem1[WAD] <= DI[1];
+ end
+end
+
+endmodule
+
+
+module RAM16SDP4 (DO, DI, WAD, RAD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+parameter INIT_2 = 16'h0000;
+parameter INIT_3 = 16'h0000;
+
+input [3:0] WAD;
+input [3:0] RAD;
+input [3:0] DI;
+output [3:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (RAD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(WAD, posedge CLK, 62);
+ (posedge CLK => (DO : 4'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1, mem2, mem3;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+ mem2 = INIT_2;
+ mem3 = INIT_3;
+end
+
+assign DO[0] = mem0[RAD];
+assign DO[1] = mem1[RAD];
+assign DO[2] = mem2[RAD];
+assign DO[3] = mem3[RAD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[WAD] <= DI[0];
+ mem1[WAD] <= DI[1];
+ mem2[WAD] <= DI[2];
+ mem3[WAD] <= DI[3];
+ end
+end
+
+endmodule
+
+
+(* blackbox *)
+module SP (DO, DI, BLKSEL, AD, WRE, CLK, CE, OCE, RESET);
+
+// 1 Enables output pipeline registers.
+parameter READ_MODE = 1'b0;
+// 0: no read on write, 1: transparent, 2: read-before-write
+parameter WRITE_MODE = 2'b00;
+parameter BIT_WIDTH = 32; // 1, 2, 4, 8, 16, 32
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 256'h0;
+parameter INIT_RAM_01 = 256'h0;
+parameter INIT_RAM_02 = 256'h0;
+parameter INIT_RAM_03 = 256'h0;
+parameter INIT_RAM_04 = 256'h0;
+parameter INIT_RAM_05 = 256'h0;
+parameter INIT_RAM_06 = 256'h0;
+parameter INIT_RAM_07 = 256'h0;
+parameter INIT_RAM_08 = 256'h0;
+parameter INIT_RAM_09 = 256'h0;
+parameter INIT_RAM_0A = 256'h0;
+parameter INIT_RAM_0B = 256'h0;
+parameter INIT_RAM_0C = 256'h0;
+parameter INIT_RAM_0D = 256'h0;
+parameter INIT_RAM_0E = 256'h0;
+parameter INIT_RAM_0F = 256'h0;
+parameter INIT_RAM_10 = 256'h0;
+parameter INIT_RAM_11 = 256'h0;
+parameter INIT_RAM_12 = 256'h0;
+parameter INIT_RAM_13 = 256'h0;
+parameter INIT_RAM_14 = 256'h0;
+parameter INIT_RAM_15 = 256'h0;
+parameter INIT_RAM_16 = 256'h0;
+parameter INIT_RAM_17 = 256'h0;
+parameter INIT_RAM_18 = 256'h0;
+parameter INIT_RAM_19 = 256'h0;
+parameter INIT_RAM_1A = 256'h0;
+parameter INIT_RAM_1B = 256'h0;
+parameter INIT_RAM_1C = 256'h0;
+parameter INIT_RAM_1D = 256'h0;
+parameter INIT_RAM_1E = 256'h0;
+parameter INIT_RAM_1F = 256'h0;
+parameter INIT_RAM_20 = 256'h0;
+parameter INIT_RAM_21 = 256'h0;
+parameter INIT_RAM_22 = 256'h0;
+parameter INIT_RAM_23 = 256'h0;
+parameter INIT_RAM_24 = 256'h0;
+parameter INIT_RAM_25 = 256'h0;
+parameter INIT_RAM_26 = 256'h0;
+parameter INIT_RAM_27 = 256'h0;
+parameter INIT_RAM_28 = 256'h0;
+parameter INIT_RAM_29 = 256'h0;
+parameter INIT_RAM_2A = 256'h0;
+parameter INIT_RAM_2B = 256'h0;
+parameter INIT_RAM_2C = 256'h0;
+parameter INIT_RAM_2D = 256'h0;
+parameter INIT_RAM_2E = 256'h0;
+parameter INIT_RAM_2F = 256'h0;
+parameter INIT_RAM_30 = 256'h0;
+parameter INIT_RAM_31 = 256'h0;
+parameter INIT_RAM_32 = 256'h0;
+parameter INIT_RAM_33 = 256'h0;
+parameter INIT_RAM_34 = 256'h0;
+parameter INIT_RAM_35 = 256'h0;
+parameter INIT_RAM_36 = 256'h0;
+parameter INIT_RAM_37 = 256'h0;
+parameter INIT_RAM_38 = 256'h0;
+parameter INIT_RAM_39 = 256'h0;
+parameter INIT_RAM_3A = 256'h0;
+parameter INIT_RAM_3B = 256'h0;
+parameter INIT_RAM_3C = 256'h0;
+parameter INIT_RAM_3D = 256'h0;
+parameter INIT_RAM_3E = 256'h0;
+parameter INIT_RAM_3F = 256'h0;
+
+output [31:0] DO;
+input [31:0] DI;
+input [2:0] BLKSEL;
+input [13:0] AD;
+input WRE;
+input CLK;
+input CE;
+input OCE;
+input RESET;
+
+endmodule
+
+(* blackbox *)
+module SPX9 (DO, DI, BLKSEL, AD, WRE, CLK, CE, OCE, RESET);
- reg [15:0] mem0, mem1, mem2, mem3;
-
- initial begin
- mem0 = INIT_0;
- mem1 = INIT_1;
- mem2 = INIT_2;
- mem3 = INIT_3;
- end
-
- assign DO[0] = mem0[AD];
- assign DO[1] = mem1[AD];
- assign DO[2] = mem2[AD];
- assign DO[3] = mem3[AD];
-
- always @(posedge CLK) begin
- if (WRE) begin
- mem0[AD] <= DI[0];
- mem1[AD] <= DI[1];
- mem2[AD] <= DI[2];
- mem3[AD] <= DI[3];
- end
- end
-
-endmodule // RAM16S4
+// 1 Enables output pipeline registers.
+parameter READ_MODE = 1'b0;
+// 0: no read on write, 1: transparent, 2: read-before-write
+parameter WRITE_MODE = 2'b00;
+parameter BIT_WIDTH = 36; // 9, 18, 36
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 288'h0;
+parameter INIT_RAM_01 = 288'h0;
+parameter INIT_RAM_02 = 288'h0;
+parameter INIT_RAM_03 = 288'h0;
+parameter INIT_RAM_04 = 288'h0;
+parameter INIT_RAM_05 = 288'h0;
+parameter INIT_RAM_06 = 288'h0;
+parameter INIT_RAM_07 = 288'h0;
+parameter INIT_RAM_08 = 288'h0;
+parameter INIT_RAM_09 = 288'h0;
+parameter INIT_RAM_0A = 288'h0;
+parameter INIT_RAM_0B = 288'h0;
+parameter INIT_RAM_0C = 288'h0;
+parameter INIT_RAM_0D = 288'h0;
+parameter INIT_RAM_0E = 288'h0;
+parameter INIT_RAM_0F = 288'h0;
+parameter INIT_RAM_10 = 288'h0;
+parameter INIT_RAM_11 = 288'h0;
+parameter INIT_RAM_12 = 288'h0;
+parameter INIT_RAM_13 = 288'h0;
+parameter INIT_RAM_14 = 288'h0;
+parameter INIT_RAM_15 = 288'h0;
+parameter INIT_RAM_16 = 288'h0;
+parameter INIT_RAM_17 = 288'h0;
+parameter INIT_RAM_18 = 288'h0;
+parameter INIT_RAM_19 = 288'h0;
+parameter INIT_RAM_1A = 288'h0;
+parameter INIT_RAM_1B = 288'h0;
+parameter INIT_RAM_1C = 288'h0;
+parameter INIT_RAM_1D = 288'h0;
+parameter INIT_RAM_1E = 288'h0;
+parameter INIT_RAM_1F = 288'h0;
+parameter INIT_RAM_20 = 288'h0;
+parameter INIT_RAM_21 = 288'h0;
+parameter INIT_RAM_22 = 288'h0;
+parameter INIT_RAM_23 = 288'h0;
+parameter INIT_RAM_24 = 288'h0;
+parameter INIT_RAM_25 = 288'h0;
+parameter INIT_RAM_26 = 288'h0;
+parameter INIT_RAM_27 = 288'h0;
+parameter INIT_RAM_28 = 288'h0;
+parameter INIT_RAM_29 = 288'h0;
+parameter INIT_RAM_2A = 288'h0;
+parameter INIT_RAM_2B = 288'h0;
+parameter INIT_RAM_2C = 288'h0;
+parameter INIT_RAM_2D = 288'h0;
+parameter INIT_RAM_2E = 288'h0;
+parameter INIT_RAM_2F = 288'h0;
+parameter INIT_RAM_30 = 288'h0;
+parameter INIT_RAM_31 = 288'h0;
+parameter INIT_RAM_32 = 288'h0;
+parameter INIT_RAM_33 = 288'h0;
+parameter INIT_RAM_34 = 288'h0;
+parameter INIT_RAM_35 = 288'h0;
+parameter INIT_RAM_36 = 288'h0;
+parameter INIT_RAM_37 = 288'h0;
+parameter INIT_RAM_38 = 288'h0;
+parameter INIT_RAM_39 = 288'h0;
+parameter INIT_RAM_3A = 288'h0;
+parameter INIT_RAM_3B = 288'h0;
+parameter INIT_RAM_3C = 288'h0;
+parameter INIT_RAM_3D = 288'h0;
+parameter INIT_RAM_3E = 288'h0;
+parameter INIT_RAM_3F = 288'h0;
+
+output [35:0] DO;
+input [35:0] DI;
+input [2:0] BLKSEL;
+input [13:0] AD;
+input WRE;
+input CLK;
+input CE;
+input OCE;
+input RESET;
+
+endmodule
(* blackbox *)
module SDP (DO, DI, BLKSEL, ADA, ADB, WREA, WREB, CLKA, CLKB, CEA, CEB, OCE, RESETA, RESETB);
-//1'b0: Bypass mode; 1'b1 Pipeline mode
+
parameter READ_MODE = 1'b0;
parameter BIT_WIDTH_0 = 32; // 1, 2, 4, 8, 16, 32
parameter BIT_WIDTH_1 = 32; // 1, 2, 4, 8, 16, 32
parameter BLK_SEL = 3'b000;
parameter RESET_MODE = "SYNC";
-parameter INIT_RAM_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-parameter INIT_RAM_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
-
-input CLKA, CEA, CLKB, CEB;
-input OCE; // clock enable of memory output register
-input RESETA, RESETB; // resets output registers, not memory contents
-input WREA, WREB; // 1'b0: read enabled; 1'b1: write enabled
-input [13:0] ADA, ADB;
+parameter INIT_RAM_00 = 256'h0;
+parameter INIT_RAM_01 = 256'h0;
+parameter INIT_RAM_02 = 256'h0;
+parameter INIT_RAM_03 = 256'h0;
+parameter INIT_RAM_04 = 256'h0;
+parameter INIT_RAM_05 = 256'h0;
+parameter INIT_RAM_06 = 256'h0;
+parameter INIT_RAM_07 = 256'h0;
+parameter INIT_RAM_08 = 256'h0;
+parameter INIT_RAM_09 = 256'h0;
+parameter INIT_RAM_0A = 256'h0;
+parameter INIT_RAM_0B = 256'h0;
+parameter INIT_RAM_0C = 256'h0;
+parameter INIT_RAM_0D = 256'h0;
+parameter INIT_RAM_0E = 256'h0;
+parameter INIT_RAM_0F = 256'h0;
+parameter INIT_RAM_10 = 256'h0;
+parameter INIT_RAM_11 = 256'h0;
+parameter INIT_RAM_12 = 256'h0;
+parameter INIT_RAM_13 = 256'h0;
+parameter INIT_RAM_14 = 256'h0;
+parameter INIT_RAM_15 = 256'h0;
+parameter INIT_RAM_16 = 256'h0;
+parameter INIT_RAM_17 = 256'h0;
+parameter INIT_RAM_18 = 256'h0;
+parameter INIT_RAM_19 = 256'h0;
+parameter INIT_RAM_1A = 256'h0;
+parameter INIT_RAM_1B = 256'h0;
+parameter INIT_RAM_1C = 256'h0;
+parameter INIT_RAM_1D = 256'h0;
+parameter INIT_RAM_1E = 256'h0;
+parameter INIT_RAM_1F = 256'h0;
+parameter INIT_RAM_20 = 256'h0;
+parameter INIT_RAM_21 = 256'h0;
+parameter INIT_RAM_22 = 256'h0;
+parameter INIT_RAM_23 = 256'h0;
+parameter INIT_RAM_24 = 256'h0;
+parameter INIT_RAM_25 = 256'h0;
+parameter INIT_RAM_26 = 256'h0;
+parameter INIT_RAM_27 = 256'h0;
+parameter INIT_RAM_28 = 256'h0;
+parameter INIT_RAM_29 = 256'h0;
+parameter INIT_RAM_2A = 256'h0;
+parameter INIT_RAM_2B = 256'h0;
+parameter INIT_RAM_2C = 256'h0;
+parameter INIT_RAM_2D = 256'h0;
+parameter INIT_RAM_2E = 256'h0;
+parameter INIT_RAM_2F = 256'h0;
+parameter INIT_RAM_30 = 256'h0;
+parameter INIT_RAM_31 = 256'h0;
+parameter INIT_RAM_32 = 256'h0;
+parameter INIT_RAM_33 = 256'h0;
+parameter INIT_RAM_34 = 256'h0;
+parameter INIT_RAM_35 = 256'h0;
+parameter INIT_RAM_36 = 256'h0;
+parameter INIT_RAM_37 = 256'h0;
+parameter INIT_RAM_38 = 256'h0;
+parameter INIT_RAM_39 = 256'h0;
+parameter INIT_RAM_3A = 256'h0;
+parameter INIT_RAM_3B = 256'h0;
+parameter INIT_RAM_3C = 256'h0;
+parameter INIT_RAM_3D = 256'h0;
+parameter INIT_RAM_3E = 256'h0;
+parameter INIT_RAM_3F = 256'h0;
+
+output [31:0] DO;
input [31:0] DI;
input [2:0] BLKSEL;
-output [31:0] DO;
+input [13:0] ADA, ADB;
+input WREA, WREB;
+input CLKA, CLKB;
+input CEA, CEB;
+input OCE;
+input RESETA, RESETB;
+
+specify
+ (posedge CLKB => (DO : DI)) = (419, 493);
+ $setup(RESETA, posedge CLKA, 62);
+ $setup(RESETB, posedge CLKB, 62);
+ $setup(OCE, posedge CLKB, 62);
+ $setup(CEA, posedge CLKA, 62);
+ $setup(CEB, posedge CLKB, 62);
+ $setup(OCE, posedge CLKB, 62);
+ $setup(WREA, posedge CLKA, 62);
+ $setup(WREB, posedge CLKB, 62);
+ $setup(DI, posedge CLKA, 62);
+ $setup(ADA, posedge CLKA, 62);
+ $setup(ADB, posedge CLKB, 62);
+ $setup(BLKSEL, posedge CLKA, 62);
+endspecify
+
+endmodule
+
+(* blackbox *)
+module SDPX9 (DO, DI, BLKSEL, ADA, ADB, WREA, WREB, CLKA, CLKB, CEA, CEB, OCE, RESETA, RESETB);
+
+parameter READ_MODE = 1'b0;
+parameter BIT_WIDTH_0 = 36; // 9, 18, 36
+parameter BIT_WIDTH_1 = 36; // 9, 18, 36
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 288'h0;
+parameter INIT_RAM_01 = 288'h0;
+parameter INIT_RAM_02 = 288'h0;
+parameter INIT_RAM_03 = 288'h0;
+parameter INIT_RAM_04 = 288'h0;
+parameter INIT_RAM_05 = 288'h0;
+parameter INIT_RAM_06 = 288'h0;
+parameter INIT_RAM_07 = 288'h0;
+parameter INIT_RAM_08 = 288'h0;
+parameter INIT_RAM_09 = 288'h0;
+parameter INIT_RAM_0A = 288'h0;
+parameter INIT_RAM_0B = 288'h0;
+parameter INIT_RAM_0C = 288'h0;
+parameter INIT_RAM_0D = 288'h0;
+parameter INIT_RAM_0E = 288'h0;
+parameter INIT_RAM_0F = 288'h0;
+parameter INIT_RAM_10 = 288'h0;
+parameter INIT_RAM_11 = 288'h0;
+parameter INIT_RAM_12 = 288'h0;
+parameter INIT_RAM_13 = 288'h0;
+parameter INIT_RAM_14 = 288'h0;
+parameter INIT_RAM_15 = 288'h0;
+parameter INIT_RAM_16 = 288'h0;
+parameter INIT_RAM_17 = 288'h0;
+parameter INIT_RAM_18 = 288'h0;
+parameter INIT_RAM_19 = 288'h0;
+parameter INIT_RAM_1A = 288'h0;
+parameter INIT_RAM_1B = 288'h0;
+parameter INIT_RAM_1C = 288'h0;
+parameter INIT_RAM_1D = 288'h0;
+parameter INIT_RAM_1E = 288'h0;
+parameter INIT_RAM_1F = 288'h0;
+parameter INIT_RAM_20 = 288'h0;
+parameter INIT_RAM_21 = 288'h0;
+parameter INIT_RAM_22 = 288'h0;
+parameter INIT_RAM_23 = 288'h0;
+parameter INIT_RAM_24 = 288'h0;
+parameter INIT_RAM_25 = 288'h0;
+parameter INIT_RAM_26 = 288'h0;
+parameter INIT_RAM_27 = 288'h0;
+parameter INIT_RAM_28 = 288'h0;
+parameter INIT_RAM_29 = 288'h0;
+parameter INIT_RAM_2A = 288'h0;
+parameter INIT_RAM_2B = 288'h0;
+parameter INIT_RAM_2C = 288'h0;
+parameter INIT_RAM_2D = 288'h0;
+parameter INIT_RAM_2E = 288'h0;
+parameter INIT_RAM_2F = 288'h0;
+parameter INIT_RAM_30 = 288'h0;
+parameter INIT_RAM_31 = 288'h0;
+parameter INIT_RAM_32 = 288'h0;
+parameter INIT_RAM_33 = 288'h0;
+parameter INIT_RAM_34 = 288'h0;
+parameter INIT_RAM_35 = 288'h0;
+parameter INIT_RAM_36 = 288'h0;
+parameter INIT_RAM_37 = 288'h0;
+parameter INIT_RAM_38 = 288'h0;
+parameter INIT_RAM_39 = 288'h0;
+parameter INIT_RAM_3A = 288'h0;
+parameter INIT_RAM_3B = 288'h0;
+parameter INIT_RAM_3C = 288'h0;
+parameter INIT_RAM_3D = 288'h0;
+parameter INIT_RAM_3E = 288'h0;
+parameter INIT_RAM_3F = 288'h0;
+
+output [35:0] DO;
+input [35:0] DI;
+input [2:0] BLKSEL;
+input [13:0] ADA, ADB;
+input WREA, WREB;
+input CLKA, CLKB;
+input CEA, CEB;
+input OCE;
+input RESETA, RESETB;
specify
(posedge CLKB => (DO : DI)) = (419, 493);
@@ -821,6 +1328,184 @@ endspecify
endmodule
+
+(* blackbox *)
+module DP (DOA, DOB, DIA, DIB, BLKSEL, ADA, ADB, WREA, WREB, CLKA, CLKB, CEA, CEB, OCEA, OCEB, RESETA, RESETB);
+
+parameter READ_MODE0 = 1'b0;
+parameter READ_MODE1 = 1'b0;
+parameter WRITE_MODE0 = 2'b00;
+parameter WRITE_MODE1 = 2'b00;
+parameter BIT_WIDTH_0 = 16; // 1, 2, 4, 8, 16
+parameter BIT_WIDTH_1 = 16; // 1, 2, 4, 8, 16
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 256'h0;
+parameter INIT_RAM_01 = 256'h0;
+parameter INIT_RAM_02 = 256'h0;
+parameter INIT_RAM_03 = 256'h0;
+parameter INIT_RAM_04 = 256'h0;
+parameter INIT_RAM_05 = 256'h0;
+parameter INIT_RAM_06 = 256'h0;
+parameter INIT_RAM_07 = 256'h0;
+parameter INIT_RAM_08 = 256'h0;
+parameter INIT_RAM_09 = 256'h0;
+parameter INIT_RAM_0A = 256'h0;
+parameter INIT_RAM_0B = 256'h0;
+parameter INIT_RAM_0C = 256'h0;
+parameter INIT_RAM_0D = 256'h0;
+parameter INIT_RAM_0E = 256'h0;
+parameter INIT_RAM_0F = 256'h0;
+parameter INIT_RAM_10 = 256'h0;
+parameter INIT_RAM_11 = 256'h0;
+parameter INIT_RAM_12 = 256'h0;
+parameter INIT_RAM_13 = 256'h0;
+parameter INIT_RAM_14 = 256'h0;
+parameter INIT_RAM_15 = 256'h0;
+parameter INIT_RAM_16 = 256'h0;
+parameter INIT_RAM_17 = 256'h0;
+parameter INIT_RAM_18 = 256'h0;
+parameter INIT_RAM_19 = 256'h0;
+parameter INIT_RAM_1A = 256'h0;
+parameter INIT_RAM_1B = 256'h0;
+parameter INIT_RAM_1C = 256'h0;
+parameter INIT_RAM_1D = 256'h0;
+parameter INIT_RAM_1E = 256'h0;
+parameter INIT_RAM_1F = 256'h0;
+parameter INIT_RAM_20 = 256'h0;
+parameter INIT_RAM_21 = 256'h0;
+parameter INIT_RAM_22 = 256'h0;
+parameter INIT_RAM_23 = 256'h0;
+parameter INIT_RAM_24 = 256'h0;
+parameter INIT_RAM_25 = 256'h0;
+parameter INIT_RAM_26 = 256'h0;
+parameter INIT_RAM_27 = 256'h0;
+parameter INIT_RAM_28 = 256'h0;
+parameter INIT_RAM_29 = 256'h0;
+parameter INIT_RAM_2A = 256'h0;
+parameter INIT_RAM_2B = 256'h0;
+parameter INIT_RAM_2C = 256'h0;
+parameter INIT_RAM_2D = 256'h0;
+parameter INIT_RAM_2E = 256'h0;
+parameter INIT_RAM_2F = 256'h0;
+parameter INIT_RAM_30 = 256'h0;
+parameter INIT_RAM_31 = 256'h0;
+parameter INIT_RAM_32 = 256'h0;
+parameter INIT_RAM_33 = 256'h0;
+parameter INIT_RAM_34 = 256'h0;
+parameter INIT_RAM_35 = 256'h0;
+parameter INIT_RAM_36 = 256'h0;
+parameter INIT_RAM_37 = 256'h0;
+parameter INIT_RAM_38 = 256'h0;
+parameter INIT_RAM_39 = 256'h0;
+parameter INIT_RAM_3A = 256'h0;
+parameter INIT_RAM_3B = 256'h0;
+parameter INIT_RAM_3C = 256'h0;
+parameter INIT_RAM_3D = 256'h0;
+parameter INIT_RAM_3E = 256'h0;
+parameter INIT_RAM_3F = 256'h0;
+
+output [15:0] DOA, DOB;
+input [15:0] DIA, DIB;
+input [2:0] BLKSEL;
+input [13:0] ADA, ADB;
+input WREA, WREB;
+input CLKA, CLKB;
+input CEA, CEB;
+input OCEA, OCEB;
+input RESETA, RESETB;
+
+endmodule
+
+(* blackbox *)
+module DPX9 (DOA, DOB, DIA, DIB, BLKSEL, ADA, ADB, WREA, WREB, CLKA, CLKB, CEA, CEB, OCEA, OCEB, RESETA, RESETB);
+
+parameter READ_MODE0 = 1'b0;
+parameter READ_MODE1 = 1'b0;
+parameter WRITE_MODE0 = 2'b00;
+parameter WRITE_MODE1 = 2'b00;
+parameter BIT_WIDTH_0 = 18; // 9, 18
+parameter BIT_WIDTH_1 = 18; // 9, 18
+parameter BLK_SEL = 3'b000;
+parameter RESET_MODE = "SYNC";
+parameter INIT_RAM_00 = 288'h0;
+parameter INIT_RAM_01 = 288'h0;
+parameter INIT_RAM_02 = 288'h0;
+parameter INIT_RAM_03 = 288'h0;
+parameter INIT_RAM_04 = 288'h0;
+parameter INIT_RAM_05 = 288'h0;
+parameter INIT_RAM_06 = 288'h0;
+parameter INIT_RAM_07 = 288'h0;
+parameter INIT_RAM_08 = 288'h0;
+parameter INIT_RAM_09 = 288'h0;
+parameter INIT_RAM_0A = 288'h0;
+parameter INIT_RAM_0B = 288'h0;
+parameter INIT_RAM_0C = 288'h0;
+parameter INIT_RAM_0D = 288'h0;
+parameter INIT_RAM_0E = 288'h0;
+parameter INIT_RAM_0F = 288'h0;
+parameter INIT_RAM_10 = 288'h0;
+parameter INIT_RAM_11 = 288'h0;
+parameter INIT_RAM_12 = 288'h0;
+parameter INIT_RAM_13 = 288'h0;
+parameter INIT_RAM_14 = 288'h0;
+parameter INIT_RAM_15 = 288'h0;
+parameter INIT_RAM_16 = 288'h0;
+parameter INIT_RAM_17 = 288'h0;
+parameter INIT_RAM_18 = 288'h0;
+parameter INIT_RAM_19 = 288'h0;
+parameter INIT_RAM_1A = 288'h0;
+parameter INIT_RAM_1B = 288'h0;
+parameter INIT_RAM_1C = 288'h0;
+parameter INIT_RAM_1D = 288'h0;
+parameter INIT_RAM_1E = 288'h0;
+parameter INIT_RAM_1F = 288'h0;
+parameter INIT_RAM_20 = 288'h0;
+parameter INIT_RAM_21 = 288'h0;
+parameter INIT_RAM_22 = 288'h0;
+parameter INIT_RAM_23 = 288'h0;
+parameter INIT_RAM_24 = 288'h0;
+parameter INIT_RAM_25 = 288'h0;
+parameter INIT_RAM_26 = 288'h0;
+parameter INIT_RAM_27 = 288'h0;
+parameter INIT_RAM_28 = 288'h0;
+parameter INIT_RAM_29 = 288'h0;
+parameter INIT_RAM_2A = 288'h0;
+parameter INIT_RAM_2B = 288'h0;
+parameter INIT_RAM_2C = 288'h0;
+parameter INIT_RAM_2D = 288'h0;
+parameter INIT_RAM_2E = 288'h0;
+parameter INIT_RAM_2F = 288'h0;
+parameter INIT_RAM_30 = 288'h0;
+parameter INIT_RAM_31 = 288'h0;
+parameter INIT_RAM_32 = 288'h0;
+parameter INIT_RAM_33 = 288'h0;
+parameter INIT_RAM_34 = 288'h0;
+parameter INIT_RAM_35 = 288'h0;
+parameter INIT_RAM_36 = 288'h0;
+parameter INIT_RAM_37 = 288'h0;
+parameter INIT_RAM_38 = 288'h0;
+parameter INIT_RAM_39 = 288'h0;
+parameter INIT_RAM_3A = 288'h0;
+parameter INIT_RAM_3B = 288'h0;
+parameter INIT_RAM_3C = 288'h0;
+parameter INIT_RAM_3D = 288'h0;
+parameter INIT_RAM_3E = 288'h0;
+parameter INIT_RAM_3F = 288'h0;
+
+output [17:0] DOA, DOB;
+input [17:0] DIA, DIB;
+input [2:0] BLKSEL;
+input [13:0] ADA, ADB;
+input WREA, WREB;
+input CLKA, CLKB;
+input CEA, CEB;
+input OCEA, OCEB;
+input RESETA, RESETB;
+
+endmodule
+
+
(* blackbox *)
module rPLL (CLKOUT, CLKOUTP, CLKOUTD, CLKOUTD3, LOCK, CLKIN, CLKFB, FBDSEL, IDSEL, ODSEL, DUTYDA, PSDA, FDLY, RESET, RESET_P);
input CLKIN;
@@ -866,3 +1551,37 @@ parameter CLKOUTD3_SRC = "CLKOUT"; // CLKOUT, CLKOUTP
parameter DEVICE = "GW1N-1"; // "GW1N-1", "GW1N-4", "GW1N-9", "GW1NR-4", "GW1NR-9", "GW1N-4B", "GW1NR-4B", "GW1NS-2", "GW1NS-2C", "GW1NZ-1", "GW1NSR-2", "GW1NSR-2C", "GW1N-1S", "GW1NSE-2C", "GW1NRF-4B", "GW1N-9C", "GW1NR-9C", "GW1N-4C", "GW1NR-4C"
endmodule
+
+(* blackbox *)
+module OSC(OSCOUT);
+output OSCOUT;
+
+parameter FREQ_DIV = 100;
+parameter DEVICE = "GW1N-4";
+endmodule
+
+(* blackbox *)
+module OSCZ(OSCOUT, OSCEN);
+input OSCEN;
+
+output OSCOUT;
+
+parameter FREQ_DIV = 100;
+endmodule
+
+(* blackbox *)
+module OSCF(OSCOUT, OSCOUT30M, OSCEN);
+input OSCEN;
+
+output OSCOUT;
+output OSCOUT30M;
+
+parameter FREQ_DIV = 100;
+endmodule
+
+(* blackbox *)
+module OSCH(OSCOUT);
+output OSCOUT;
+
+parameter FREQ_DIV = 96;
+endmodule
diff --git a/techlibs/gowin/lutrams_map.v b/techlibs/gowin/lutrams_map.v
index a50ab365a..e5daab6ae 100644
--- a/techlibs/gowin/lutrams_map.v
+++ b/techlibs/gowin/lutrams_map.v
@@ -15,13 +15,14 @@ module \$__GW1NR_RAM16S4 (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
`include "brams_init3.vh"
- RAM16S4
+ RAM16SDP4
#(.INIT_0(INIT_0),
.INIT_1(INIT_1),
.INIT_2(INIT_2),
.INIT_3(INIT_3))
_TECHMAP_REPLACE_
- (.AD(B1ADDR),
+ (.WAD(B1ADDR),
+ .RAD(A1ADDR),
.DI(B1DATA),
.DO(A1DATA),
.CLK(CLK1),
diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc
index 614d5802c..b5f279a92 100644
--- a/techlibs/intel_alm/Makefile.inc
+++ b/techlibs/intel_alm/Makefile.inc
@@ -19,6 +19,7 @@ $(eval $(call add_share_file,share/intel_alm/cyclonev,techlibs/intel_alm/cyclone
# RAM
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m10k.txt))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m10k_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m20k.txt))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_m20k_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt))
diff --git a/techlibs/intel_alm/common/bram_m10k.txt b/techlibs/intel_alm/common/bram_m10k.txt
index 0d9a49b7d..560711b65 100644
--- a/techlibs/intel_alm/common/bram_m10k.txt
+++ b/techlibs/intel_alm/common/bram_m10k.txt
@@ -1,4 +1,4 @@
-bram MISTRAL_M10K
+bram $__MISTRAL_M10K
init 0 # TODO: Re-enable when I figure out how BRAM init works
abits 13 @D8192x1
dbits 1 @D8192x1
@@ -21,7 +21,7 @@ bram MISTRAL_M10K
endbram
-match MISTRAL_M10K
+match $__MISTRAL_M10K
min efficiency 5
make_transp
endmatch
diff --git a/techlibs/intel_alm/common/bram_m10k_map.v b/techlibs/intel_alm/common/bram_m10k_map.v
new file mode 100644
index 000000000..8f9d4a3b3
--- /dev/null
+++ b/techlibs/intel_alm/common/bram_m10k_map.v
@@ -0,0 +1,16 @@
+// Stub to invert M10K write-enable.
+
+module \$__MISTRAL_M10K (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 10;
+
+input CLK1;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+input A1EN, B1EN;
+output reg [CFG_DBITS-1:0] B1DATA;
+
+MISTRAL_M10K #(.CFG_ABITS(CFG_ABITS), .CFG_DBITS(CFG_DBITS)) _TECHMAP_REPLACE_ (.CLK1(CLK1), .A1ADDR(A1ADDR), .A1DATA(A1DATA), .A1EN(!A1EN), .B1ADDR(B1ADDR), .B1DATA(B1DATA), .B1EN(B1EN));
+
+endmodule \ No newline at end of file
diff --git a/techlibs/intel_alm/common/mem_sim.v b/techlibs/intel_alm/common/mem_sim.v
index 370e17f27..c9ba8c7f1 100644
--- a/techlibs/intel_alm/common/mem_sim.v
+++ b/techlibs/intel_alm/common/mem_sim.v
@@ -145,7 +145,7 @@ endspecify
`endif
always @(posedge CLK1) begin
- if (A1EN)
+ if (!A1EN)
mem[(A1ADDR + 1) * CFG_DBITS - 1 : A1ADDR * CFG_DBITS] <= A1DATA;
if (B1EN)
diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v
index 5850f6907..217dc5de9 100644
--- a/techlibs/intel_alm/common/quartus_rename.v
+++ b/techlibs/intel_alm/common/quartus_rename.v
@@ -157,6 +157,11 @@ output [CFG_DBITS-1:0] B1DATA;
// Much like the MLAB, the M10K has mem_init[01234] parameters which would let
// you initialise the RAM cell via hex literals. If they were implemented.
+// Since the MISTRAL_M10K block has an inverted write-enable (like the real hardware)
+// but the Quartus primitive expects a normal write-enable, we add an inverter.
+wire A1EN_N;
+NOT wren_inv (.IN(A1EN), .OUT(A1EN_N));
+
`RAM_BLOCK #(
.operation_mode("dual_port"),
.logical_ram_name(_TECHMAP_CELLNAME_),
@@ -176,10 +181,10 @@ output [CFG_DBITS-1:0] B1DATA;
.port_b_first_bit_number(0),
.port_b_address_clock("clock0"),
.port_b_read_enable_clock("clock0")
-) _TECHMAP_REPLACE_ (
+) ram_block (
.portaaddr(A1ADDR),
.portadatain(A1DATA),
- .portawe(A1EN),
+ .portawe(A1EN_N),
.portbaddr(B1ADDR),
.portbdataout(B1DATA),
.portbre(B1EN),
diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc
index 34a5ffa5d..43d3592d5 100644
--- a/techlibs/intel_alm/synth_intel_alm.cc
+++ b/techlibs/intel_alm/synth_intel_alm.cc
@@ -262,8 +262,7 @@ struct SynthIntelALMPass : public ScriptPass {
if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str()));
- if (help_mode || bram_type != "m10k")
- run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
+ run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str()));
}
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) {
diff --git a/techlibs/nexus/arith_map.v b/techlibs/nexus/arith_map.v
index 9a1fedfc8..81ab7ba54 100644
--- a/techlibs/nexus/arith_map.v
+++ b/techlibs/nexus/arith_map.v
@@ -90,7 +90,7 @@ module _80_nexus_alu (A, B, CI, BI, X, Y, CO);
assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i]));
if (i+1 < Y_WIDTH) begin
- assign CO[i + 1] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i]));
+ assign CO[i + 1] = (AA[i + 1] && BB[i + 1]) || ((Y[i + 1] ^ AA[i + 1] ^ BB[i + 1]) && (AA[i + 1] || BB[i + 1]));
assign Y[i+1] = Y1[i];
end
end endgenerate
diff --git a/techlibs/nexus/cells_sim.v b/techlibs/nexus/cells_sim.v
index 1e876a210..d1c8bf0d7 100644
--- a/techlibs/nexus/cells_sim.v
+++ b/techlibs/nexus/cells_sim.v
@@ -54,8 +54,8 @@ endmodule
// Bidirectional IO buffer
module BB(input T, I, output O,
(* iopad_external_pin *) inout B);
- assign B = T ? 1'bz : O;
- assign I = B;
+ assign B = T ? 1'bz : I;
+ assign O = B;
endmodule
// Input buffer
diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc
index a67b167b8..754de2de6 100644
--- a/techlibs/quicklogic/synth_quicklogic.cc
+++ b/techlibs/quicklogic/synth_quicklogic.cc
@@ -225,8 +225,8 @@ struct SynthQuickLogicPass : public ScriptPass {
}
if (check_label("verilog")) {
- if (!verilog_file.empty()) {
- run("write_verilog -noattr -nohex " + verilog_file);
+ if (!verilog_file.empty() || help_mode) {
+ run(stringf("write_verilog -noattr -nohex %s", help_mode ? "<file-name>" : verilog_file.c_str()));
}
}
}
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index cb23b9787..2630c7a0f 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -108,7 +108,26 @@ CELLS = [
# Block RAM.
# Virtex.
- # TODO: RAMB4_*
+ Cell('RAMB4_S1', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('RAMB4_S2', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('RAMB4_S4', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('RAMB4_S8', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('RAMB4_S16', port_attrs={'CLK': ['clkbuf_sink']}),
+ Cell('RAMB4_S1_S1', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S1_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S1_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S1_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S1_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S2_S2', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S2_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S2_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S2_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S4_S4', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S4_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S4_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S8_S8', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S8_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
+ Cell('RAMB4_S16_S16', port_attrs={'CLKA': ['clkbuf_sink'], 'CLKB': ['clkbuf_sink']}),
# Virtex 2, Spartan 3.
Cell('RAMB16_S1', port_attrs={'CLK': ['clkbuf_sink']}),
Cell('RAMB16_S2', port_attrs={'CLK': ['clkbuf_sink']}),
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index 1187101fd..aae0d3ee5 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -1,5 +1,680 @@
// Created by cells_xtra.py from Xilinx models
+module RAMB4_S1 (...);
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [0:0] DO;
+ input [11:0] ADDR;
+ input [0:0] DI;
+ input EN;
+ (* clkbuf_sink *)
+ input CLK;
+ input WE;
+ input RST;
+endmodule
+
+module RAMB4_S2 (...);
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [1:0] DO;
+ input [10:0] ADDR;
+ input [1:0] DI;
+ input EN;
+ (* clkbuf_sink *)
+ input CLK;
+ input WE;
+ input RST;
+endmodule
+
+module RAMB4_S4 (...);
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [3:0] DO;
+ input [9:0] ADDR;
+ input [3:0] DI;
+ input EN;
+ (* clkbuf_sink *)
+ input CLK;
+ input WE;
+ input RST;
+endmodule
+
+module RAMB4_S8 (...);
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [7:0] DO;
+ input [8:0] ADDR;
+ input [7:0] DI;
+ input EN;
+ (* clkbuf_sink *)
+ input CLK;
+ input WE;
+ input RST;
+endmodule
+
+module RAMB4_S16 (...);
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [15:0] DO;
+ input [7:0] ADDR;
+ input [15:0] DI;
+ input EN;
+ (* clkbuf_sink *)
+ input CLK;
+ input WE;
+ input RST;
+endmodule
+
+module RAMB4_S1_S1 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [0:0] DOA;
+ input [11:0] ADDRA;
+ input [0:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [0:0] DOB;
+ input [11:0] ADDRB;
+ input [0:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S1_S2 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [0:0] DOA;
+ input [11:0] ADDRA;
+ input [0:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [1:0] DOB;
+ input [10:0] ADDRB;
+ input [1:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S1_S4 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [0:0] DOA;
+ input [11:0] ADDRA;
+ input [0:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [3:0] DOB;
+ input [9:0] ADDRB;
+ input [3:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S1_S8 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [0:0] DOA;
+ input [11:0] ADDRA;
+ input [0:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [7:0] DOB;
+ input [8:0] ADDRB;
+ input [7:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S1_S16 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [0:0] DOA;
+ input [11:0] ADDRA;
+ input [0:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [15:0] DOB;
+ input [7:0] ADDRB;
+ input [15:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S2_S2 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [1:0] DOA;
+ input [10:0] ADDRA;
+ input [1:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [1:0] DOB;
+ input [10:0] ADDRB;
+ input [1:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S2_S4 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [1:0] DOA;
+ input [10:0] ADDRA;
+ input [1:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [3:0] DOB;
+ input [9:0] ADDRB;
+ input [3:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S2_S8 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [1:0] DOA;
+ input [10:0] ADDRA;
+ input [1:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [7:0] DOB;
+ input [8:0] ADDRB;
+ input [7:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S2_S16 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [1:0] DOA;
+ input [10:0] ADDRA;
+ input [1:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [15:0] DOB;
+ input [7:0] ADDRB;
+ input [15:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S4_S4 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [3:0] DOA;
+ input [9:0] ADDRA;
+ input [3:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [3:0] DOB;
+ input [9:0] ADDRB;
+ input [3:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S4_S8 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [3:0] DOA;
+ input [9:0] ADDRA;
+ input [3:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [7:0] DOB;
+ input [8:0] ADDRB;
+ input [7:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S4_S16 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [3:0] DOA;
+ input [9:0] ADDRA;
+ input [3:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [15:0] DOB;
+ input [7:0] ADDRB;
+ input [15:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S8_S8 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [7:0] DOA;
+ input [8:0] ADDRA;
+ input [7:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [7:0] DOB;
+ input [8:0] ADDRB;
+ input [7:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S8_S16 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [7:0] DOA;
+ input [8:0] ADDRA;
+ input [7:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [15:0] DOB;
+ input [7:0] ADDRB;
+ input [15:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
+module RAMB4_S16_S16 (...);
+ parameter SIM_COLLISION_CHECK = "ALL";
+ parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000;
+ output [15:0] DOA;
+ input [7:0] ADDRA;
+ input [15:0] DIA;
+ input ENA;
+ (* clkbuf_sink *)
+ input CLKA;
+ input WEA;
+ input RSTA;
+ output [15:0] DOB;
+ input [7:0] ADDRB;
+ input [15:0] DIB;
+ input ENB;
+ (* clkbuf_sink *)
+ input CLKB;
+ input WEB;
+ input RSTB;
+endmodule
+
module RAMB16_S1 (...);
parameter [0:0] INIT = 1'h0;
parameter [0:0] SRVAL = 1'h0;
diff --git a/tests/arch/anlogic/blockram.ys b/tests/arch/anlogic/blockram.ys
new file mode 100644
index 000000000..da23409ba
--- /dev/null
+++ b/tests/arch/anlogic/blockram.ys
@@ -0,0 +1,13 @@
+read_verilog ../common/blockram.v
+hierarchy -top sync_ram_sp
+proc
+memory -nomap
+equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic
+memory
+opt -full
+
+design -load postopt
+cd sync_ram_sp
+
+select -assert-count 1 t:EG_PHY_BRAM
+select -assert-none t:EG_PHY_BRAM %% t:* %D
diff --git a/tests/arch/anlogic/lutram.ys b/tests/arch/anlogic/lutram.ys
index 6dbdbdac3..fe6135c73 100644
--- a/tests/arch/anlogic/lutram.ys
+++ b/tests/arch/anlogic/lutram.ys
@@ -2,7 +2,7 @@ read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r
proc
memory -nomap
-equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic
+equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic -nobram
memory
opt -full
diff --git a/tests/arch/gowin/lutram.ys b/tests/arch/gowin/lutram.ys
index 56f69e7c5..d668783a2 100644
--- a/tests/arch/gowin/lutram.ys
+++ b/tests/arch/gowin/lutram.ys
@@ -7,12 +7,11 @@ memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
-#ERROR: Called with -verify and proof did fail!
-#sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
+sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
sat -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
-select -assert-count 8 t:RAM16S4
+select -assert-count 8 t:RAM16SDP4
# other logic present that is not simple
#select -assert-none t:RAM16S4 %% t:* %D
diff --git a/tests/arch/intel_alm/blockram.ys b/tests/arch/intel_alm/blockram.ys
index c157c3165..3b61b9339 100644
--- a/tests/arch/intel_alm/blockram.ys
+++ b/tests/arch/intel_alm/blockram.ys
@@ -2,5 +2,6 @@ read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp
synth_intel_alm -family cyclonev -noiopad -noclkbuf
cd sync_ram_sdp
+select -assert-count 1 t:MISTRAL_NOT
select -assert-count 1 t:MISTRAL_M10K
-select -assert-none t:MISTRAL_M10K %% t:* %D
+select -assert-none t:MISTRAL_NOT t:MISTRAL_M10K %% t:* %D
diff --git a/tests/opt/opt_reduce_bmux.ys b/tests/opt/opt_reduce_bmux.ys
new file mode 100644
index 000000000..55e0b6d4b
--- /dev/null
+++ b/tests/opt/opt_reduce_bmux.ys
@@ -0,0 +1,117 @@
+read_ilang << EOT
+
+module \top
+ wire width 12 input 0 \A
+ wire width 2 input 1 \S
+ wire width 6 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A { \A [11:10] \A [3:2] \A [10:9] \A [7] \A [7] \A [8] \A [2] \A [7:6] \A [5] \A [5] \A [3:2] \A [5:4] \A [1] \A [1] \A [3:0] }
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$bmux r:WIDTH=4 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 6 input 0 \A
+ wire width 2 input 1 \S
+ wire width 6 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A { \A [5:0] \A [5:0] \A [5:0] \A [5:0] }
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$bmux
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 160 input 0 \A
+ wire width 2 input 1 \S
+ wire width 5 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 5
+ connect \A \A
+ connect \S { \S [1] 1'1 \S [0] \S [1] 1'0 }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$bmux r:S_WIDTH=2 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 10 input 0 \A
+ wire input 1 \S
+ wire width 5 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 1
+ connect \A \A
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$bmux
+select -assert-count 1 t:$mux
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 5 input 0 \A
+ wire width 5 output 1 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 0
+ connect \A \A
+ connect \S { }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$bmux
diff --git a/tests/opt/opt_reduce_demux.ys b/tests/opt/opt_reduce_demux.ys
new file mode 100644
index 000000000..3c5bd7d43
--- /dev/null
+++ b/tests/opt/opt_reduce_demux.ys
@@ -0,0 +1,91 @@
+read_ilang << EOT
+
+module \top
+ wire width 4 input 0 \A
+ wire width 2 input 1 \S
+ wire width 24 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A { \A [3] \A [1] 1'0 \A [2:0] }
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$demux r:WIDTH=4 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 2 input 1 \S
+ wire width 24 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A 6'000000
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$demux
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 5 input 0 \A
+ wire width 2 input 1 \S
+ wire width 160 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 5
+ connect \A \A
+ connect \S { \S [0] \S [1] 1'1 \S [0] 1'0 }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$demux r:S_WIDTH=2 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 5 input 0 \A
+ wire width 20 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 2
+ connect \A \A
+ connect \S { 2'10 }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$demux
diff --git a/tests/sat/.gitignore b/tests/sat/.gitignore
index 8355de9dc..664425d73 100644
--- a/tests/sat/.gitignore
+++ b/tests/sat/.gitignore
@@ -1,2 +1,4 @@
*.log
run-test.mk
+*.vcd
+*.fst
diff --git a/tests/sat/alu.v b/tests/sat/alu.v
new file mode 100644
index 000000000..9826fe05d
--- /dev/null
+++ b/tests/sat/alu.v
@@ -0,0 +1,79 @@
+module alu(
+ input clk,
+ input [7:0] A,
+ input [7:0] B,
+ input [3:0] operation,
+ output reg [7:0] result,
+ output reg CF,
+ output reg ZF,
+ output reg SF
+);
+
+ localparam ALU_OP_ADD /* verilator public_flat */ = 4'b0000;
+ localparam ALU_OP_SUB /* verilator public_flat */ = 4'b0001;
+ localparam ALU_OP_ADC /* verilator public_flat */ = 4'b0010;
+ localparam ALU_OP_SBC /* verilator public_flat */ = 4'b0011;
+
+ localparam ALU_OP_AND /* verilator public_flat */ = 4'b0100;
+ localparam ALU_OP_OR /* verilator public_flat */ = 4'b0101;
+ localparam ALU_OP_NOT /* verilator public_flat */ = 4'b0110;
+ localparam ALU_OP_XOR /* verilator public_flat */ = 4'b0111;
+
+ localparam ALU_OP_SHL /* verilator public_flat */ = 4'b1000;
+ localparam ALU_OP_SHR /* verilator public_flat */ = 4'b1001;
+ localparam ALU_OP_SAL /* verilator public_flat */ = 4'b1010;
+ localparam ALU_OP_SAR /* verilator public_flat */ = 4'b1011;
+
+ localparam ALU_OP_ROL /* verilator public_flat */ = 4'b1100;
+ localparam ALU_OP_ROR /* verilator public_flat */ = 4'b1101;
+ localparam ALU_OP_RCL /* verilator public_flat */ = 4'b1110;
+ localparam ALU_OP_RCR /* verilator public_flat */ = 4'b1111;
+
+ reg [8:0] tmp;
+
+ always @(posedge clk)
+ begin
+ case (operation)
+ ALU_OP_ADD :
+ tmp = A + B;
+ ALU_OP_SUB :
+ tmp = A - B;
+ ALU_OP_ADC :
+ tmp = A + B + { 7'b0000000, CF };
+ ALU_OP_SBC :
+ tmp = A - B - { 7'b0000000, CF };
+ ALU_OP_AND :
+ tmp = {1'b0, A & B };
+ ALU_OP_OR :
+ tmp = {1'b0, A | B };
+ ALU_OP_NOT :
+ tmp = {1'b0, ~B };
+ ALU_OP_XOR :
+ tmp = {1'b0, A ^ B};
+ ALU_OP_SHL :
+ tmp = { A[7], A[6:0], 1'b0};
+ ALU_OP_SHR :
+ tmp = { A[0], 1'b0, A[7:1]};
+ ALU_OP_SAL :
+ // Same as SHL
+ tmp = { A[7], A[6:0], 1'b0};
+ ALU_OP_SAR :
+ tmp = { A[0], A[7], A[7:1]};
+ ALU_OP_ROL :
+ tmp = { A[7], A[6:0], A[7]};
+ ALU_OP_ROR :
+ tmp = { A[0], A[0], A[7:1]};
+ ALU_OP_RCL :
+ tmp = { A[7], A[6:0], CF};
+ ALU_OP_RCR :
+ tmp = { A[0], CF, A[7:1]};
+ endcase
+
+ CF <= tmp[8];
+ ZF <= tmp[7:0] == 0;
+ SF <= tmp[7];
+
+ result <= tmp[7:0];
+ end
+endmodule
+
diff --git a/tests/sat/grom.ys b/tests/sat/grom.ys
new file mode 100644
index 000000000..da0f3b620
--- /dev/null
+++ b/tests/sat/grom.ys
@@ -0,0 +1,9 @@
+read_verilog grom_computer.v grom_cpu.v alu.v ram_memory.v;
+prep -top grom_computer;
+sim -clock clk -reset reset -fst grom.fst -vcd grom.vcd -n 80
+
+sim -clock clk -r grom.fst -scope grom_computer -start 25ns -stop 100ns -sim-cmp
+
+sim -clock clk -r grom.fst -scope grom_computer -stop 100ns -sim-gold
+
+sim -clock clk -r grom.fst -scope grom_computer -n 10 -sim-gate
diff --git a/tests/sat/grom_computer.v b/tests/sat/grom_computer.v
new file mode 100644
index 000000000..63a5c8ff8
--- /dev/null
+++ b/tests/sat/grom_computer.v
@@ -0,0 +1,31 @@
+module grom_computer
+ (input clk, // Main Clock
+ input reset, // reset
+ output hlt,
+ output reg[7:0] display_out
+ );
+
+ wire [11:0] addr;
+ wire [7:0] memory_out;
+ wire [7:0] memory_in;
+ wire mem_enable;
+ wire we;
+ wire ioreq;
+
+ grom_cpu cpu(.clk(clk),.reset(reset),.addr(addr),.data_in(memory_out),.data_out(memory_in),.we(we),.ioreq(ioreq),.hlt(hlt));
+
+ assign mem_enable = we & ~ioreq;
+
+ ram_memory memory(.clk(clk),.addr(addr),.data_in(memory_in),.we(mem_enable),.data_out(memory_out));
+
+ always @(posedge clk)
+ begin
+ if(ioreq==1 && we==1)
+ begin
+ display_out <= memory_in;
+ `ifdef DISASSEMBLY
+ $display("Display output : %h", memory_in);
+ `endif
+ end
+ end
+endmodule
diff --git a/tests/sat/grom_cpu.v b/tests/sat/grom_cpu.v
new file mode 100644
index 000000000..914c0f56c
--- /dev/null
+++ b/tests/sat/grom_cpu.v
@@ -0,0 +1,747 @@
+module grom_cpu(
+ input clk,
+ input reset,
+ output reg [11:0] addr,
+ input [7:0] data_in,
+ output reg [7:0] data_out,
+ output reg we,
+ output reg ioreq,
+ output reg hlt
+);
+
+ reg[11:0] PC /* verilator public_flat */; // Program counter
+ reg[7:0] IR /* verilator public_flat */; // Instruction register
+ reg[7:0] VALUE /* verilator public_flat */; // Temp reg for storing 2nd operand
+ reg[3:0] CS /* verilator public_flat */; // Code segment regiser
+ reg[3:0] DS /* verilator public_flat */; // Data segment regiser
+ reg[11:0] SP /* verilator public_flat */; // Stack pointer regiser
+ reg[7:0] R[0:3] /* verilator public_flat */; // General purpose registers
+ reg[11:0] FUTURE_PC /* verilator public_flat */; // PC to jump to
+
+ localparam STATE_RESET /*verilator public_flat*/ = 5'b00000;
+ localparam STATE_FETCH_PREP /*verilator public_flat*/ = 5'b00001;
+ localparam STATE_FETCH_WAIT /*verilator public_flat*/ = 5'b00010;
+ localparam STATE_FETCH /*verilator public_flat*/ = 5'b00011;
+ localparam STATE_EXECUTE /*verilator public_flat*/ = 5'b00100;
+ localparam STATE_FETCH_VALUE_PREP /*verilator public_flat*/ = 5'b00101;
+ localparam STATE_FETCH_VALUE /*verilator public_flat*/ = 5'b00110;
+ localparam STATE_EXECUTE_DBL /*verilator public_flat*/ = 5'b00111;
+ localparam STATE_LOAD_VALUE /*verilator public_flat*/ = 5'b01000;
+ localparam STATE_LOAD_VALUE_WAIT /*verilator public_flat*/ = 5'b01001;
+ localparam STATE_ALU_RESULT_WAIT /*verilator public_flat*/ = 5'b01010;
+ localparam STATE_ALU_RESULT /*verilator public_flat*/ = 5'b01011;
+ localparam STATE_PUSH_PC_LOW /*verilator public_flat*/ = 5'b01100;
+ localparam STATE_JUMP /*verilator public_flat*/ = 5'b01101;
+ localparam STATE_RET_VALUE_WAIT /*verilator public_flat*/ = 5'b01110;
+ localparam STATE_RET_VALUE /*verilator public_flat*/ = 5'b01111;
+ localparam STATE_RET_VALUE_WAIT2 /*verilator public_flat*/ = 5'b10000;
+ localparam STATE_RET_VALUE2 /*verilator public_flat*/ = 5'b10001;
+
+ reg [4:0] state /* verilator public_flat */ = STATE_RESET;
+
+ reg [7:0] alu_a /* verilator public_flat */;
+ reg [7:0] alu_b /* verilator public_flat */;
+ reg [3:0] alu_op /* verilator public_flat */;
+
+ reg [1:0] RESULT_REG /* verilator public_flat */;
+
+ wire [7:0] alu_res /* verilator public_flat */;
+ wire alu_CF /* verilator public_flat */;
+ wire alu_ZF /* verilator public_flat */;
+ wire alu_SF /* verilator public_flat */;
+ reg jump;
+
+ alu alu(.clk(clk),.A(alu_a),.B(alu_b),.operation(alu_op),.result(alu_res),.CF(alu_CF),.ZF(alu_ZF),.SF(alu_SF));
+
+ always @(posedge clk)
+ begin
+ if (reset)
+ begin
+ state <= STATE_RESET;
+ hlt <= 0;
+ end
+ else
+ begin
+ case (state)
+ STATE_RESET :
+ begin
+ PC <= 12'h000;
+ state <= STATE_FETCH_PREP;
+ CS <= 4'h0;
+ DS <= 4'h0;
+ R[0] <= 8'h00;
+ R[1] <= 8'h00;
+ R[2] <= 8'h00;
+ R[3] <= 8'h00;
+ SP <= 12'hfff;
+ end
+
+ STATE_FETCH_PREP :
+ begin
+ addr <= PC;
+ we <= 0;
+ ioreq <= 0;
+
+ state <= STATE_FETCH_WAIT;
+ end
+
+ STATE_FETCH_WAIT :
+ begin
+ // Sync with memory due to CLK
+ state <= (hlt) ? STATE_FETCH_PREP : STATE_FETCH;
+ end
+
+ STATE_FETCH :
+ begin
+ IR <= data_in;
+ PC <= PC + 1;
+
+ state <= STATE_EXECUTE;
+ end
+ STATE_EXECUTE :
+ begin
+ `ifdef DISASSEMBLY
+ $display(" PC %h R0 %h R1 %h R2 %h R3 %h CS %h DS %h SP %h ALU [%d %d %d]", PC, R[0], R[1], R[2], R[3], CS, DS, SP, alu_CF,alu_SF,alu_ZF);
+ `endif
+ if (IR[7])
+ begin
+ addr <= PC;
+ state <= STATE_FETCH_VALUE_PREP;
+ PC <= PC + 1;
+ end
+ else
+ begin
+ case(IR[6:4])
+ 3'b000 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("MOV R%d,R%d",IR[3:2],IR[1:0]);
+ `endif
+ R[IR[3:2]] <= R[IR[1:0]];
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b001 :
+ begin
+ alu_a <= R[0]; // first input R0
+ alu_b <= R[IR[1:0]];
+ RESULT_REG <= 0; // result in R0
+ alu_op <= { 2'b00, IR[3:2] };
+
+ state <= STATE_ALU_RESULT_WAIT;
+
+ `ifdef DISASSEMBLY
+ case(IR[3:2])
+ 2'b00 : begin
+ $display("ADD R%d",IR[1:0]);
+ end
+ 2'b01 : begin
+ $display("SUB R%d",IR[1:0]);
+ end
+ 2'b10 : begin
+ $display("ADC R%d",IR[1:0]);
+ end
+ 2'b11 : begin
+ $display("SBC R%d",IR[1:0]);
+ end
+ endcase
+ `endif
+ end
+ 3'b010 :
+ begin
+ alu_a <= R[0]; // first input R0
+ alu_b <= R[IR[1:0]];
+ RESULT_REG <= 0; // result in R0
+ alu_op <= { 2'b01, IR[3:2] };
+ state <= STATE_ALU_RESULT_WAIT;
+ `ifdef DISASSEMBLY
+ case(IR[3:2])
+ 2'b00 : begin
+ $display("AND R%d",IR[1:0]);
+ end
+ 2'b01 : begin
+ $display("OR R%d",IR[1:0]);
+ end
+ 2'b10 : begin
+ $display("NOT R%d",IR[1:0]);
+ end
+ 2'b11 : begin
+ $display("XOR R%d",IR[1:0]);
+ end
+ endcase
+ `endif
+ end
+ 3'b011 :
+ begin
+ RESULT_REG <= IR[1:0]; // result in REG
+ // CMP and TEST are not storing result
+ state <= IR[3] ? STATE_FETCH_PREP : STATE_ALU_RESULT_WAIT;
+ // CMP and TEST are having first input R0, for INC and DEC is REG
+ alu_a <= IR[3] ? R[0] : R[IR[1:0]];
+ // CMP and TEST are having second input REG, for INC and DEC is 1
+ alu_b <= IR[3] ? R[IR[1:0]] : 8'b00000001;
+
+ case(IR[3:2])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("INC R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0000; // ALU_OP_ADD
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("DEC R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0001; // ALU_OP_SUB
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("CMP R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0001; // ALU_OP_SUB
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("TST R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0100; // ALU_OP_AND
+ end
+ endcase
+ end
+ 3'b100 :
+ begin
+ if (IR[3]==0)
+ begin
+ alu_a <= R[0]; // first input R0
+ // no 2nd input
+ RESULT_REG <= 0; // result in R0
+ alu_op <= { 1'b1, IR[2:0] };
+ `ifdef DISASSEMBLY
+ case(IR[2:0])
+ 3'b000 : begin
+ $display("SHL");
+ end
+ 3'b001 : begin
+ $display("SHR");
+ end
+ 3'b010 : begin
+ $display("SAL");
+ end
+ 3'b011 : begin
+ $display("SAR");
+ end
+ 3'b100 : begin
+ $display("ROL");
+ end
+ 3'b101 : begin
+ $display("ROR");
+ end
+ 3'b110 : begin
+ $display("RCL");
+ end
+ 3'b111 : begin
+ $display("RCR");
+ end
+ endcase
+ `endif
+ state <= STATE_ALU_RESULT_WAIT;
+ end
+ else
+ begin
+ if (IR[2]==0)
+ begin
+ `ifdef DISASSEMBLY
+ $display("PUSH R%d",IR[1:0]);
+ `endif
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= R[IR[1:0]];
+ SP <= SP - 1;
+ state <= STATE_FETCH_PREP;
+ end
+ else
+ begin
+ `ifdef DISASSEMBLY
+ $display("POP R%d",IR[1:0]);
+ `endif
+ addr <= SP + 1;
+ we <= 0;
+ ioreq <= 0;
+ RESULT_REG <= IR[1:0];
+ SP <= SP + 1;
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ end
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("LOAD R%d,[R%d]", IR[3:2], IR[1:0]);
+ `endif
+ addr <= { DS, R[IR[1:0]] };
+ we <= 0;
+ ioreq <= 0;
+ RESULT_REG <= IR[3:2];
+
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ 3'b110 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("STORE [R%d],R%d", IR[3:2], IR[1:0]);
+ `endif
+ addr <= { DS, R[IR[3:2]] };
+ we <= 1;
+ ioreq <= 0;
+ data_out <= R[IR[1:0]];
+
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b111 :
+ begin
+ // Special instuctions
+ case(IR[3:2])
+ 2'b00 : begin
+ CS <= R[IR[1:0]][3:0];
+ state <= STATE_FETCH_PREP;
+ `ifdef DISASSEMBLY
+ $display("MOV CS,R%d",IR[1:0]);
+ `endif
+ end
+ 2'b01 : begin
+ DS <= R[IR[1:0]][3:0];
+ state <= STATE_FETCH_PREP;
+ `ifdef DISASSEMBLY
+ $display("MOV DS,R%d",IR[1:0]);
+ `endif
+ end
+ 2'b10 : begin
+ case(IR[1:0])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("PUSH CS");
+ `endif
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= { 4'b0000, CS};
+ SP <= SP - 1;
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("PUSH DS");
+ `endif
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= { 4'b0000, DS};
+ SP <= SP - 1;
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ end
+ endcase
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b11 : begin
+ case(IR[1:0])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("RET");
+ `endif
+ addr <= SP + 1;
+ we <= 0;
+ ioreq <= 0;
+ SP <= SP + 1;
+ state <= STATE_RET_VALUE_WAIT;
+ end
+ 2'b11 : begin
+ hlt <= 1;
+ `ifdef DISASSEMBLY
+ $display("HALT");
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ endcase
+ end
+ endcase
+ end
+ end
+ STATE_FETCH_VALUE_PREP :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_FETCH_VALUE;
+ end
+ STATE_FETCH_VALUE :
+ begin
+ VALUE <= data_in;
+ state <= STATE_EXECUTE_DBL;
+ end
+ STATE_EXECUTE_DBL :
+ begin
+ case(IR[6:4])
+ 3'b000 :
+ begin
+ if (IR[3]==0)
+ begin
+ case(IR[2:0])
+ 3'b000 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JMP %h ",{ CS, VALUE[7:0] });
+ `endif
+ jump = 1;
+ end
+ 3'b001 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==1);
+ end
+ 3'b010 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JNC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==0);
+ end
+ 3'b011 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JM %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==1);
+ end
+ 3'b100 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JP %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==0);
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==1);
+ end
+ 3'b110 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JNZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==0);
+ end
+ 3'b111 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ jump = 0;
+ end
+ endcase
+
+ if (jump)
+ begin
+ PC <= { CS, VALUE[7:0] };
+ addr <= { CS, VALUE[7:0] };
+ we <= 0;
+ ioreq <= 0;
+ end
+ state <= STATE_FETCH_PREP;
+ end
+ else
+ begin
+ case(IR[2:0])
+ 3'b000 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JR %h ", PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]} );
+ `endif
+ jump = 1;
+ end
+ 3'b001 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==1);
+ end
+ 3'b010 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRNC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==0);
+ end
+ 3'b011 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRM %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==1);
+ end
+ 3'b100 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRP %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==0);
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==1);
+ end
+ 3'b110 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRNZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==0);
+ end
+ 3'b111 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ jump = 0;
+ end
+ endcase
+ if (jump)
+ begin
+ PC <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
+ addr <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
+ we <= 0;
+ ioreq <= 0;
+ end
+ state <= STATE_FETCH_PREP;
+ end
+ end
+ 3'b001 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JUMP %h ",{ IR[3:0], VALUE[7:0] });
+ `endif
+ PC <= { IR[3:0], VALUE[7:0] };
+ addr <= { IR[3:0], VALUE[7:0] };
+ we <= 0;
+ ioreq <= 0;
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b010 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("CALL %h ",{ IR[3:0], VALUE[7:0] });
+ `endif
+ FUTURE_PC <= { IR[3:0], VALUE[7:0] };
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= { 4'b0000, PC[11:8]};
+ SP <= SP - 1;
+ state <= STATE_PUSH_PC_LOW;
+ end
+ 3'b011 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("MOV SP,%h ",{ IR[3:0], VALUE[7:0] });
+ `endif
+ SP <= { IR[3:0], VALUE[7:0] };
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b100 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("IN R%d,[0x%h]",IR[1:0], VALUE);
+ `endif
+ ioreq <= 1;
+ we <= 0;
+ addr <= { 4'b0000, VALUE };
+ RESULT_REG <= IR[1:0];
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("OUT [0x%h],R%d",VALUE,IR[1:0]);
+ `endif
+ ioreq <= 1;
+ we <= 1;
+ addr <= { 4'b0000, VALUE };
+ data_out <= R[IR[1:0]];
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b110 :
+ begin
+ // Special instuctions
+ case(IR[1:0])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("MOV CS,0x%h",VALUE);
+ `endif
+ CS <= VALUE[3:0];
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("MOV DS,0x%h",VALUE);
+ `endif
+ DS <= VALUE[3:0];
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ 3'b111 :
+ begin
+ case(IR[3:2])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("MOV R%d,0x%h",IR[1:0],VALUE);
+ `endif
+ R[IR[1:0]] <= VALUE;
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("LOAD R%d,[0x%h]",IR[1:0], {DS, VALUE});
+ `endif
+ addr <= { DS, VALUE };
+ we <= 0;
+ ioreq <= 0;
+ RESULT_REG <= IR[1:0];
+
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("STORE [0x%h],R%d", {DS, VALUE}, IR[1:0]);
+ `endif
+ addr <= { DS, VALUE };
+ we <= 1;
+ ioreq <= 0;
+ data_out <= R[IR[1:0]];
+
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ endcase
+ end
+ STATE_LOAD_VALUE_WAIT :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_LOAD_VALUE;
+ end
+ STATE_LOAD_VALUE :
+ begin
+ R[RESULT_REG] <= data_in;
+ we <= 0;
+ state <= STATE_FETCH_PREP;
+ end
+ STATE_ALU_RESULT_WAIT :
+ begin
+ state <= STATE_ALU_RESULT;
+ end
+ STATE_ALU_RESULT :
+ begin
+ R[RESULT_REG] <= alu_res;
+ state <= STATE_FETCH_PREP;
+ end
+ STATE_PUSH_PC_LOW :
+ begin
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= PC[7:0];
+ SP <= SP - 1;
+ state <= STATE_JUMP;
+ end
+ STATE_JUMP :
+ begin
+ `ifdef DISASSEMBLY
+ $display("Jumping to %h",FUTURE_PC);
+ `endif
+ PC <= FUTURE_PC;
+ state <= STATE_FETCH_PREP;
+ end
+ STATE_RET_VALUE_WAIT :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_RET_VALUE;
+ end
+ STATE_RET_VALUE :
+ begin
+ FUTURE_PC <= { 4'b0000, data_in };
+ we <= 0;
+ state <= STATE_RET_VALUE_WAIT2;
+
+ addr <= SP + 1;
+ we <= 0;
+ ioreq <= 0;
+ SP <= SP + 1;
+ end
+ STATE_RET_VALUE_WAIT2 :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_RET_VALUE2;
+ end
+ STATE_RET_VALUE2 :
+ begin
+ FUTURE_PC <= FUTURE_PC | ({ 4'b0000, data_in } << 8);
+ we <= 0;
+ state <= STATE_JUMP;
+ end
+ default :
+ begin
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ end
+endmodule
diff --git a/tests/sat/ram_memory.v b/tests/sat/ram_memory.v
new file mode 100644
index 000000000..0d91514b2
--- /dev/null
+++ b/tests/sat/ram_memory.v
@@ -0,0 +1,39 @@
+module ram_memory(
+ input clk,
+ input [11:0] addr,
+ input [7:0] data_in,
+ input we,
+ output reg [7:0] data_out
+);
+
+ reg [7:0] store[0:4095] /* verilator public_flat */;
+
+ initial
+ begin
+ store[0] <= 8'b11100001; // MOV DS,2
+ store[1] <= 8'b00000010; //
+ store[2] <= 8'b01010100; // LOAD R1,[R0]
+ store[3] <= 8'b00110001; // INC R1
+ store[4] <= 8'b00110001; // INC R1
+ store[5] <= 8'b01100001; // STORE [R0],R1
+ store[6] <= 8'b11010001; // OUT [0],R1
+ store[7] <= 8'b00000000; //
+ store[8] <= 8'b00110001; // INC R1
+ store[9] <= 8'b10100001; // CALL 0x100
+ store[10] <= 8'b00000000; //
+ store[11] <= 8'b01111111; // HLT
+
+
+ store[256] <= 8'b11010001; // OUT [0],R1
+ store[257] <= 8'b00000000; //
+ store[258] <= 8'b01111110; // RET
+
+ store[512] <= 8'b00000000;
+ end
+
+ always @(posedge clk)
+ if (we)
+ store[addr] <= data_in;
+ else
+ data_out <= store[addr];
+endmodule
diff --git a/tests/sat/sim_counter.ys b/tests/sat/sim_counter.ys
new file mode 100644
index 000000000..a0ff41b6e
--- /dev/null
+++ b/tests/sat/sim_counter.ys
@@ -0,0 +1,48 @@
+# Create stimulus file
+read_verilog <<EOT
+module top (clk, reset, cnt);
+
+input clk;
+input reset;
+output [7:0] cnt;
+
+reg [7:0] cnt;
+
+endmodule
+EOT
+prep -top top;
+sim -clock clk -reset reset -fst stimulus.fst -n 10
+design -reset
+
+# Counter implementation
+read_verilog <<EOT
+module top (clk, reset, cnt);
+
+input clk;
+input reset;
+output [7:0] cnt;
+
+reg [7:0] cnt;
+
+always @(posedge clk)
+ if (!reset)
+ cnt = cnt + 1;
+ else
+ cnt = 0;
+
+endmodule
+EOT
+prep -top top;
+
+# Simulate with stimulus
+sim -clock clk -scope top -r stimulus.fst
+
+# Stimulus does not have counter values
+# x in FST can match any value in simulation
+sim -clock clk -scope top -r stimulus.fst -sim-gate
+
+# Stimulus does not have counter values
+# x in simulation can match any value in FST
+# so we expect error
+logger -expect error "Signal difference" 1
+sim -clock clk -scope top -r stimulus.fst -sim-gold
diff --git a/tests/sim/.gitignore b/tests/sim/.gitignore
new file mode 100644
index 000000000..2c96b65f8
--- /dev/null
+++ b/tests/sim/.gitignore
@@ -0,0 +1,6 @@
+*.log
+/run-test.mk
++*_synth.v
++*_testbench
+*.out
+*.fst
diff --git a/tests/sim/adff.v b/tests/sim/adff.v
new file mode 100644
index 000000000..8c8fb0acf
--- /dev/null
+++ b/tests/sim/adff.v
@@ -0,0 +1,7 @@
+module adff( input d, clk, rst, output reg q );
+ always @( posedge clk, posedge rst )
+ if (rst)
+ q <= 0;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/adffe.v b/tests/sim/adffe.v
new file mode 100644
index 000000000..55c7d8d4e
--- /dev/null
+++ b/tests/sim/adffe.v
@@ -0,0 +1,8 @@
+module adffe( input d, clk, rst, en, output reg q );
+ always @( posedge clk, posedge rst )
+ if (rst)
+ q <= 0;
+ else
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/sim/adlatch.v b/tests/sim/adlatch.v
new file mode 100644
index 000000000..5e8f48e49
--- /dev/null
+++ b/tests/sim/adlatch.v
@@ -0,0 +1,8 @@
+module adlatch( input d, rst, en, output reg q );
+ always @* begin
+ if (rst)
+ q = 0;
+ else if (en)
+ q = d;
+ end
+endmodule
diff --git a/tests/sim/aldff.v b/tests/sim/aldff.v
new file mode 100644
index 000000000..eeb0f0673
--- /dev/null
+++ b/tests/sim/aldff.v
@@ -0,0 +1,7 @@
+module aldff( input [0:3] d, input [0:3] ad, input clk, aload, output reg [0:3] q );
+ always @( posedge clk, posedge aload)
+ if (aload)
+ q <= ad;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/aldffe.v b/tests/sim/aldffe.v
new file mode 100644
index 000000000..79c65afc4
--- /dev/null
+++ b/tests/sim/aldffe.v
@@ -0,0 +1,8 @@
+module aldffe( input [0:3] d, input [0:3] ad, input clk, aload, en, output reg [0:3] q );
+ always @( posedge clk, posedge aload)
+ if (aload)
+ q <= ad;
+ else
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/sim/dff.v b/tests/sim/dff.v
new file mode 100644
index 000000000..ce792b59a
--- /dev/null
+++ b/tests/sim/dff.v
@@ -0,0 +1,4 @@
+module dff( input d, clk, output reg q );
+ always @( posedge clk )
+ q <= d;
+endmodule
diff --git a/tests/sim/dffe.v b/tests/sim/dffe.v
new file mode 100644
index 000000000..853fcf66a
--- /dev/null
+++ b/tests/sim/dffe.v
@@ -0,0 +1,5 @@
+module dffe( input clk, en, d, output reg q );
+ always @( posedge clk )
+ if ( en )
+ q <= d;
+endmodule
diff --git a/tests/sim/dffsr.v b/tests/sim/dffsr.v
new file mode 100644
index 000000000..2158708f1
--- /dev/null
+++ b/tests/sim/dffsr.v
@@ -0,0 +1,9 @@
+module dffsr( input clk, d, clr, set, output reg q );
+ always @( posedge clk, posedge set, posedge clr)
+ if ( clr )
+ q <= 0;
+ else if (set)
+ q <= 1;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/dlatch.v b/tests/sim/dlatch.v
new file mode 100644
index 000000000..315b43216
--- /dev/null
+++ b/tests/sim/dlatch.v
@@ -0,0 +1,6 @@
+module dlatch( input d, en, output reg q );
+ always @* begin
+ if ( en )
+ q = d;
+ end
+endmodule
diff --git a/tests/sim/dlatchsr.v b/tests/sim/dlatchsr.v
new file mode 100644
index 000000000..1d13ac2ad
--- /dev/null
+++ b/tests/sim/dlatchsr.v
@@ -0,0 +1,11 @@
+module dlatchsr( input d, set, clr, en, output reg q );
+ always @* begin
+ if ( clr )
+ q = 0;
+ else if (set)
+ q = 1;
+ else
+ if (en)
+ q = d;
+ end
+endmodule
diff --git a/tests/sim/run-test.sh b/tests/sim/run-test.sh
new file mode 100755
index 000000000..d34d1f3c9
--- /dev/null
+++ b/tests/sim/run-test.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+set -eu
+source ../gen-tests-makefile.sh
+echo "Generate FST for sim models"
+find tb/* -name tb*.v | while read name; do
+ test_name=$(basename -s .v $name)
+ echo "Test $test_name"
+ verilog_name=${test_name:3}.v
+ iverilog -o tb/$test_name.out $name $verilog_name
+ ./tb/$test_name.out -fst
+done
+run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'"
diff --git a/tests/sim/sdff.v b/tests/sim/sdff.v
new file mode 100644
index 000000000..6b25516e1
--- /dev/null
+++ b/tests/sim/sdff.v
@@ -0,0 +1,7 @@
+module sdff( input d, clk, rst, output reg q );
+ always @( posedge clk)
+ if (rst)
+ q <= 0;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/sdffce.v b/tests/sim/sdffce.v
new file mode 100644
index 000000000..7d27d5741
--- /dev/null
+++ b/tests/sim/sdffce.v
@@ -0,0 +1,8 @@
+module sdffce( input d, clk, rst, en, output reg q );
+ always @( posedge clk)
+ if(en)
+ if (rst)
+ q <= 0;
+ else
+ q <= d;
+endmodule
diff --git a/tests/sim/sdffe.v b/tests/sim/sdffe.v
new file mode 100644
index 000000000..0a96693e1
--- /dev/null
+++ b/tests/sim/sdffe.v
@@ -0,0 +1,8 @@
+module sdffe( input d, clk, rst, en, output reg q );
+ always @( posedge clk)
+ if (rst)
+ q <= 0;
+ else
+ if (en)
+ q <= d;
+endmodule
diff --git a/tests/sim/sim_adff.ys b/tests/sim/sim_adff.ys
new file mode 100644
index 000000000..6efd804a9
--- /dev/null
+++ b/tests/sim/sim_adff.ys
@@ -0,0 +1,6 @@
+read_verilog adff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$adff
+sim -clock clk -r tb_adff.fst -scope tb_adff.uut -sim-cmp adff
diff --git a/tests/sim/sim_adffe.ys b/tests/sim/sim_adffe.ys
new file mode 100644
index 000000000..47a51ebce
--- /dev/null
+++ b/tests/sim/sim_adffe.ys
@@ -0,0 +1,6 @@
+read_verilog adffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$adffe
+sim -clock clk -r tb_adffe.fst -scope tb_adffe.uut -sim-cmp adffe
diff --git a/tests/sim/sim_adlatch.ys b/tests/sim/sim_adlatch.ys
new file mode 100644
index 000000000..eece7dc0d
--- /dev/null
+++ b/tests/sim/sim_adlatch.ys
@@ -0,0 +1,10 @@
+read_verilog -icells <<EOT
+module adlatch(input d, rst, en, output reg q);
+$adlatch #(.EN_POLARITY(1'b1), .ARST_POLARITY(1'b1), .ARST_VALUE(1'b0), .WIDTH(1)) uut (.EN(en), .ARST(rst), .D(d), .Q(q));
+endmodule
+EOT
+proc
+opt_dff
+stat
+select -assert-count 1 t:$adlatch
+sim -r tb_adlatch.fst -scope tb_adlatch.uut -sim-cmp adlatch
diff --git a/tests/sim/sim_aldff.ys b/tests/sim/sim_aldff.ys
new file mode 100644
index 000000000..9c8b3bdfc
--- /dev/null
+++ b/tests/sim/sim_aldff.ys
@@ -0,0 +1,6 @@
+read_verilog aldff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$aldff
+sim -clock clk -r tb_aldff.fst -scope tb_aldff.uut -sim-cmp aldff
diff --git a/tests/sim/sim_aldffe.ys b/tests/sim/sim_aldffe.ys
new file mode 100644
index 000000000..b191cf877
--- /dev/null
+++ b/tests/sim/sim_aldffe.ys
@@ -0,0 +1,6 @@
+read_verilog aldffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$aldffe
+sim -clock clk -r tb_aldffe.fst -scope tb_aldffe.uut -sim-cmp aldffe
diff --git a/tests/sim/sim_dff.ys b/tests/sim/sim_dff.ys
new file mode 100644
index 000000000..12f402443
--- /dev/null
+++ b/tests/sim/sim_dff.ys
@@ -0,0 +1,6 @@
+read_verilog dff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dff
+sim -clock clk -r tb_dff.fst -scope tb_dff.uut -sim-cmp dff
diff --git a/tests/sim/sim_dffe.ys b/tests/sim/sim_dffe.ys
new file mode 100644
index 000000000..f9b9e4767
--- /dev/null
+++ b/tests/sim/sim_dffe.ys
@@ -0,0 +1,6 @@
+read_verilog dffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dffe
+sim -clock clk -r tb_dffe.fst -scope tb_dffe.uut -sim-cmp dffe
diff --git a/tests/sim/sim_dffsr.ys b/tests/sim/sim_dffsr.ys
new file mode 100644
index 000000000..e99ee860d
--- /dev/null
+++ b/tests/sim/sim_dffsr.ys
@@ -0,0 +1,6 @@
+read_verilog dffsr.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dffsr
+sim -clock clk -r tb_dffsr.fst -scope tb_dffsr.uut -sim-cmp dffsr
diff --git a/tests/sim/sim_dlatch.ys b/tests/sim/sim_dlatch.ys
new file mode 100644
index 000000000..79e4601e3
--- /dev/null
+++ b/tests/sim/sim_dlatch.ys
@@ -0,0 +1,6 @@
+read_verilog dlatch.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dlatch
+sim -r tb_dlatch.fst -scope tb_dlatch.uut -sim-cmp dlatch
diff --git a/tests/sim/sim_dlatchsr.ys b/tests/sim/sim_dlatchsr.ys
new file mode 100644
index 000000000..c83051c8b
--- /dev/null
+++ b/tests/sim/sim_dlatchsr.ys
@@ -0,0 +1,10 @@
+read_verilog -icells <<EOT
+module dlatchsr(input d, set, clr, en, output reg q);
+$dlatchsr #(.EN_POLARITY(1'b1), .CLR_POLARITY(1'b1), .SET_POLARITY(1'b1), .WIDTH(1)) uut (.EN(en), .SET(set), .CLR(clr), .D(d), .Q(q));
+endmodule
+EOT
+proc
+opt_dff
+stat
+select -assert-count 1 t:$dlatchsr
+sim -r tb_dlatchsr.fst -scope tb_dlatchsr.uut -sim-cmp dlatchsr
diff --git a/tests/sim/sim_sdff.ys b/tests/sim/sim_sdff.ys
new file mode 100644
index 000000000..a812c5d80
--- /dev/null
+++ b/tests/sim/sim_sdff.ys
@@ -0,0 +1,6 @@
+read_verilog sdff.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$sdff
+sim -clock clk -r tb_sdff.fst -scope tb_sdff.uut -sim-cmp sdff
diff --git a/tests/sim/sim_sdffce.ys b/tests/sim/sim_sdffce.ys
new file mode 100644
index 000000000..b28acb83d
--- /dev/null
+++ b/tests/sim/sim_sdffce.ys
@@ -0,0 +1,6 @@
+read_verilog sdffce.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$sdffce
+sim -clock clk -r tb_sdffce.fst -scope tb_sdffce.uut -sim-cmp sdffce
diff --git a/tests/sim/sim_sdffe.ys b/tests/sim/sim_sdffe.ys
new file mode 100644
index 000000000..044f78eb3
--- /dev/null
+++ b/tests/sim/sim_sdffe.ys
@@ -0,0 +1,6 @@
+read_verilog sdffe.v
+proc
+opt_dff
+stat
+select -assert-count 1 t:$sdffe
+sim -clock clk -r tb_sdffe.fst -scope tb_sdffe.uut -sim-cmp sdffe
diff --git a/tests/sim/tb/tb_adff.v b/tests/sim/tb/tb_adff.v
new file mode 100755
index 000000000..f1bc3547e
--- /dev/null
+++ b/tests/sim/tb/tb_adff.v
@@ -0,0 +1,40 @@
+`timescale 1ns/1ns
+module tb_adff();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ wire q;
+
+ adff uut(.clk(clk),.d(d),.rst(rst),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_adff");
+ $dumpvars(0,tb_adff);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_adffe.v b/tests/sim/tb/tb_adffe.v
new file mode 100755
index 000000000..bb23f963d
--- /dev/null
+++ b/tests/sim/tb/tb_adffe.v
@@ -0,0 +1,58 @@
+`timescale 1ns/1ns
+module tb_adffe();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ reg en = 0;
+ wire q;
+
+ adffe uut(.clk(clk),.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_adffe");
+ $dumpvars(0,tb_adffe);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_adlatch.v b/tests/sim/tb/tb_adlatch.v
new file mode 100755
index 000000000..59dd498d2
--- /dev/null
+++ b/tests/sim/tb/tb_adlatch.v
@@ -0,0 +1,70 @@
+`timescale 1ns/1ns
+module tb_adlatch();
+ reg clk = 0;
+ reg rst = 0;
+ reg en = 0;
+ reg d = 0;
+ wire q;
+
+ adlatch uut(.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_adlatch");
+ $dumpvars(0,tb_adlatch);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_aldff.v b/tests/sim/tb/tb_aldff.v
new file mode 100755
index 000000000..0591c8b3c
--- /dev/null
+++ b/tests/sim/tb/tb_aldff.v
@@ -0,0 +1,73 @@
+`timescale 1ns/1ns
+module tb_aldff();
+ reg clk = 0;
+ reg aload = 0;
+ reg [0:3] d = 4'b0000;
+ reg [0:3] ad = 4'b1010;
+ wire [0:3] q;
+
+ aldff uut(.clk(clk),.d(d),.ad(ad),.aload(aload),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_aldff");
+ $dumpvars(0,tb_aldff);
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_aldffe.v b/tests/sim/tb/tb_aldffe.v
new file mode 100755
index 000000000..c3cb57f4e
--- /dev/null
+++ b/tests/sim/tb/tb_aldffe.v
@@ -0,0 +1,75 @@
+`timescale 1ns/1ns
+module tb_aldffe();
+ reg clk = 0;
+ reg aload = 0;
+ reg [0:3] d = 4'b0000;
+ reg [0:3] ad = 4'b1010;
+ reg en = 0;
+ wire [0:3] q;
+
+ aldffe uut(.clk(clk),.d(d),.ad(ad),.aload(aload),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_aldffe");
+ $dumpvars(0,tb_aldffe);
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ en = 1;
+ aload = 1;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ aload = 0;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ d = 4'b1100;
+ #10
+ d = 4'b0011;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dff.v b/tests/sim/tb/tb_dff.v
new file mode 100755
index 000000000..aa41d1c6c
--- /dev/null
+++ b/tests/sim/tb/tb_dff.v
@@ -0,0 +1,47 @@
+`timescale 1ns/1ns
+module tb_dff();
+ reg clk = 0;
+ reg d = 0;
+ wire q;
+
+ dff uut(.clk(clk),.d(d),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dff");
+ $dumpvars(0,tb_dff);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dffe.v b/tests/sim/tb/tb_dffe.v
new file mode 100755
index 000000000..4e262b928
--- /dev/null
+++ b/tests/sim/tb/tb_dffe.v
@@ -0,0 +1,42 @@
+`timescale 1ns/1ns
+module tb_dffe();
+ reg clk = 0;
+ reg en = 0;
+ reg d = 0;
+ wire q;
+
+ dffe uut(.clk(clk),.d(d),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dffe");
+ $dumpvars(0,tb_dffe);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dffsr.v b/tests/sim/tb/tb_dffsr.v
new file mode 100755
index 000000000..6ecb85d67
--- /dev/null
+++ b/tests/sim/tb/tb_dffsr.v
@@ -0,0 +1,69 @@
+`timescale 1ns/1ns
+module tb_dffsr();
+ reg clk = 0;
+ reg d = 0;
+ reg set = 0;
+ reg clr = 0;
+ wire q;
+
+ dffsr uut(.d(d),.clk(clk),.set(set),.clr(clr),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dffsr");
+ $dumpvars(0,tb_dffsr);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dlatch.v b/tests/sim/tb/tb_dlatch.v
new file mode 100755
index 000000000..aea6cb0a3
--- /dev/null
+++ b/tests/sim/tb/tb_dlatch.v
@@ -0,0 +1,50 @@
+`timescale 1ns/1ns
+module tb_dlatch();
+ reg clk = 0;
+ reg en = 0;
+ reg d = 0;
+ wire q;
+
+ dlatch uut(.d(d),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_dlatch");
+ $dumpvars(0,tb_dlatch);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_dlatchsr.v b/tests/sim/tb/tb_dlatchsr.v
new file mode 100755
index 000000000..0105d3288
--- /dev/null
+++ b/tests/sim/tb/tb_dlatchsr.v
@@ -0,0 +1,65 @@
+`timescale 1ns/1ns
+module tb_dlatchsr();
+ reg d = 0;
+ reg set = 0;
+ reg clr = 0;
+ wire q;
+
+ dlatchsr uut(.d(d),.set(set),.clr(clr),.q(q));
+
+ initial
+ begin
+ $dumpfile("tb_dlatchsr");
+ $dumpvars(0,tb_dlatchsr);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ clr = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ set = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_sdff.v b/tests/sim/tb/tb_sdff.v
new file mode 100755
index 000000000..f8e2a1c9d
--- /dev/null
+++ b/tests/sim/tb/tb_sdff.v
@@ -0,0 +1,48 @@
+`timescale 1ns/1ns
+module tb_sdff();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ wire q;
+
+ sdff uut(.clk(clk),.d(d),.rst(rst),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_sdff");
+ $dumpvars(0,tb_sdff);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_sdffce.v b/tests/sim/tb/tb_sdffce.v
new file mode 100755
index 000000000..1c9952806
--- /dev/null
+++ b/tests/sim/tb/tb_sdffce.v
@@ -0,0 +1,79 @@
+`timescale 1ns/1ns
+module tb_sdffce();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ reg en = 0;
+ wire q;
+
+ sdffce uut(.clk(clk),.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_sdffce");
+ $dumpvars(0,tb_sdffce);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/sim/tb/tb_sdffe.v b/tests/sim/tb/tb_sdffe.v
new file mode 100755
index 000000000..36072f93d
--- /dev/null
+++ b/tests/sim/tb/tb_sdffe.v
@@ -0,0 +1,70 @@
+`timescale 1ns/1ns
+module tb_sdffe();
+ reg clk = 0;
+ reg rst = 0;
+ reg d = 0;
+ reg en = 0;
+ wire q;
+
+ sdffe uut(.clk(clk),.d(d),.rst(rst),.en(en),.q(q));
+
+ always
+ #(5) clk <= !clk;
+
+ initial
+ begin
+ $dumpfile("tb_sdffe");
+ $dumpvars(0,tb_sdffe);
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ en = 1;
+ rst = 1;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ rst = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ d = 1;
+ #10
+ d = 0;
+ #10
+ $finish;
+ end
+endmodule
diff --git a/tests/various/.gitignore b/tests/various/.gitignore
index 2bb6c7179..c6373468a 100644
--- a/tests/various/.gitignore
+++ b/tests/various/.gitignore
@@ -5,3 +5,4 @@
/run-test.mk
/plugin.so
/plugin.so.dSYM
+/temp
diff --git a/tests/various/json_escape_chars.ys b/tests/various/json_escape_chars.ys
new file mode 100644
index 000000000..f118357c0
--- /dev/null
+++ b/tests/various/json_escape_chars.ys
@@ -0,0 +1,14 @@
+! mkdir -p temp
+read_verilog <<EOT
+(* src = "\042 \057 \134 \010 \014 \012 \015 \011 \025 \033" *)
+module foo;
+endmodule
+EOT
+write_json temp/test_escapes.json
+design -reset
+read_json temp/test_escapes.json
+write_json temp/test_escapes.json
+design -reset
+read_json temp/test_escapes.json
+write_rtlil temp/test_escapes.json.il
+! grep -F 'attribute \src "\" / \\ \010 \014 \n \015 \t \025 \033"' temp/test_escapes.json.il
diff --git a/tests/various/param_struct.ys b/tests/various/param_struct.ys
index 6d7a7c6ad..b8de67968 100644
--- a/tests/various/param_struct.ys
+++ b/tests/various/param_struct.ys
@@ -41,8 +41,7 @@ always_comb begin
assert(j == 1'b1);
assert(k == 1'b0);
assert(l == 3'b111);
-// TODO: support access to whole sub-structs and unions
-// assert(m == 2'b10);
+ assert(m == 2'b10);
assert(u == 5'b11001);
end
endmodule
diff --git a/tests/various/struct_access.sv b/tests/various/struct_access.sv
new file mode 100644
index 000000000..d41a7114f
--- /dev/null
+++ b/tests/various/struct_access.sv
@@ -0,0 +1,43 @@
+module dut();
+typedef struct packed {
+ logic a;
+ logic b;
+} sub_sub_struct_t;
+
+typedef struct packed {
+ sub_sub_struct_t c;
+} sub_struct_t;
+
+typedef struct packed {
+ sub_struct_t d;
+ sub_struct_t e;
+} struct_t;
+
+parameter struct_t P = 4'b1100;
+
+localparam sub_struct_t f = P.d;
+localparam sub_struct_t g = P.e;
+localparam sub_sub_struct_t h = f.c;
+localparam logic i = P.d.c.a;
+localparam logic j = P.d.c.b;
+localparam x = P.e;
+localparam y = x.c;
+localparam z = y.a;
+localparam q = P.d;
+localparam n = q.c.a;
+
+always_comb begin
+ assert(P == 4'b1100);
+ assert(f == 2'b11);
+ assert(g == 2'b00);
+ assert(h == 2'b11);
+ assert(i == 1'b1);
+ assert(j == 1'b1);
+ assert(x == 2'b00);
+ assert(y == 2'b00);
+ assert(x.c == 2'b00);
+ assert(y.b == 1'b0);
+ assert(n == 1'b1);
+ assert(z == 1'b0);
+end
+endmodule
diff --git a/tests/various/struct_access.ys b/tests/various/struct_access.ys
new file mode 100644
index 000000000..2282edd92
--- /dev/null
+++ b/tests/various/struct_access.ys
@@ -0,0 +1,5 @@
+read_verilog -sv struct_access.sv
+hierarchy
+proc
+opt
+sat -verify -seq 1 -prove-asserts -show-all
diff --git a/tests/verilog/delay_time_scale.ys b/tests/verilog/delay_time_scale.ys
new file mode 100644
index 000000000..f45ba7b26
--- /dev/null
+++ b/tests/verilog/delay_time_scale.ys
@@ -0,0 +1,25 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOT
+module top;
+wand x;
+`define TEST(time_scale) if (1) assign #time_scale x = 1;
+
+`TEST(1s)
+`TEST(1ms)
+`TEST(1us)
+`TEST(1ns)
+`TEST(1ps)
+`TEST(1fs)
+
+`TEST((1s))
+`TEST(( 1s))
+`TEST((1s ))
+`TEST(( 1s ))
+
+`TEST(1.0s)
+`TEST(1.1s)
+`TEST(1.0e-1s)
+`TEST(1e-1s)
+
+endmodule
+EOT
diff --git a/tests/verilog/dynamic_range_lhs.sh b/tests/verilog/dynamic_range_lhs.sh
new file mode 100755
index 000000000..618204aed
--- /dev/null
+++ b/tests/verilog/dynamic_range_lhs.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+run() {
+ alt=$1
+ span=$2
+ left=$3
+ right=$4
+ echo "a=$alt s=$span l=$left r=$right"
+
+ ../../yosys -q \
+ -DALT=$alt \
+ -DSPAN=$span \
+ -DLEFT=$left \
+ -DRIGHT=$right \
+ -p "read_verilog dynamic_range_lhs.v" \
+ -p "proc" \
+ -p "equiv_make gold gate equiv" \
+ -p "equiv_simple" \
+ -p "equiv_status -assert"
+}
+
+trap 'echo "ERROR in dynamic_range_lhs.sh span=$span left=$left right=$right" >&2; exit 1' ERR
+
+for alt in `seq 0 1`; do
+for span in `seq 1 4`; do
+for left in `seq -4 4`; do
+for right in `seq $(expr $left + -3) $(expr $left + 3)`; do
+ run $alt $span $left $right
+done
+done
+done
+done
diff --git a/tests/verilog/dynamic_range_lhs.v b/tests/verilog/dynamic_range_lhs.v
new file mode 100644
index 000000000..ae291374d
--- /dev/null
+++ b/tests/verilog/dynamic_range_lhs.v
@@ -0,0 +1,76 @@
+module gate(
+ output reg [`LEFT:`RIGHT] out_u, out_s,
+ (* nowrshmsk = `ALT *)
+ input wire data,
+ input wire [1:0] sel1, sel2
+);
+always @* begin
+ out_u = 0;
+ out_s = 0;
+ case (`SPAN)
+ 1: begin
+ out_u[sel1*sel2] = data;
+ out_s[$signed(sel1*sel2)] = data;
+ end
+ 2: begin
+ out_u[sel1*sel2+:2] = {data, data};
+ out_s[$signed(sel1*sel2)+:2] = {data, data};
+ end
+ 3: begin
+ out_u[sel1*sel2+:3] = {data, data, data};
+ out_s[$signed(sel1*sel2)+:3] = {data, data, data};
+ end
+ 4: begin
+ out_u[sel1*sel2+:4] = {data, data, data, data};
+ out_s[$signed(sel1*sel2)+:4] = {data, data, data, data};
+ end
+ endcase
+end
+endmodule
+
+module gold(
+ output reg [`LEFT:`RIGHT] out_u, out_s,
+ input wire data,
+ input wire [1:0] sel1, sel2
+);
+task set;
+ input integer a, b;
+ localparam LOW = `LEFT > `RIGHT ? `RIGHT : `LEFT;
+ localparam HIGH = `LEFT > `RIGHT ? `LEFT : `RIGHT;
+ if (LOW <= a && a <= HIGH)
+ out_u[a] = data;
+ if (LOW <= b && b <= HIGH)
+ out_s[b] = data;
+endtask
+always @* begin
+ out_u = 0;
+ out_s = 0;
+ case (sel1*sel2)
+ 2'b00: set(0, 0);
+ 2'b01: set(1, 1);
+ 2'b10: set(2, -2);
+ 2'b11: set(3, -1);
+ endcase
+ if (`SPAN >= 2)
+ case (sel1*sel2)
+ 2'b00: set(1, 1);
+ 2'b01: set(2, 2);
+ 2'b10: set(3, -1);
+ 2'b11: set(4, 0);
+ endcase
+ if (`SPAN >= 3)
+ case (sel1*sel2)
+ 2'b00: set(2, 2);
+ 2'b01: set(3, 3);
+ 2'b10: set(4, 0);
+ 2'b11: set(5, 1);
+ endcase
+ if (`SPAN >= 4)
+ case (sel1*sel2)
+ 2'b00: set(3, 3);
+ 2'b01: set(4, 4);
+ 2'b10: set(5, 1);
+ 2'b11: set(6, 2);
+ endcase
+end
+endmodule
diff --git a/tests/verilog/func_upto.sv b/tests/verilog/func_upto.sv
new file mode 100644
index 000000000..547e5d325
--- /dev/null
+++ b/tests/verilog/func_upto.sv
@@ -0,0 +1,77 @@
+`default_nettype none
+
+module evil;
+ parameter HI = 3;
+ parameter LO = 0;
+ parameter SPAN = 1;
+ parameter [HI:LO] A_VAL = 4'b0110;
+ parameter [HI:LO] B_VAL = 4'b1100;
+ parameter [2:0] SWAPS = 0;
+
+ localparam D_LEFT = !(SWAPS[0]) ? HI : LO;
+ localparam D_RIGHT = (SWAPS[0]) ? HI : LO;
+ localparam E_LEFT = !(SWAPS[1]) ? HI : LO;
+ localparam E_RIGHT = (SWAPS[1]) ? HI : LO;
+ localparam F_LEFT = !(SWAPS[2]) ? HI : LO;
+ localparam F_RIGHT = (SWAPS[2]) ? HI : LO;
+
+ localparam [HI:LO] A_CONST = A_VAL;
+ localparam [HI:LO] B_CONST = B_VAL;
+ localparam [HI:LO] C_CONST = F(A_CONST, B_CONST);
+
+ reg [HI:LO] C_WIRE, C_FUNC;
+ always @* begin
+ assert (C_CONST == C_WIRE);
+ assert (C_CONST == C_FUNC);
+ end
+
+ initial begin : blk
+ reg [HI:LO] A_WIRE;
+ reg [HI:LO] B_WIRE;
+ reg [D_LEFT:D_RIGHT] D;
+ reg [E_LEFT:E_RIGHT] E;
+ reg [F_LEFT:F_RIGHT] F_WIRE;
+ reg [31:0] i;
+ A_WIRE = A_VAL;
+ B_WIRE = B_VAL;
+ D = A_WIRE;
+ E = B_WIRE;
+ F_WIRE = 0;
+ for (i = LO; i + SPAN < HI; i = i + SPAN)
+ if (SPAN == 1)
+ F_WIRE[i] = D[i] && E[i];
+ else
+ F_WIRE[i+:SPAN] = D[i+:SPAN] && E[i+:SPAN];
+ C_WIRE = F_WIRE;
+ C_FUNC = F(A_WIRE, B_WIRE);
+ end
+
+ function automatic [F_LEFT:F_RIGHT] F(
+ input [D_LEFT:D_RIGHT] D,
+ input [E_LEFT:E_RIGHT] E);
+ reg [31:0] i;
+ F = 0;
+ for (i = LO; i + SPAN < HI; i = i + SPAN)
+ if (SPAN == 1)
+ F[i] = D[i] && E[i];
+ else
+ F[i+:SPAN] = D[i+:SPAN] && E[i+:SPAN];
+ endfunction
+endmodule
+
+module top;
+ for (genvar hi = 0; hi < 3; hi++)
+ for (genvar lo = 0; lo <= hi; lo++)
+ for (genvar span = 1; span <= hi - lo + 1; span++)
+ for (genvar a_val = 0; a_val < 2 ** (hi - lo + 1); a_val++)
+ for (genvar b_val = 0; b_val < 2 ** (hi - lo + 1); b_val++)
+ for (genvar swaps = 0; swaps < 2 ** 3; swaps++)
+ evil #(
+ .HI(hi),
+ .LO(lo),
+ .SPAN(span),
+ .A_VAL(a_val),
+ .B_VAL(b_val),
+ .SWAPS(swaps)
+ ) e();
+endmodule
diff --git a/tests/verilog/func_upto.ys b/tests/verilog/func_upto.ys
new file mode 100644
index 000000000..7a8c53506
--- /dev/null
+++ b/tests/verilog/func_upto.ys
@@ -0,0 +1,7 @@
+read_verilog -sv func_upto.sv
+hierarchy -top top
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -prove-asserts -enable_undef
diff --git a/tests/verilog/struct_access.sv b/tests/verilog/struct_access.sv
index f13b8dd51..bc91e3f01 100644
--- a/tests/verilog/struct_access.sv
+++ b/tests/verilog/struct_access.sv
@@ -77,9 +77,8 @@ module top;
`CHECK(s.y.a, 1, 0)
`CHECK(s.y.b, 1, 1)
- // TODO(zachjs): support access to whole sub-structs and unions
- // `CHECK(s.x, 2, 0)
- // `CHECK(s.y, 2, 1)
+ `CHECK(s.x, 2, 0)
+ `CHECK(s.y, 2, 1)
assert (fail === 0);
end