diff options
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 @@ -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 @@ -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 @@ -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 |