@yowasp/yosys 0.37.13-dev.628 → 0.37.58-dev.635
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/gen/resources-yosys.js
CHANGED
|
@@ -132,7 +132,7 @@ export const filesystem = {
|
|
|
132
132
|
"cxxrtl_capi_vcd.cc": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2020 whitequark <whitequark@whitequark.org>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n// This file is a part of the CXXRTL C API. It should be used together with `cxxrtl/capi/cxxrtl_capi_vcd.h`.\n\n#include <cxxrtl/capi/cxxrtl_capi_vcd.h>\n#include <cxxrtl/cxxrtl_vcd.h>\n\nextern const cxxrtl::debug_items &cxxrtl_debug_items_from_handle(cxxrtl_handle handle);\n\nstruct _cxxrtl_vcd {\n\tcxxrtl::vcd_writer writer;\n\tbool flush = false;\n};\n\ncxxrtl_vcd cxxrtl_vcd_create() {\n\treturn new _cxxrtl_vcd;\n}\n\nvoid cxxrtl_vcd_destroy(cxxrtl_vcd vcd) {\n\tdelete vcd;\n}\n\nvoid cxxrtl_vcd_timescale(cxxrtl_vcd vcd, int number, const char *unit) {\n\tvcd->writer.timescale(number, unit);\n}\n\nvoid cxxrtl_vcd_add(cxxrtl_vcd vcd, const char *name, cxxrtl_object *object) {\n\t// Note the copy. We don't know whether `object` came from a design (in which case it is\n\t// an instance of `debug_item`), or from user code (in which case it is an instance of\n\t// `cxxrtl_object`), so casting the pointer wouldn't be safe.\n\tvcd->writer.add(name, cxxrtl::debug_item(*object));\n}\n\nvoid cxxrtl_vcd_add_from(cxxrtl_vcd vcd, cxxrtl_handle handle) {\n\tvcd->writer.add(cxxrtl_debug_items_from_handle(handle));\n}\n\nvoid cxxrtl_vcd_add_from_if(cxxrtl_vcd vcd, cxxrtl_handle handle, void *data,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tint (*filter)(void *data, const char *name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t const cxxrtl_object *object)) {\n\tvcd->writer.add(cxxrtl_debug_items_from_handle(handle),\n\t\t[=](const std::string &name, const cxxrtl::debug_item &item) {\n\t\t\treturn filter(data, name.c_str(), static_cast<const cxxrtl_object*>(&item));\n\t\t});\n}\n\nvoid cxxrtl_vcd_add_from_without_memories(cxxrtl_vcd vcd, cxxrtl_handle handle) {\n\tvcd->writer.add_without_memories(cxxrtl_debug_items_from_handle(handle));\n}\n\nvoid cxxrtl_vcd_sample(cxxrtl_vcd vcd, uint64_t time) {\n\tif (vcd->flush) {\n\t\tvcd->writer.buffer.clear();\n\t\tvcd->flush = false;\n\t}\n\tvcd->writer.sample(time);\n}\n\nvoid cxxrtl_vcd_read(cxxrtl_vcd vcd, const char **data, size_t *size) {\n\tif (vcd->flush) {\n\t\tvcd->writer.buffer.clear();\n\t\tvcd->flush = false;\n\t}\n\t*data = vcd->writer.buffer.c_str();\n\t*size = vcd->writer.buffer.size();\n\tvcd->flush = true;\n}\n",
|
|
133
133
|
"cxxrtl_capi_vcd.h": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2020 whitequark <whitequark@whitequark.org>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n#ifndef CXXRTL_CAPI_VCD_H\n#define CXXRTL_CAPI_VCD_H\n\n// This file is a part of the CXXRTL C API. It should be used together with `cxxrtl_vcd_capi.cc`.\n//\n// The CXXRTL C API for VCD writing makes it possible to insert virtual probes into designs and\n// dump waveforms to Value Change Dump files.\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <cxxrtl/capi/cxxrtl_capi.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// Opaque reference to a VCD writer.\ntypedef struct _cxxrtl_vcd *cxxrtl_vcd;\n\n// Create a VCD writer.\ncxxrtl_vcd cxxrtl_vcd_create();\n\n// Release all resources used by a VCD writer.\nvoid cxxrtl_vcd_destroy(cxxrtl_vcd vcd);\n\n// Set VCD timescale.\n//\n// The `number` must be 1, 10, or 100, and the `unit` must be one of `\"s\"`, `\"ms\"`, `\"us\"`, `\"ns\"`,\n// `\"ps\"`, or `\"fs\"`.\n//\n// Timescale can only be set before the first call to `cxxrtl_vcd_sample`.\nvoid cxxrtl_vcd_timescale(cxxrtl_vcd vcd, int number, const char *unit);\n\n// Schedule a specific CXXRTL object to be sampled.\n//\n// The `name` is a full hierarchical name as described for `cxxrtl_get`; it does not need to match\n// the original name of `object`, if any. The `object` must outlive the VCD writer, but there are\n// no other requirements; if desired, it can be provided by user code, rather than come from\n// a design.\n//\n// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`.\nvoid cxxrtl_vcd_add(cxxrtl_vcd vcd, const char *name, struct cxxrtl_object *object);\n\n// Schedule all CXXRTL objects in a simulation.\n//\n// The design `handle` must outlive the VCD writer.\n//\n// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`.\nvoid cxxrtl_vcd_add_from(cxxrtl_vcd vcd, cxxrtl_handle handle);\n\n// Schedule CXXRTL objects in a simulation that match a given predicate.\n//\n// For every object in the simulation, `filter` is called with the provided `data`, the full\n// hierarchical name of the object (see `cxxrtl_get` for details), and the object description.\n// The object will be sampled if the predicate returns a non-zero value.\n//\n// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`.\nvoid cxxrtl_vcd_add_from_if(cxxrtl_vcd vcd, cxxrtl_handle handle, void *data,\n int (*filter)(void *data, const char *name,\n const struct cxxrtl_object *object));\n\n// Schedule all CXXRTL objects in a simulation except for memories.\n//\n// The design `handle` must outlive the VCD writer.\n//\n// Objects can only be scheduled before the first call to `cxxrtl_vcd_sample`.\nvoid cxxrtl_vcd_add_from_without_memories(cxxrtl_vcd vcd, cxxrtl_handle handle);\n\n// Sample all scheduled objects.\n//\n// First, `time` is written to the internal buffer. Second, the values of every signal changed since\n// the previous call to `cxxrtl_vcd_sample` (all values if this is the first call) are written to\n// the internal buffer. The contents of the buffer can be retrieved with `cxxrtl_vcd_read`.\nvoid cxxrtl_vcd_sample(cxxrtl_vcd vcd, uint64_t time);\n\n// Retrieve buffered VCD data.\n//\n// The pointer to the start of the next chunk of VCD data is assigned to `*data`, and the length\n// of that chunk is assigned to `*size`. The pointer to the data is valid until the next call to\n// `cxxrtl_vcd_sample` or `cxxrtl_vcd_read`. Once all of the buffered data has been retrieved,\n// this function will always return zero sized chunks.\nvoid cxxrtl_vcd_read(cxxrtl_vcd vcd, const char **data, size_t *size);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n",
|
|
134
134
|
},
|
|
135
|
-
"cxxrtl.h": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2019-2020 whitequark <whitequark@whitequark.org>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n// This file is included by the designs generated with `write_cxxrtl`. It is not used in Yosys itself.\n//\n// The CXXRTL support library implements compile time specialized arbitrary width arithmetics, as well as provides\n// composite lvalues made out of bit slices and concatenations of lvalues. This allows the `write_cxxrtl` pass\n// to perform a straightforward translation of RTLIL structures to readable C++, relying on the C++ compiler\n// to unwrap the abstraction and generate efficient code.\n\n#ifndef CXXRTL_H\n#define CXXRTL_H\n\n#include <cstddef>\n#include <cstdint>\n#include <cassert>\n#include <limits>\n#include <type_traits>\n#include <tuple>\n#include <vector>\n#include <map>\n#include <algorithm>\n#include <memory>\n#include <functional>\n#include <sstream>\n\n// `cxxrtl::debug_item` has to inherit from `cxxrtl_object` to satisfy strict aliasing requirements.\n#include <cxxrtl/capi/cxxrtl_capi.h>\n\n#ifndef __has_attribute\n#\tdefine __has_attribute(x) 0\n#endif\n\n// CXXRTL essentially uses the C++ compiler as a hygienic macro engine that feeds an instruction selector.\n// It generates a lot of specialized template functions with relatively large bodies that, when inlined\n// into the caller and (for those with loops) unrolled, often expose many new optimization opportunities.\n// Because of this, most of the CXXRTL runtime must be always inlined for best performance.\n#if __has_attribute(always_inline)\n#define CXXRTL_ALWAYS_INLINE inline __attribute__((__always_inline__))\n#else\n#define CXXRTL_ALWAYS_INLINE inline\n#endif\n// Conversely, some functions in the generated code are extremely large yet very cold, with both of these\n// properties being extreme enough to confuse C++ compilers into spending pathological amounts of time\n// on a futile (the code becomes worse) attempt to optimize the least important parts of code.\n#if __has_attribute(optnone)\n#define CXXRTL_EXTREMELY_COLD __attribute__((__optnone__))\n#elif __has_attribute(optimize)\n#define CXXRTL_EXTREMELY_COLD __attribute__((__optimize__(0)))\n#else\n#define CXXRTL_EXTREMELY_COLD\n#endif\n\n// CXXRTL uses assert() to check for C++ contract violations (which may result in e.g. undefined behavior\n// of the simulation code itself), and CXXRTL_ASSERT to check for RTL contract violations (which may at\n// most result in undefined simulation results).\n//\n// Though by default, CXXRTL_ASSERT() expands to assert(), it may be overridden e.g. when integrating\n// the simulation into another process that should survive violating RTL contracts.\n#ifndef CXXRTL_ASSERT\n#ifndef CXXRTL_NDEBUG\n#define CXXRTL_ASSERT(x) assert(x)\n#else\n#define CXXRTL_ASSERT(x)\n#endif\n#endif\n\nnamespace cxxrtl {\n\n// All arbitrary-width values in CXXRTL are backed by arrays of unsigned integers called chunks. The chunk size\n// is the same regardless of the value width to simplify manipulating values via FFI interfaces, e.g. driving\n// and introspecting the simulation in Python.\n//\n// It is practical to use chunk sizes between 32 bits and platform register size because when arithmetics on\n// narrower integer types is legalized by the C++ compiler, it inserts code to clear the high bits of the register.\n// However, (a) most of our operations do not change those bits in the first place because of invariants that are\n// invisible to the compiler, (b) we often operate on non-power-of-2 values and have to clear the high bits anyway.\n// Therefore, using relatively wide chunks and clearing the high bits explicitly and only when we know they may be\n// clobbered results in simpler generated code.\ntypedef uint32_t chunk_t;\ntypedef uint64_t wide_chunk_t;\n\ntemplate<typename T>\nstruct chunk_traits {\n\tstatic_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,\n\t \"chunk type must be an unsigned integral type\");\n\tusing type = T;\n\tstatic constexpr size_t bits = std::numeric_limits<T>::digits;\n\tstatic constexpr T mask = std::numeric_limits<T>::max();\n};\n\ntemplate<class T>\nstruct expr_base;\n\ntemplate<size_t Bits>\nstruct value : public expr_base<value<Bits>> {\n\tstatic constexpr size_t bits = Bits;\n\n\tusing chunk = chunk_traits<chunk_t>;\n\tstatic constexpr chunk::type msb_mask = (Bits % chunk::bits == 0) ? chunk::mask\n\t\t: chunk::mask >> (chunk::bits - (Bits % chunk::bits));\n\n\tstatic constexpr size_t chunks = (Bits + chunk::bits - 1) / chunk::bits;\n\tchunk::type data[chunks] = {};\n\n\tvalue() = default;\n\ttemplate<typename... Init>\n\texplicit constexpr value(Init ...init) : data{init...} {}\n\n\tvalue(const value<Bits> &) = default;\n\tvalue<Bits> &operator=(const value<Bits> &) = default;\n\n\tvalue(value<Bits> &&) = default;\n\tvalue<Bits> &operator=(value<Bits> &&) = default;\n\n\t// A (no-op) helper that forces the cast to value<>.\n\tCXXRTL_ALWAYS_INLINE\n\tconst value<Bits> &val() const {\n\t\treturn *this;\n\t}\n\n\tstd::string str() const {\n\t\tstd::stringstream ss;\n\t\tss << *this;\n\t\treturn ss.str();\n\t}\n\n\t// Conversion operations.\n\t//\n\t// These functions ensure that a conversion is never out of range, and should be always used, if at all\n\t// possible, instead of direct manipulation of the `data` member. For very large types, .slice() and\n\t// .concat() can be used to split them into more manageable parts.\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tIntegerT get() const {\n\t\tstatic_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,\n\t\t \"get<T>() requires T to be an unsigned integral type\");\n\t\tstatic_assert(std::numeric_limits<IntegerT>::digits >= Bits,\n\t\t \"get<T>() requires T to be at least as wide as the value is\");\n\t\tIntegerT result = 0;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult |= IntegerT(data[n]) << (n * chunk::bits);\n\t\treturn result;\n\t}\n\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tvoid set(IntegerT other) {\n\t\tstatic_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,\n\t\t \"set<T>() requires T to be an unsigned integral type\");\n\t\tstatic_assert(std::numeric_limits<IntegerT>::digits >= Bits,\n\t\t \"set<T>() requires the value to be at least as wide as T is\");\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tdata[n] = (other >> (n * chunk::bits)) & chunk::mask;\n\t}\n\n\t// Operations with compile-time parameters.\n\t//\n\t// These operations are used to implement slicing, concatenation, and blitting.\n\t// The trunc, zext and sext operations add or remove most significant bits (i.e. on the left);\n\t// the rtrunc and rzext operations add or remove least significant bits (i.e. on the right).\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> trunc() const {\n\t\tstatic_assert(NewBits <= Bits, \"trunc() may not increase width\");\n\t\tvalue<NewBits> result;\n\t\tfor (size_t n = 0; n < result.chunks; n++)\n\t\t\tresult.data[n] = data[n];\n\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> zext() const {\n\t\tstatic_assert(NewBits >= Bits, \"zext() may not decrease width\");\n\t\tvalue<NewBits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n];\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> sext() const {\n\t\tstatic_assert(NewBits >= Bits, \"sext() may not decrease width\");\n\t\tvalue<NewBits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n];\n\t\tif (is_neg()) {\n\t\t\tresult.data[chunks - 1] |= ~msb_mask;\n\t\t\tfor (size_t n = chunks; n < result.chunks; n++)\n\t\t\t\tresult.data[n] = chunk::mask;\n\t\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> rtrunc() const {\n\t\tstatic_assert(NewBits <= Bits, \"rtrunc() may not increase width\");\n\t\tvalue<NewBits> result;\n\t\tconstexpr size_t shift_chunks = (Bits - NewBits) / chunk::bits;\n\t\tconstexpr size_t shift_bits = (Bits - NewBits) % chunk::bits;\n\t\tchunk::type carry = 0;\n\t\tif (shift_chunks + result.chunks < chunks) {\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[shift_chunks + result.chunks] << (chunk::bits - shift_bits);\n\t\t}\n\t\tfor (size_t n = result.chunks; n > 0; n--) {\n\t\t\tresult.data[n - 1] = carry | (data[shift_chunks + n - 1] >> shift_bits);\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[shift_chunks + n - 1] << (chunk::bits - shift_bits);\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> rzext() const {\n\t\tstatic_assert(NewBits >= Bits, \"rzext() may not decrease width\");\n\t\tvalue<NewBits> result;\n\t\tconstexpr size_t shift_chunks = (NewBits - Bits) / chunk::bits;\n\t\tconstexpr size_t shift_bits = (NewBits - Bits) % chunk::bits;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tresult.data[shift_chunks + n] = (data[n] << shift_bits) | carry;\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[n] >> (chunk::bits - shift_bits);\n\t\t}\n\t\tif (shift_chunks + chunks < result.chunks)\n\t\t\tresult.data[shift_chunks + chunks] = carry;\n\t\treturn result;\n\t}\n\n\t// Bit blit operation, i.e. a partial read-modify-write.\n\ttemplate<size_t Stop, size_t Start>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<Bits> blit(const value<Stop - Start + 1> &source) const {\n\t\tstatic_assert(Stop >= Start, \"blit() may not reverse bit order\");\n\t\tconstexpr chunk::type start_mask = ~(chunk::mask << (Start % chunk::bits));\n\t\tconstexpr chunk::type stop_mask = (Stop % chunk::bits + 1 == chunk::bits) ? 0\n\t\t\t: (chunk::mask << (Stop % chunk::bits + 1));\n\t\tvalue<Bits> masked = *this;\n\t\tif (Start / chunk::bits == Stop / chunk::bits) {\n\t\t\tmasked.data[Start / chunk::bits] &= stop_mask | start_mask;\n\t\t} else {\n\t\t\tmasked.data[Start / chunk::bits] &= start_mask;\n\t\t\tfor (size_t n = Start / chunk::bits + 1; n < Stop / chunk::bits; n++)\n\t\t\t\tmasked.data[n] = 0;\n\t\t\tmasked.data[Stop / chunk::bits] &= stop_mask;\n\t\t}\n\t\tvalue<Bits> shifted = source\n\t\t\t.template rzext<Stop + 1>()\n\t\t\t.template zext<Bits>();\n\t\treturn masked.bit_or(shifted);\n\t}\n\n\t// Helpers for selecting extending or truncating operation depending on whether the result is wider or narrower\n\t// than the operand. In C++17 these can be replaced with `if constexpr`.\n\ttemplate<size_t NewBits, typename = void>\n\tstruct zext_cast {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template zext<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits>\n\tstruct zext_cast<NewBits, typename std::enable_if<(NewBits < Bits)>::type> {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template trunc<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits, typename = void>\n\tstruct sext_cast {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template sext<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits>\n\tstruct sext_cast<NewBits, typename std::enable_if<(NewBits < Bits)>::type> {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template trunc<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> zcast() const {\n\t\treturn zext_cast<NewBits>()(*this);\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> scast() const {\n\t\treturn sext_cast<NewBits>()(*this);\n\t}\n\n\t// Bit replication is far more efficient than the equivalent concatenation.\n\ttemplate<size_t Count>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<Bits * Count> repeat() const {\n\t\tstatic_assert(Bits == 1, \"repeat() is implemented only for 1-bit values\");\n\t\treturn *this ? value<Bits * Count>().bit_not() : value<Bits * Count>();\n\t}\n\n\t// Operations with run-time parameters (offsets, amounts, etc).\n\t//\n\t// These operations are used for computations.\n\tbool bit(size_t offset) const {\n\t\treturn data[offset / chunk::bits] & (1 << (offset % chunk::bits));\n\t}\n\n\tvoid set_bit(size_t offset, bool value = true) {\n\t\tsize_t offset_chunks = offset / chunk::bits;\n\t\tsize_t offset_bits = offset % chunk::bits;\n\t\tdata[offset_chunks] &= ~(1 << offset_bits);\n\t\tdata[offset_chunks] |= value ? 1 << offset_bits : 0;\n\t}\n\n\texplicit operator bool() const {\n\t\treturn !is_zero();\n\t}\n\n\tbool is_zero() const {\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tif (data[n] != 0)\n\t\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tbool is_neg() const {\n\t\treturn data[chunks - 1] & (1 << ((Bits - 1) % chunk::bits));\n\t}\n\n\tbool operator ==(const value<Bits> &other) const {\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tif (data[n] != other.data[n])\n\t\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tbool operator !=(const value<Bits> &other) const {\n\t\treturn !(*this == other);\n\t}\n\n\tvalue<Bits> bit_not() const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = ~data[n];\n\t\tresult.data[chunks - 1] &= msb_mask;\n\t\treturn result;\n\t}\n\n\tvalue<Bits> bit_and(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n] & other.data[n];\n\t\treturn result;\n\t}\n\n\tvalue<Bits> bit_or(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n] | other.data[n];\n\t\treturn result;\n\t}\n\n\tvalue<Bits> bit_xor(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n] ^ other.data[n];\n\t\treturn result;\n\t}\n\n\tvalue<Bits> update(const value<Bits> &val, const value<Bits> &mask) const {\n\t\treturn bit_and(mask.bit_not()).bit_or(val.bit_and(mask));\n\t}\n\n\ttemplate<size_t AmountBits>\n\tvalue<Bits> shl(const value<AmountBits> &amount) const {\n\t\t// Ensure our early return is correct by prohibiting values larger than 4 Gbit.\n\t\tstatic_assert(Bits <= chunk::mask, \"shl() of unreasonably large values is not supported\");\n\t\t// Detect shifts definitely large than Bits early.\n\t\tfor (size_t n = 1; n < amount.chunks; n++)\n\t\t\tif (amount.data[n] != 0)\n\t\t\t\treturn {};\n\t\t// Past this point we can use the least significant chunk as the shift size.\n\t\tsize_t shift_chunks = amount.data[0] / chunk::bits;\n\t\tsize_t shift_bits = amount.data[0] % chunk::bits;\n\t\tif (shift_chunks >= chunks)\n\t\t\treturn {};\n\t\tvalue<Bits> result;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks - shift_chunks; n++) {\n\t\t\tresult.data[shift_chunks + n] = (data[n] << shift_bits) | carry;\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[n] >> (chunk::bits - shift_bits);\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t AmountBits, bool Signed = false>\n\tvalue<Bits> shr(const value<AmountBits> &amount) const {\n\t\t// Ensure our early return is correct by prohibiting values larger than 4 Gbit.\n\t\tstatic_assert(Bits <= chunk::mask, \"shr() of unreasonably large values is not supported\");\n\t\t// Detect shifts definitely large than Bits early.\n\t\tfor (size_t n = 1; n < amount.chunks; n++)\n\t\t\tif (amount.data[n] != 0)\n\t\t\t\treturn {};\n\t\t// Past this point we can use the least significant chunk as the shift size.\n\t\tsize_t shift_chunks = amount.data[0] / chunk::bits;\n\t\tsize_t shift_bits = amount.data[0] % chunk::bits;\n\t\tif (shift_chunks >= chunks)\n\t\t\treturn {};\n\t\tvalue<Bits> result;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks - shift_chunks; n++) {\n\t\t\tresult.data[chunks - shift_chunks - 1 - n] = carry | (data[chunks - 1 - n] >> shift_bits);\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[chunks - 1 - n] << (chunk::bits - shift_bits);\n\t\t}\n\t\tif (Signed && is_neg()) {\n\t\t\tsize_t top_chunk_idx = (Bits - shift_bits) / chunk::bits;\n\t\t\tsize_t top_chunk_bits = (Bits - shift_bits) % chunk::bits;\n\t\t\tfor (size_t n = top_chunk_idx + 1; n < chunks; n++)\n\t\t\t\tresult.data[n] = chunk::mask;\n\t\t\tif (shift_bits != 0)\n\t\t\t\tresult.data[top_chunk_idx] |= chunk::mask << top_chunk_bits;\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t AmountBits>\n\tvalue<Bits> sshr(const value<AmountBits> &amount) const {\n\t\treturn shr<AmountBits, /*Signed=*/true>(amount);\n\t}\n\n\ttemplate<size_t ResultBits, size_t SelBits>\n\tvalue<ResultBits> bmux(const value<SelBits> &sel) const {\n\t\tstatic_assert(ResultBits << SelBits == Bits, \"invalid sizes used in bmux()\");\n\t\tsize_t amount = sel.data[0] * ResultBits;\n\t\tsize_t shift_chunks = amount / chunk::bits;\n\t\tsize_t shift_bits = amount % chunk::bits;\n\t\tvalue<ResultBits> result;\n\t\tchunk::type carry = 0;\n\t\tif (ResultBits % chunk::bits + shift_bits > chunk::bits)\n\t\t\tcarry = data[result.chunks + shift_chunks] << (chunk::bits - shift_bits);\n\t\tfor (size_t n = 0; n < result.chunks; n++) {\n\t\t\tresult.data[result.chunks - 1 - n] = carry | (data[result.chunks + shift_chunks - 1 - n] >> shift_bits);\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[result.chunks + shift_chunks - 1 - n] << (chunk::bits - shift_bits);\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t ResultBits, size_t SelBits>\n\tvalue<ResultBits> demux(const value<SelBits> &sel) const {\n\t\tstatic_assert(Bits << SelBits == ResultBits, \"invalid sizes used in demux()\");\n\t\tsize_t amount = sel.data[0] * Bits;\n\t\tsize_t shift_chunks = amount / chunk::bits;\n\t\tsize_t shift_bits = amount % chunk::bits;\n\t\tvalue<ResultBits> result;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tresult.data[shift_chunks + n] = (data[n] << shift_bits) | carry;\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[n] >> (chunk::bits - shift_bits);\n\t\t}\n\t\tif (Bits % chunk::bits + shift_bits > chunk::bits)\n\t\t\tresult.data[shift_chunks + chunks] = carry;\n\t\treturn result;\n\t}\n\n\tsize_t ctpop() const {\n\t\tsize_t count = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\t// This loop implements the population count idiom as recognized by LLVM and GCC.\n\t\t\tfor (chunk::type x = data[n]; x != 0; count++)\n\t\t\t\tx = x & (x - 1);\n\t\t}\n\t\treturn count;\n\t}\n\n\tsize_t ctlz() const {\n\t\tsize_t count = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tchunk::type x = data[chunks - 1 - n];\n\t\t\tif (x == 0) {\n\t\t\t\tcount += (n == 0 ? Bits % chunk::bits : chunk::bits);\n\t\t\t} else {\n\t\t\t\t// This loop implements the find first set idiom as recognized by LLVM.\n\t\t\t\tfor (; x != 0; count++)\n\t\t\t\t\tx >>= 1;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\ttemplate<bool Invert, bool CarryIn>\n\tstd::pair<value<Bits>, bool /*CarryOut*/> alu(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tbool carry = CarryIn;\n\t\tfor (size_t n = 0; n < result.chunks; n++) {\n\t\t\tresult.data[n] = data[n] + (Invert ? ~other.data[n] : other.data[n]) + carry;\n\t\t\tif (result.chunks - 1 == n)\n\t\t\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\t\tcarry = (result.data[n] < data[n]) ||\n\t\t\t (result.data[n] == data[n] && carry);\n\t\t}\n\t\treturn {result, carry};\n\t}\n\n\tvalue<Bits> add(const value<Bits> &other) const {\n\t\treturn alu</*Invert=*/false, /*CarryIn=*/false>(other).first;\n\t}\n\n\tvalue<Bits> sub(const value<Bits> &other) const {\n\t\treturn alu</*Invert=*/true, /*CarryIn=*/true>(other).first;\n\t}\n\n\tvalue<Bits> neg() const {\n\t\treturn value<Bits> { 0u }.sub(*this);\n\t}\n\n\tbool ucmp(const value<Bits> &other) const {\n\t\tbool carry;\n\t\tstd::tie(std::ignore, carry) = alu</*Invert=*/true, /*CarryIn=*/true>(other);\n\t\treturn !carry; // a.ucmp(b) ≡ a u< b\n\t}\n\n\tbool scmp(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tbool carry;\n\t\tstd::tie(result, carry) = alu</*Invert=*/true, /*CarryIn=*/true>(other);\n\t\tbool overflow = (is_neg() == !other.is_neg()) && (is_neg() != result.is_neg());\n\t\treturn result.is_neg() ^ overflow; // a.scmp(b) ≡ a s< b\n\t}\n\n\ttemplate<size_t ResultBits>\n\tvalue<ResultBits> mul(const value<Bits> &other) const {\n\t\tvalue<ResultBits> result;\n\t\twide_chunk_t wide_result[result.chunks + 1] = {};\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tfor (size_t m = 0; m < chunks && n + m < result.chunks; m++) {\n\t\t\t\twide_result[n + m] += wide_chunk_t(data[n]) * wide_chunk_t(other.data[m]);\n\t\t\t\twide_result[n + m + 1] += wide_result[n + m] >> chunk::bits;\n\t\t\t\twide_result[n + m] &= chunk::mask;\n\t\t\t}\n\t\t}\n\t\tfor (size_t n = 0; n < result.chunks; n++) {\n\t\t\tresult.data[n] = wide_result[n];\n\t\t}\n\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\treturn result;\n\t}\n\n\tstd::pair<value<Bits>, value<Bits>> udivmod(value<Bits> divisor) const {\n\t\tvalue<Bits> quotient;\n\t\tvalue<Bits> dividend = *this;\n\t\tif (dividend.ucmp(divisor))\n\t\t\treturn {/*quotient=*/value<Bits>{0u}, /*remainder=*/dividend};\n\t\tuint32_t divisor_shift = dividend.ctlz() - divisor.ctlz();\n\t\tdivisor = divisor.shl(value<Bits>{divisor_shift});\n\t\tfor (size_t step = 0; step <= divisor_shift; step++) {\n\t\t\tquotient = quotient.shl(value<Bits>{1u});\n\t\t\tif (!dividend.ucmp(divisor)) {\n\t\t\t\tdividend = dividend.sub(divisor);\n\t\t\t\tquotient.set_bit(0, true);\n\t\t\t}\n\t\t\tdivisor = divisor.shr(value<Bits>{1u});\n\t\t}\n\t\treturn {quotient, /*remainder=*/dividend};\n\t}\n\n\tstd::pair<value<Bits>, value<Bits>> sdivmod(const value<Bits> &other) const {\n\t\tvalue<Bits + 1> quotient;\n\t\tvalue<Bits + 1> remainder;\n\t\tvalue<Bits + 1> dividend = sext<Bits + 1>();\n\t\tvalue<Bits + 1> divisor = other.template sext<Bits + 1>();\n\t\tif (dividend.is_neg()) dividend = dividend.neg();\n\t\tif (divisor.is_neg()) divisor = divisor.neg();\n\t\tstd::tie(quotient, remainder) = dividend.udivmod(divisor);\n\t\tif (dividend.is_neg() != divisor.is_neg()) quotient = quotient.neg();\n\t\tif (dividend.is_neg()) remainder = remainder.neg();\n\t\treturn {quotient.template trunc<Bits>(), remainder.template trunc<Bits>()};\n\t}\n};\n\n// Expression template for a slice, usable as lvalue or rvalue, and composable with other expression templates here.\ntemplate<class T, size_t Stop, size_t Start>\nstruct slice_expr : public expr_base<slice_expr<T, Stop, Start>> {\n\tstatic_assert(Stop >= Start, \"slice_expr() may not reverse bit order\");\n\tstatic_assert(Start < T::bits && Stop < T::bits, \"slice_expr() must be within bounds\");\n\tstatic constexpr size_t bits = Stop - Start + 1;\n\n\tT &expr;\n\n\tslice_expr(T &expr) : expr(expr) {}\n\tslice_expr(const slice_expr<T, Stop, Start> &) = delete;\n\n\tCXXRTL_ALWAYS_INLINE\n\toperator value<bits>() const {\n\t\treturn static_cast<const value<T::bits> &>(expr)\n\t\t\t.template rtrunc<T::bits - Start>()\n\t\t\t.template trunc<bits>();\n\t}\n\n\tCXXRTL_ALWAYS_INLINE\n\tslice_expr<T, Stop, Start> &operator=(const value<bits> &rhs) {\n\t\t// Generic partial assignment implemented using a read-modify-write operation on the sliced expression.\n\t\texpr = static_cast<const value<T::bits> &>(expr)\n\t\t\t.template blit<Stop, Start>(rhs);\n\t\treturn *this;\n\t}\n\n\t// A helper that forces the cast to value<>, which allows deduction to work.\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<bits> val() const {\n\t\treturn static_cast<const value<bits> &>(*this);\n\t}\n};\n\n// Expression template for a concatenation, usable as lvalue or rvalue, and composable with other expression templates here.\ntemplate<class T, class U>\nstruct concat_expr : public expr_base<concat_expr<T, U>> {\n\tstatic constexpr size_t bits = T::bits + U::bits;\n\n\tT &ms_expr;\n\tU &ls_expr;\n\n\tconcat_expr(T &ms_expr, U &ls_expr) : ms_expr(ms_expr), ls_expr(ls_expr) {}\n\tconcat_expr(const concat_expr<T, U> &) = delete;\n\n\tCXXRTL_ALWAYS_INLINE\n\toperator value<bits>() const {\n\t\tvalue<bits> ms_shifted = static_cast<const value<T::bits> &>(ms_expr)\n\t\t\t.template rzext<bits>();\n\t\tvalue<bits> ls_extended = static_cast<const value<U::bits> &>(ls_expr)\n\t\t\t.template zext<bits>();\n\t\treturn ms_shifted.bit_or(ls_extended);\n\t}\n\n\tCXXRTL_ALWAYS_INLINE\n\tconcat_expr<T, U> &operator=(const value<bits> &rhs) {\n\t\tms_expr = rhs.template rtrunc<T::bits>();\n\t\tls_expr = rhs.template trunc<U::bits>();\n\t\treturn *this;\n\t}\n\n\t// A helper that forces the cast to value<>, which allows deduction to work.\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<bits> val() const {\n\t\treturn static_cast<const value<bits> &>(*this);\n\t}\n};\n\n// Base class for expression templates, providing helper methods for operations that are valid on both rvalues and lvalues.\n//\n// Note that expression objects (slices and concatenations) constructed in this way should NEVER be captured because\n// they refer to temporaries that will, in general, only live until the end of the statement. For example, both of\n// these snippets perform use-after-free:\n//\n// const auto &a = val.slice<7,0>().slice<1>();\n// value<1> b = a;\n//\n// auto &&c = val.slice<7,0>().slice<1>();\n// c = value<1>{1u};\n//\n// An easy way to write code using slices and concatenations safely is to follow two simple rules:\n// * Never explicitly name any type except `value<W>` or `const value<W> &`.\n// * Never use a `const auto &` or `auto &&` in any such expression.\n// Then, any code that compiles will be well-defined.\ntemplate<class T>\nstruct expr_base {\n\ttemplate<size_t Stop, size_t Start = Stop>\n\tCXXRTL_ALWAYS_INLINE\n\tslice_expr<const T, Stop, Start> slice() const {\n\t\treturn {*static_cast<const T *>(this)};\n\t}\n\n\ttemplate<size_t Stop, size_t Start = Stop>\n\tCXXRTL_ALWAYS_INLINE\n\tslice_expr<T, Stop, Start> slice() {\n\t\treturn {*static_cast<T *>(this)};\n\t}\n\n\ttemplate<class U>\n\tCXXRTL_ALWAYS_INLINE\n\tconcat_expr<const T, typename std::remove_reference<const U>::type> concat(const U &other) const {\n\t\treturn {*static_cast<const T *>(this), other};\n\t}\n\n\ttemplate<class U>\n\tCXXRTL_ALWAYS_INLINE\n\tconcat_expr<T, typename std::remove_reference<U>::type> concat(U &&other) {\n\t\treturn {*static_cast<T *>(this), other};\n\t}\n};\n\ntemplate<size_t Bits>\nstd::ostream &operator<<(std::ostream &os, const value<Bits> &val) {\n\tauto old_flags = os.flags(std::ios::right);\n\tauto old_width = os.width(0);\n\tauto old_fill = os.fill('0');\n\tos << val.bits << '\\'' << std::hex;\n\tfor (size_t n = val.chunks - 1; n != (size_t)-1; n--) {\n\t\tif (n == val.chunks - 1 && Bits % value<Bits>::chunk::bits != 0)\n\t\t\tos.width((Bits % value<Bits>::chunk::bits + 3) / 4);\n\t\telse\n\t\t\tos.width((value<Bits>::chunk::bits + 3) / 4);\n\t\tos << val.data[n];\n\t}\n\tos.fill(old_fill);\n\tos.width(old_width);\n\tos.flags(old_flags);\n\treturn os;\n}\n\ntemplate<size_t Bits>\nstruct value_formatted {\n\tconst value<Bits> &val;\n\tbool character;\n\tbool justify_left;\n\tchar padding;\n\tint width;\n\tint base;\n\tbool signed_;\n\tbool plus;\n\n\tvalue_formatted(const value<Bits> &val, bool character, bool justify_left, char padding, int width, int base, bool signed_, bool plus) :\n\t\tval(val), character(character), justify_left(justify_left), padding(padding), width(width), base(base), signed_(signed_), plus(plus) {}\n\tvalue_formatted(const value_formatted<Bits> &) = delete;\n\tvalue_formatted<Bits> &operator=(const value_formatted<Bits> &rhs) = delete;\n};\n\ntemplate<size_t Bits>\nstd::ostream &operator<<(std::ostream &os, const value_formatted<Bits> &vf)\n{\n\tvalue<Bits> val = vf.val;\n\n\tstd::string buf;\n\n\t// We might want to replace some of these bit() calls with direct\n\t// chunk access if it turns out to be slow enough to matter.\n\n\tif (!vf.character) {\n\t\tsize_t width = Bits;\n\t\tif (vf.base != 10) {\n\t\t\twidth = 0;\n\t\t\tfor (size_t index = 0; index < Bits; index++)\n\t\t\t\tif (val.bit(index))\n\t\t\t\t\twidth = index + 1;\n\t\t}\n\n\t\tif (vf.base == 2) {\n\t\t\tfor (size_t i = width; i > 0; i--)\n\t\t\t\tbuf += (val.bit(i - 1) ? '1' : '0');\n\t\t} else if (vf.base == 8 || vf.base == 16) {\n\t\t\tsize_t step = (vf.base == 16) ? 4 : 3;\n\t\t\tfor (size_t index = 0; index < width; index += step) {\n\t\t\t\tuint8_t value = val.bit(index) | (val.bit(index + 1) << 1) | (val.bit(index + 2) << 2);\n\t\t\t\tif (step == 4)\n\t\t\t\t\tvalue |= val.bit(index + 3) << 3;\n\t\t\t\tbuf += \"0123456789abcdef\"[value];\n\t\t\t}\n\t\t\tstd::reverse(buf.begin(), buf.end());\n\t\t} else if (vf.base == 10) {\n\t\t\tbool negative = vf.signed_ && val.is_neg();\n\t\t\tif (negative)\n\t\t\t\tval = val.neg();\n\t\t\tif (val.is_zero())\n\t\t\t\tbuf += '0';\n\t\t\twhile (!val.is_zero()) {\n\t\t\t\tvalue<Bits> quotient, remainder;\n\t\t\t\tstd::tie(quotient, remainder) = val.udivmod(value<Bits>{10u});\n\t\t\t\tbuf += '0' + remainder.template trunc<(Bits > 4 ? 4 : Bits)>().val().template get<uint8_t>();\n\t\t\t\tval = quotient;\n\t\t\t}\n\t\t\tif (negative || vf.plus)\n\t\t\t\tbuf += negative ? '-' : '+';\n\t\t\tstd::reverse(buf.begin(), buf.end());\n\t\t} else assert(false);\n\t} else {\n\t\tbuf.reserve(Bits/8);\n\t\tfor (int i = 0; i < Bits; i += 8) {\n\t\t\tchar ch = 0;\n\t\t\tfor (int j = 0; j < 8 && i + j < int(Bits); j++)\n\t\t\t\tif (val.bit(i + j))\n\t\t\t\t\tch |= 1 << j;\n\t\t\tif (ch != 0)\n\t\t\t\tbuf.append({ch});\n\t\t}\n\t\tstd::reverse(buf.begin(), buf.end());\n\t}\n\n\tassert(vf.width == 0 || vf.padding != '\\0');\n\tif (!vf.justify_left && buf.size() < vf.width) {\n\t\tsize_t pad_width = vf.width - buf.size();\n\t\tif (vf.padding == '0' && (buf.front() == '+' || buf.front() == '-')) {\n\t\t\tos << buf.front();\n\t\t\tbuf.erase(0, 1);\n\t\t}\n\t\tos << std::string(pad_width, vf.padding);\n\t}\n\tos << buf;\n\tif (vf.justify_left && buf.size() < vf.width)\n\t\tos << std::string(vf.width - buf.size(), vf.padding);\n\n\treturn os;\n}\n\ntemplate<size_t Bits>\nstruct wire {\n\tstatic constexpr size_t bits = Bits;\n\n\tvalue<Bits> curr;\n\tvalue<Bits> next;\n\n\twire() = default;\n\texplicit constexpr wire(const value<Bits> &init) : curr(init), next(init) {}\n\ttemplate<typename... Init>\n\texplicit constexpr wire(Init ...init) : curr{init...}, next{init...} {}\n\n\t// Copying and copy-assigning values is natural. If, however, a value is replaced with a wire,\n\t// e.g. because a module is built with a different optimization level, then existing code could\n\t// unintentionally copy a wire instead, which would create a subtle but serious bug. To make sure\n\t// this doesn't happen, prohibit copying and copy-assigning wires.\n\twire(const wire<Bits> &) = delete;\n\twire<Bits> &operator=(const wire<Bits> &) = delete;\n\n\twire(wire<Bits> &&) = default;\n\twire<Bits> &operator=(wire<Bits> &&) = default;\n\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tIntegerT get() const {\n\t\treturn curr.template get<IntegerT>();\n\t}\n\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tvoid set(IntegerT other) {\n\t\tnext.template set<IntegerT>(other);\n\t}\n\n\tbool commit() {\n\t\tif (curr != next) {\n\t\t\tcurr = next;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n};\n\ntemplate<size_t Bits>\nstd::ostream &operator<<(std::ostream &os, const wire<Bits> &val) {\n\tos << val.curr;\n\treturn os;\n}\n\ntemplate<size_t Width>\nstruct memory {\n\tconst size_t depth;\n\tstd::unique_ptr<value<Width>[]> data;\n\n\texplicit memory(size_t depth) : depth(depth), data(new value<Width>[depth]) {}\n\n\tmemory(const memory<Width> &) = delete;\n\tmemory<Width> &operator=(const memory<Width> &) = delete;\n\n\tmemory(memory<Width> &&) = default;\n\tmemory<Width> &operator=(memory<Width> &&other) {\n\t\tassert(depth == other.depth);\n\t\tdata = std::move(other.data);\n\t\twrite_queue = std::move(other.write_queue);\n\t\treturn *this;\n\t}\n\n\t// An operator for direct memory reads. May be used at any time during the simulation.\n\tconst value<Width> &operator [](size_t index) const {\n\t\tassert(index < depth);\n\t\treturn data[index];\n\t}\n\n\t// An operator for direct memory writes. May only be used before the simulation is started. If used\n\t// after the simulation is started, the design may malfunction.\n\tvalue<Width> &operator [](size_t index) {\n\t\tassert(index < depth);\n\t\treturn data[index];\n\t}\n\n\t// A simple way to make a writable memory would be to use an array of wires instead of an array of values.\n\t// However, there are two significant downsides to this approach: first, it has large overhead (2× space\n\t// overhead, and O(depth) time overhead during commit); second, it does not simplify handling write port\n\t// priorities. Although in principle write ports could be ordered or conditionally enabled in generated\n\t// code based on their priorities and selected addresses, the feedback arc set problem is computationally\n\t// expensive, and the heuristic based algorithms are not easily modified to guarantee (rather than prefer)\n\t// a particular write port evaluation order.\n\t//\n\t// The approach used here instead is to queue writes into a buffer during the eval phase, then perform\n\t// the writes during the commit phase in the priority order. This approach has low overhead, with both space\n\t// and time proportional to the amount of write ports. Because virtually every memory in a practical design\n\t// has at most two write ports, linear search is used on every write, being the fastest and simplest approach.\n\tstruct write {\n\t\tsize_t index;\n\t\tvalue<Width> val;\n\t\tvalue<Width> mask;\n\t\tint priority;\n\t};\n\tstd::vector<write> write_queue;\n\n\tvoid update(size_t index, const value<Width> &val, const value<Width> &mask, int priority = 0) {\n\t\tassert(index < depth);\n\t\t// Queue up the write while keeping the queue sorted by priority.\n\t\twrite_queue.insert(\n\t\t\tstd::upper_bound(write_queue.begin(), write_queue.end(), priority,\n\t\t\t\t[](const int a, const write& b) { return a < b.priority; }),\n\t\t\twrite { index, val, mask, priority });\n\t}\n\n\tbool commit() {\n\t\tbool changed = false;\n\t\tfor (const write &entry : write_queue) {\n\t\t\tvalue<Width> elem = data[entry.index];\n\t\t\telem = elem.update(entry.val, entry.mask);\n\t\t\tchanged |= (data[entry.index] != elem);\n\t\t\tdata[entry.index] = elem;\n\t\t}\n\t\twrite_queue.clear();\n\t\treturn changed;\n\t}\n};\n\nstruct metadata {\n\tconst enum {\n\t\tMISSING = 0,\n\t\tUINT \t= 1,\n\t\tSINT \t= 2,\n\t\tSTRING \t= 3,\n\t\tDOUBLE \t= 4,\n\t} value_type;\n\n\t// In debug mode, using the wrong .as_*() function will assert.\n\t// In release mode, using the wrong .as_*() function will safely return a default value.\n\tconst uint64_t uint_value = 0;\n\tconst int64_t sint_value = 0;\n\tconst std::string string_value = \"\";\n\tconst double double_value = 0.0;\n\n\tmetadata() : value_type(MISSING) {}\n\tmetadata(uint64_t value) : value_type(UINT), uint_value(value) {}\n\tmetadata(int64_t value) : value_type(SINT), sint_value(value) {}\n\tmetadata(const std::string &value) : value_type(STRING), string_value(value) {}\n\tmetadata(const char *value) : value_type(STRING), string_value(value) {}\n\tmetadata(double value) : value_type(DOUBLE), double_value(value) {}\n\n\tmetadata(const metadata &) = default;\n\tmetadata &operator=(const metadata &) = delete;\n\n\tuint64_t as_uint() const {\n\t\tassert(value_type == UINT);\n\t\treturn uint_value;\n\t}\n\n\tint64_t as_sint() const {\n\t\tassert(value_type == SINT);\n\t\treturn sint_value;\n\t}\n\n\tconst std::string &as_string() const {\n\t\tassert(value_type == STRING);\n\t\treturn string_value;\n\t}\n\n\tdouble as_double() const {\n\t\tassert(value_type == DOUBLE);\n\t\treturn double_value;\n\t}\n};\n\ntypedef std::map<std::string, metadata> metadata_map;\n\n// Tag class to disambiguate values/wires and their aliases.\nstruct debug_alias {};\n\n// Tag declaration to disambiguate values and debug outlines.\nusing debug_outline = ::_cxxrtl_outline;\n\n// This structure is intended for consumption via foreign function interfaces, like Python's ctypes.\n// Because of this it uses a C-style layout that is easy to parse rather than more idiomatic C++.\n//\n// To avoid violating strict aliasing rules, this structure has to be a subclass of the one used\n// in the C API, or it would not be possible to cast between the pointers to these.\n//\n// The `attrs` member cannot be owned by this structure because a `cxxrtl_object` can be created\n// from external C code.\nstruct debug_item : ::cxxrtl_object {\n\t// Object types.\n\tenum : uint32_t {\n\t\tVALUE = CXXRTL_VALUE,\n\t\tWIRE = CXXRTL_WIRE,\n\t\tMEMORY = CXXRTL_MEMORY,\n\t\tALIAS = CXXRTL_ALIAS,\n\t\tOUTLINE = CXXRTL_OUTLINE,\n\t};\n\n\t// Object flags.\n\tenum : uint32_t {\n\t\tINPUT = CXXRTL_INPUT,\n\t\tOUTPUT = CXXRTL_OUTPUT,\n\t\tINOUT = CXXRTL_INOUT,\n\t\tDRIVEN_SYNC = CXXRTL_DRIVEN_SYNC,\n\t\tDRIVEN_COMB = CXXRTL_DRIVEN_COMB,\n\t\tUNDRIVEN = CXXRTL_UNDRIVEN,\n\t};\n\n\tdebug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {}\n\n\ttemplate<size_t Bits>\n\tdebug_item(value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = VALUE;\n\t\tflags = flags_;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = item.data;\n\t\tnext = item.data;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(const value<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = VALUE;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.data);\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(wire<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {\n\t\tstatic_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&\n\t\t sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"wire<Bits> is not compatible with C layout\");\n\t\ttype = WIRE;\n\t\tflags = flags_;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = item.curr.data;\n\t\tnext = item.next.data;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Width>\n\tdebug_item(memory<Width> &item, size_t zero_offset = 0) {\n\t\tstatic_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t),\n\t\t \"memory<Width> is not compatible with C layout\");\n\t\ttype = MEMORY;\n\t\tflags = 0;\n\t\twidth = Width;\n\t\tlsb_at = 0;\n\t\tdepth = item.depth;\n\t\tzero_at = zero_offset;\n\t\tcurr = item.data ? item.data[0].data : nullptr;\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(debug_alias, const value<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = ALIAS;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.data);\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(debug_alias, const wire<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&\n\t\t sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"wire<Bits> is not compatible with C layout\");\n\t\ttype = ALIAS;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.curr.data);\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(debug_outline &group, const value<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = OUTLINE;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.data);\n\t\tnext = nullptr;\n\t\toutline = &group;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits, class IntegerT>\n\tIntegerT get() const {\n\t\tassert(width == Bits && depth == 1);\n\t\tvalue<Bits> item;\n\t\tstd::copy(curr, curr + value<Bits>::chunks, item.data);\n\t\treturn item.template get<IntegerT>();\n\t}\n\n\ttemplate<size_t Bits, class IntegerT>\n\tvoid set(IntegerT other) const {\n\t\tassert(width == Bits && depth == 1);\n\t\tvalue<Bits> item;\n\t\titem.template set<IntegerT>(other);\n\t\tstd::copy(item.data, item.data + value<Bits>::chunks, next);\n\t}\n};\nstatic_assert(std::is_standard_layout<debug_item>::value, \"debug_item is not compatible with C layout\");\n\n} // namespace cxxrtl\n\ntypedef struct _cxxrtl_attr_set {\n\tcxxrtl::metadata_map map;\n} *cxxrtl_attr_set;\n\nnamespace cxxrtl {\n\n// Representation of an attribute set in the C++ interface.\nusing debug_attrs = ::_cxxrtl_attr_set;\n\nstruct debug_items {\n\tstd::map<std::string, std::vector<debug_item>> table;\n\tstd::map<std::string, std::unique_ptr<debug_attrs>> attrs_table;\n\n\tvoid add(const std::string &name, debug_item &&item, metadata_map &&item_attrs = {}) {\n\t\tstd::unique_ptr<debug_attrs> &attrs = attrs_table[name];\n\t\tif (attrs.get() == nullptr)\n\t\t\tattrs = std::unique_ptr<debug_attrs>(new debug_attrs);\n\t\tfor (auto attr : item_attrs)\n\t\t\tattrs->map.insert(attr);\n\t\titem.attrs = attrs.get();\n\t\tstd::vector<debug_item> &parts = table[name];\n\t\tparts.emplace_back(item);\n\t\tstd::sort(parts.begin(), parts.end(),\n\t\t\t[](const debug_item &a, const debug_item &b) {\n\t\t\t\treturn a.lsb_at < b.lsb_at;\n\t\t\t});\n\t}\n\n\tsize_t count(const std::string &name) const {\n\t\tif (table.count(name) == 0)\n\t\t\treturn 0;\n\t\treturn table.at(name).size();\n\t}\n\n\tconst std::vector<debug_item> &parts_at(const std::string &name) const {\n\t\treturn table.at(name);\n\t}\n\n\tconst debug_item &at(const std::string &name) const {\n\t\tconst std::vector<debug_item> &parts = table.at(name);\n\t\tassert(parts.size() == 1);\n\t\treturn parts.at(0);\n\t}\n\n\tconst debug_item &operator [](const std::string &name) const {\n\t\treturn at(name);\n\t}\n\n\tconst metadata_map &attrs(const std::string &name) const {\n\t\treturn attrs_table.at(name)->map;\n\t}\n};\n\n// Tag class to disambiguate the default constructor used by the toplevel module that calls reset(),\n// and the constructor of interior modules that should not call it.\nstruct interior {};\n\nstruct module {\n\tmodule() {}\n\tvirtual ~module() {}\n\n\t// Modules with black boxes cannot be copied. Although not all designs include black boxes,\n\t// delete the copy constructor and copy assignment operator to make sure that any downstream\n\t// code that manipulates modules doesn't accidentally depend on their availability.\n\tmodule(const module &) = delete;\n\tmodule &operator=(const module &) = delete;\n\n\tmodule(module &&) = default;\n\tmodule &operator=(module &&) = default;\n\n\tvirtual void reset() = 0;\n\n\tvirtual bool eval() = 0;\n\tvirtual bool commit() = 0;\n\n\tunsigned int steps = 0;\n\n\tsize_t step() {\n\t\t++steps;\n\t\tsize_t deltas = 0;\n\t\tbool converged = false;\n\t\tdo {\n\t\t\tconverged = eval();\n\t\t\tdeltas++;\n\t\t} while (commit() && !converged);\n\t\treturn deltas;\n\t}\n\n\tvirtual void debug_info(debug_items &items, std::string path = \"\") {\n\t\t(void)items, (void)path;\n\t}\n};\n\n} // namespace cxxrtl\n\n// Internal structures used to communicate with the implementation of the C interface.\n\ntypedef struct _cxxrtl_toplevel {\n\tstd::unique_ptr<cxxrtl::module> module;\n} *cxxrtl_toplevel;\n\ntypedef struct _cxxrtl_outline {\n\tstd::function<void()> eval;\n} *cxxrtl_outline;\n\n// Definitions of internal Yosys cells. Other than the functions in this namespace, CXXRTL is fully generic\n// and indepenent of Yosys implementation details.\n//\n// The `write_cxxrtl` pass translates internal cells (cells with names that start with `$`) to calls of these\n// functions. All of Yosys arithmetic and logical cells perform sign or zero extension on their operands,\n// whereas basic operations on arbitrary width values require operands to be of the same width. These functions\n// bridge the gap by performing the necessary casts. They are named similar to `cell_A[B]`, where A and B are `u`\n// if the corresponding operand is unsigned, and `s` if it is signed.\nnamespace cxxrtl_yosys {\n\nusing namespace cxxrtl;\n\n// std::max isn't constexpr until C++14 for no particular reason (it's an oversight), so we define our own.\ntemplate<class T>\nCXXRTL_ALWAYS_INLINE\nconstexpr T max(const T &a, const T &b) {\n\treturn a > b ? a : b;\n}\n\n// Logic operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> logic_not(const value<BitsA> &a) {\n\treturn value<BitsY> { a ? 0u : 1u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> logic_and(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn value<BitsY> { (bool(a) && bool(b)) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> logic_or(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn value<BitsY> { (bool(a) || bool(b)) ? 1u : 0u };\n}\n\n// Reduction operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_and(const value<BitsA> &a) {\n\treturn value<BitsY> { a.bit_not().is_zero() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_or(const value<BitsA> &a) {\n\treturn value<BitsY> { a ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_xor(const value<BitsA> &a) {\n\treturn value<BitsY> { (a.ctpop() % 2) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_xnor(const value<BitsA> &a) {\n\treturn value<BitsY> { (a.ctpop() % 2) ? 0u : 1u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_bool(const value<BitsA> &a) {\n\treturn value<BitsY> { a ? 1u : 0u };\n}\n\n// Bitwise operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> not_u(const value<BitsA> &a) {\n\treturn a.template zcast<BitsY>().bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> not_s(const value<BitsA> &a) {\n\treturn a.template scast<BitsY>().bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> and_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_and(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> and_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_and(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> or_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_or(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> or_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_or(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_xor(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_xor(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xnor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_xor(b.template zcast<BitsY>()).bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xnor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_xor(b.template scast<BitsY>()).bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shl_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shl_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshl_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshl_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shr_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.shr(b).template zcast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shr_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.shr(b).template scast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshr_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.shr(b).template zcast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshr_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.sshr(b).template scast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shr_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shr_su<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_us(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn b.is_neg() ? shl_uu<BitsY>(a, b.template sext<BitsB + 1>().neg()) : shr_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn b.is_neg() ? shl_su<BitsY>(a, b.template sext<BitsB + 1>().neg()) : shr_su<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_su<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_us(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_us<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_ss<BitsY>(a, b);\n}\n\n// Comparison operations\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eq_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template zext<BitsExt>() == b.template zext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eq_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template sext<BitsExt>() == b.template sext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ne_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template zext<BitsExt>() != b.template zext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ne_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template sext<BitsExt>() != b.template sext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eqx_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn eq_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eqx_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn eq_ss<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> nex_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn ne_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> nex_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn ne_ss<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> gt_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { b.template zext<BitsExt>().ucmp(a.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> gt_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { b.template sext<BitsExt>().scmp(a.template sext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ge_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !a.template zext<BitsExt>().ucmp(b.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ge_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !a.template sext<BitsExt>().scmp(b.template sext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> lt_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { a.template zext<BitsExt>().ucmp(b.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> lt_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { a.template sext<BitsExt>().scmp(b.template sext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> le_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !b.template zext<BitsExt>().ucmp(a.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> le_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !b.template sext<BitsExt>().scmp(a.template sext<BitsExt>()) ? 1u : 0u };\n}\n\n// Arithmetic operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> pos_u(const value<BitsA> &a) {\n\treturn a.template zcast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> pos_s(const value<BitsA> &a) {\n\treturn a.template scast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> neg_u(const value<BitsA> &a) {\n\treturn a.template zcast<BitsY>().neg();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> neg_s(const value<BitsA> &a) {\n\treturn a.template scast<BitsY>().neg();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> add_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().add(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> add_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().add(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sub_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().sub(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sub_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().sub(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mul_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsM = BitsA >= BitsB ? BitsA : BitsB;\n\treturn a.template zcast<BitsM>().template mul<BitsY>(b.template zcast<BitsM>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mul_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().template mul<BitsY>(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nstd::pair<value<BitsY>, value<BitsY>> divmod_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t Bits = max(BitsY, max(BitsA, BitsB));\n\tvalue<Bits> quotient;\n\tvalue<Bits> remainder;\n\tvalue<Bits> dividend = a.template zext<Bits>();\n\tvalue<Bits> divisor = b.template zext<Bits>();\n\tstd::tie(quotient, remainder) = dividend.udivmod(divisor);\n\treturn {quotient.template trunc<BitsY>(), remainder.template trunc<BitsY>()};\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nstd::pair<value<BitsY>, value<BitsY>> divmod_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t Bits = max(BitsY, max(BitsA, BitsB));\n\tvalue<Bits> quotient;\n\tvalue<Bits> remainder;\n\tvalue<Bits> dividend = a.template sext<Bits>();\n\tvalue<Bits> divisor = b.template sext<Bits>();\n\tstd::tie(quotient, remainder) = dividend.sdivmod(divisor);\n\treturn {quotient.template trunc<BitsY>(), remainder.template trunc<BitsY>()};\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> div_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).first;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> div_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_ss<BitsY>(a, b).first;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mod_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).second;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mod_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_ss<BitsY>(a, b).second;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> modfloor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).second;\n}\n\n// GHDL Modfloor operator. Returns r=a mod b, such that r has the same sign as b and\n// a=b*N+r where N is some integer\n// In practical terms, when a and b have different signs and the remainder returned by divmod_ss is not 0\n// then return the remainder + b\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> modfloor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tvalue<BitsY> r;\n\tr = divmod_ss<BitsY>(a, b).second;\n\tif((b.is_neg() != a.is_neg()) && !r.is_zero())\n\t\treturn add_ss<BitsY>(b, r);\n\treturn r;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> divfloor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).first;\n}\n\n// Divfloor. Similar to above: returns q=a//b, where q has the sign of a*b and a=b*q+N.\n// In other words, returns (truncating) a/b, except if a and b have different signs\n// and there's non-zero remainder, subtract one more towards floor.\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> divfloor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tvalue<BitsY> q, r;\n\tstd::tie(q, r) = divmod_ss<BitsY>(a, b);\n\tif ((b.is_neg() != a.is_neg()) && !r.is_zero())\n\t\treturn sub_uu<BitsY>(q, value<1> { 1u });\n\treturn q;\n\n}\n\n// Memory helper\nstruct memory_index {\n\tbool valid;\n\tsize_t index;\n\n\ttemplate<size_t BitsAddr>\n\tmemory_index(const value<BitsAddr> &addr, size_t offset, size_t depth) {\n\t\tstatic_assert(value<BitsAddr>::chunks <= 1, \"memory address is too wide\");\n\t\tsize_t offset_index = addr.data[0];\n\n\t\tvalid = (offset_index >= offset && offset_index < offset + depth);\n\t\tindex = offset_index - offset;\n\t}\n};\n\n} // namespace cxxrtl_yosys\n\n#endif\n",
|
|
135
|
+
"cxxrtl.h": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2019-2020 whitequark <whitequark@whitequark.org>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n// This file is included by the designs generated with `write_cxxrtl`. It is not used in Yosys itself.\n//\n// The CXXRTL support library implements compile time specialized arbitrary width arithmetics, as well as provides\n// composite lvalues made out of bit slices and concatenations of lvalues. This allows the `write_cxxrtl` pass\n// to perform a straightforward translation of RTLIL structures to readable C++, relying on the C++ compiler\n// to unwrap the abstraction and generate efficient code.\n\n#ifndef CXXRTL_H\n#define CXXRTL_H\n\n#include <cstddef>\n#include <cstdint>\n#include <cassert>\n#include <limits>\n#include <type_traits>\n#include <tuple>\n#include <vector>\n#include <map>\n#include <algorithm>\n#include <memory>\n#include <functional>\n#include <sstream>\n\n// `cxxrtl::debug_item` has to inherit from `cxxrtl_object` to satisfy strict aliasing requirements.\n#include <cxxrtl/capi/cxxrtl_capi.h>\n\n#ifndef __has_attribute\n#\tdefine __has_attribute(x) 0\n#endif\n\n// CXXRTL essentially uses the C++ compiler as a hygienic macro engine that feeds an instruction selector.\n// It generates a lot of specialized template functions with relatively large bodies that, when inlined\n// into the caller and (for those with loops) unrolled, often expose many new optimization opportunities.\n// Because of this, most of the CXXRTL runtime must be always inlined for best performance.\n#if __has_attribute(always_inline)\n#define CXXRTL_ALWAYS_INLINE inline __attribute__((__always_inline__))\n#else\n#define CXXRTL_ALWAYS_INLINE inline\n#endif\n// Conversely, some functions in the generated code are extremely large yet very cold, with both of these\n// properties being extreme enough to confuse C++ compilers into spending pathological amounts of time\n// on a futile (the code becomes worse) attempt to optimize the least important parts of code.\n#if __has_attribute(optnone)\n#define CXXRTL_EXTREMELY_COLD __attribute__((__optnone__))\n#elif __has_attribute(optimize)\n#define CXXRTL_EXTREMELY_COLD __attribute__((__optimize__(0)))\n#else\n#define CXXRTL_EXTREMELY_COLD\n#endif\n\n// CXXRTL uses assert() to check for C++ contract violations (which may result in e.g. undefined behavior\n// of the simulation code itself), and CXXRTL_ASSERT to check for RTL contract violations (which may at\n// most result in undefined simulation results).\n//\n// Though by default, CXXRTL_ASSERT() expands to assert(), it may be overridden e.g. when integrating\n// the simulation into another process that should survive violating RTL contracts.\n#ifndef CXXRTL_ASSERT\n#ifndef CXXRTL_NDEBUG\n#define CXXRTL_ASSERT(x) assert(x)\n#else\n#define CXXRTL_ASSERT(x)\n#endif\n#endif\n\nnamespace cxxrtl {\n\n// All arbitrary-width values in CXXRTL are backed by arrays of unsigned integers called chunks. The chunk size\n// is the same regardless of the value width to simplify manipulating values via FFI interfaces, e.g. driving\n// and introspecting the simulation in Python.\n//\n// It is practical to use chunk sizes between 32 bits and platform register size because when arithmetics on\n// narrower integer types is legalized by the C++ compiler, it inserts code to clear the high bits of the register.\n// However, (a) most of our operations do not change those bits in the first place because of invariants that are\n// invisible to the compiler, (b) we often operate on non-power-of-2 values and have to clear the high bits anyway.\n// Therefore, using relatively wide chunks and clearing the high bits explicitly and only when we know they may be\n// clobbered results in simpler generated code.\ntypedef uint32_t chunk_t;\ntypedef uint64_t wide_chunk_t;\n\ntemplate<typename T>\nstruct chunk_traits {\n\tstatic_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,\n\t \"chunk type must be an unsigned integral type\");\n\tusing type = T;\n\tstatic constexpr size_t bits = std::numeric_limits<T>::digits;\n\tstatic constexpr T mask = std::numeric_limits<T>::max();\n};\n\ntemplate<class T>\nstruct expr_base;\n\ntemplate<size_t Bits>\nstruct value : public expr_base<value<Bits>> {\n\tstatic constexpr size_t bits = Bits;\n\n\tusing chunk = chunk_traits<chunk_t>;\n\tstatic constexpr chunk::type msb_mask = (Bits % chunk::bits == 0) ? chunk::mask\n\t\t: chunk::mask >> (chunk::bits - (Bits % chunk::bits));\n\n\tstatic constexpr size_t chunks = (Bits + chunk::bits - 1) / chunk::bits;\n\tchunk::type data[chunks] = {};\n\n\tvalue() = default;\n\ttemplate<typename... Init>\n\texplicit constexpr value(Init ...init) : data{init...} {}\n\n\tvalue(const value<Bits> &) = default;\n\tvalue<Bits> &operator=(const value<Bits> &) = default;\n\n\tvalue(value<Bits> &&) = default;\n\tvalue<Bits> &operator=(value<Bits> &&) = default;\n\n\t// A (no-op) helper that forces the cast to value<>.\n\tCXXRTL_ALWAYS_INLINE\n\tconst value<Bits> &val() const {\n\t\treturn *this;\n\t}\n\n\tstd::string str() const {\n\t\tstd::stringstream ss;\n\t\tss << *this;\n\t\treturn ss.str();\n\t}\n\n\t// Conversion operations.\n\t//\n\t// These functions ensure that a conversion is never out of range, and should be always used, if at all\n\t// possible, instead of direct manipulation of the `data` member. For very large types, .slice() and\n\t// .concat() can be used to split them into more manageable parts.\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tIntegerT get() const {\n\t\tstatic_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,\n\t\t \"get<T>() requires T to be an unsigned integral type\");\n\t\tstatic_assert(std::numeric_limits<IntegerT>::digits >= Bits,\n\t\t \"get<T>() requires T to be at least as wide as the value is\");\n\t\tIntegerT result = 0;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult |= IntegerT(data[n]) << (n * chunk::bits);\n\t\treturn result;\n\t}\n\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tvoid set(IntegerT other) {\n\t\tstatic_assert(std::numeric_limits<IntegerT>::is_integer && !std::numeric_limits<IntegerT>::is_signed,\n\t\t \"set<T>() requires T to be an unsigned integral type\");\n\t\tstatic_assert(std::numeric_limits<IntegerT>::digits >= Bits,\n\t\t \"set<T>() requires the value to be at least as wide as T is\");\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tdata[n] = (other >> (n * chunk::bits)) & chunk::mask;\n\t}\n\n\t// Operations with compile-time parameters.\n\t//\n\t// These operations are used to implement slicing, concatenation, and blitting.\n\t// The trunc, zext and sext operations add or remove most significant bits (i.e. on the left);\n\t// the rtrunc and rzext operations add or remove least significant bits (i.e. on the right).\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> trunc() const {\n\t\tstatic_assert(NewBits <= Bits, \"trunc() may not increase width\");\n\t\tvalue<NewBits> result;\n\t\tfor (size_t n = 0; n < result.chunks; n++)\n\t\t\tresult.data[n] = data[n];\n\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> zext() const {\n\t\tstatic_assert(NewBits >= Bits, \"zext() may not decrease width\");\n\t\tvalue<NewBits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n];\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> sext() const {\n\t\tstatic_assert(NewBits >= Bits, \"sext() may not decrease width\");\n\t\tvalue<NewBits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n];\n\t\tif (is_neg()) {\n\t\t\tresult.data[chunks - 1] |= ~msb_mask;\n\t\t\tfor (size_t n = chunks; n < result.chunks; n++)\n\t\t\t\tresult.data[n] = chunk::mask;\n\t\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> rtrunc() const {\n\t\tstatic_assert(NewBits <= Bits, \"rtrunc() may not increase width\");\n\t\tvalue<NewBits> result;\n\t\tconstexpr size_t shift_chunks = (Bits - NewBits) / chunk::bits;\n\t\tconstexpr size_t shift_bits = (Bits - NewBits) % chunk::bits;\n\t\tchunk::type carry = 0;\n\t\tif (shift_chunks + result.chunks < chunks) {\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[shift_chunks + result.chunks] << (chunk::bits - shift_bits);\n\t\t}\n\t\tfor (size_t n = result.chunks; n > 0; n--) {\n\t\t\tresult.data[n - 1] = carry | (data[shift_chunks + n - 1] >> shift_bits);\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[shift_chunks + n - 1] << (chunk::bits - shift_bits);\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> rzext() const {\n\t\tstatic_assert(NewBits >= Bits, \"rzext() may not decrease width\");\n\t\tvalue<NewBits> result;\n\t\tconstexpr size_t shift_chunks = (NewBits - Bits) / chunk::bits;\n\t\tconstexpr size_t shift_bits = (NewBits - Bits) % chunk::bits;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tresult.data[shift_chunks + n] = (data[n] << shift_bits) | carry;\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[n] >> (chunk::bits - shift_bits);\n\t\t}\n\t\tif (shift_chunks + chunks < result.chunks)\n\t\t\tresult.data[shift_chunks + chunks] = carry;\n\t\treturn result;\n\t}\n\n\t// Bit blit operation, i.e. a partial read-modify-write.\n\ttemplate<size_t Stop, size_t Start>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<Bits> blit(const value<Stop - Start + 1> &source) const {\n\t\tstatic_assert(Stop >= Start, \"blit() may not reverse bit order\");\n\t\tconstexpr chunk::type start_mask = ~(chunk::mask << (Start % chunk::bits));\n\t\tconstexpr chunk::type stop_mask = (Stop % chunk::bits + 1 == chunk::bits) ? 0\n\t\t\t: (chunk::mask << (Stop % chunk::bits + 1));\n\t\tvalue<Bits> masked = *this;\n\t\tif (Start / chunk::bits == Stop / chunk::bits) {\n\t\t\tmasked.data[Start / chunk::bits] &= stop_mask | start_mask;\n\t\t} else {\n\t\t\tmasked.data[Start / chunk::bits] &= start_mask;\n\t\t\tfor (size_t n = Start / chunk::bits + 1; n < Stop / chunk::bits; n++)\n\t\t\t\tmasked.data[n] = 0;\n\t\t\tmasked.data[Stop / chunk::bits] &= stop_mask;\n\t\t}\n\t\tvalue<Bits> shifted = source\n\t\t\t.template rzext<Stop + 1>()\n\t\t\t.template zext<Bits>();\n\t\treturn masked.bit_or(shifted);\n\t}\n\n\t// Helpers for selecting extending or truncating operation depending on whether the result is wider or narrower\n\t// than the operand. In C++17 these can be replaced with `if constexpr`.\n\ttemplate<size_t NewBits, typename = void>\n\tstruct zext_cast {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template zext<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits>\n\tstruct zext_cast<NewBits, typename std::enable_if<(NewBits < Bits)>::type> {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template trunc<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits, typename = void>\n\tstruct sext_cast {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template sext<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits>\n\tstruct sext_cast<NewBits, typename std::enable_if<(NewBits < Bits)>::type> {\n\t\tCXXRTL_ALWAYS_INLINE\n\t\tvalue<NewBits> operator()(const value<Bits> &val) {\n\t\t\treturn val.template trunc<NewBits>();\n\t\t}\n\t};\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> zcast() const {\n\t\treturn zext_cast<NewBits>()(*this);\n\t}\n\n\ttemplate<size_t NewBits>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<NewBits> scast() const {\n\t\treturn sext_cast<NewBits>()(*this);\n\t}\n\n\t// Bit replication is far more efficient than the equivalent concatenation.\n\ttemplate<size_t Count>\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<Bits * Count> repeat() const {\n\t\tstatic_assert(Bits == 1, \"repeat() is implemented only for 1-bit values\");\n\t\treturn *this ? value<Bits * Count>().bit_not() : value<Bits * Count>();\n\t}\n\n\t// Operations with run-time parameters (offsets, amounts, etc).\n\t//\n\t// These operations are used for computations.\n\tbool bit(size_t offset) const {\n\t\treturn data[offset / chunk::bits] & (1 << (offset % chunk::bits));\n\t}\n\n\tvoid set_bit(size_t offset, bool value = true) {\n\t\tsize_t offset_chunks = offset / chunk::bits;\n\t\tsize_t offset_bits = offset % chunk::bits;\n\t\tdata[offset_chunks] &= ~(1 << offset_bits);\n\t\tdata[offset_chunks] |= value ? 1 << offset_bits : 0;\n\t}\n\n\texplicit operator bool() const {\n\t\treturn !is_zero();\n\t}\n\n\tbool is_zero() const {\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tif (data[n] != 0)\n\t\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tbool is_neg() const {\n\t\treturn data[chunks - 1] & (1 << ((Bits - 1) % chunk::bits));\n\t}\n\n\tbool operator ==(const value<Bits> &other) const {\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tif (data[n] != other.data[n])\n\t\t\t\treturn false;\n\t\treturn true;\n\t}\n\n\tbool operator !=(const value<Bits> &other) const {\n\t\treturn !(*this == other);\n\t}\n\n\tvalue<Bits> bit_not() const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = ~data[n];\n\t\tresult.data[chunks - 1] &= msb_mask;\n\t\treturn result;\n\t}\n\n\tvalue<Bits> bit_and(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n] & other.data[n];\n\t\treturn result;\n\t}\n\n\tvalue<Bits> bit_or(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n] | other.data[n];\n\t\treturn result;\n\t}\n\n\tvalue<Bits> bit_xor(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tfor (size_t n = 0; n < chunks; n++)\n\t\t\tresult.data[n] = data[n] ^ other.data[n];\n\t\treturn result;\n\t}\n\n\tvalue<Bits> update(const value<Bits> &val, const value<Bits> &mask) const {\n\t\treturn bit_and(mask.bit_not()).bit_or(val.bit_and(mask));\n\t}\n\n\ttemplate<size_t AmountBits>\n\tvalue<Bits> shl(const value<AmountBits> &amount) const {\n\t\t// Ensure our early return is correct by prohibiting values larger than 4 Gbit.\n\t\tstatic_assert(Bits <= chunk::mask, \"shl() of unreasonably large values is not supported\");\n\t\t// Detect shifts definitely large than Bits early.\n\t\tfor (size_t n = 1; n < amount.chunks; n++)\n\t\t\tif (amount.data[n] != 0)\n\t\t\t\treturn {};\n\t\t// Past this point we can use the least significant chunk as the shift size.\n\t\tsize_t shift_chunks = amount.data[0] / chunk::bits;\n\t\tsize_t shift_bits = amount.data[0] % chunk::bits;\n\t\tif (shift_chunks >= chunks)\n\t\t\treturn {};\n\t\tvalue<Bits> result;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks - shift_chunks; n++) {\n\t\t\tresult.data[shift_chunks + n] = (data[n] << shift_bits) | carry;\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[n] >> (chunk::bits - shift_bits);\n\t\t}\n\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\treturn result;\n\t}\n\n\ttemplate<size_t AmountBits, bool Signed = false>\n\tvalue<Bits> shr(const value<AmountBits> &amount) const {\n\t\t// Ensure our early return is correct by prohibiting values larger than 4 Gbit.\n\t\tstatic_assert(Bits <= chunk::mask, \"shr() of unreasonably large values is not supported\");\n\t\t// Detect shifts definitely large than Bits early.\n\t\tfor (size_t n = 1; n < amount.chunks; n++)\n\t\t\tif (amount.data[n] != 0)\n\t\t\t\treturn (Signed && is_neg()) ? value<Bits>().bit_not() : value<Bits>();\n\t\t// Past this point we can use the least significant chunk as the shift size.\n\t\tsize_t shift_chunks = amount.data[0] / chunk::bits;\n\t\tsize_t shift_bits = amount.data[0] % chunk::bits;\n\t\tif (shift_chunks >= chunks)\n\t\t\treturn (Signed && is_neg()) ? value<Bits>().bit_not() : value<Bits>();\n\t\tvalue<Bits> result;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks - shift_chunks; n++) {\n\t\t\tresult.data[chunks - shift_chunks - 1 - n] = carry | (data[chunks - 1 - n] >> shift_bits);\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[chunks - 1 - n] << (chunk::bits - shift_bits);\n\t\t}\n\t\tif (Signed && is_neg()) {\n\t\t\tsize_t top_chunk_idx = amount.data[0] > Bits ? 0 : (Bits - amount.data[0]) / chunk::bits;\n\t\t\tsize_t top_chunk_bits = amount.data[0] > Bits ? 0 : (Bits - amount.data[0]) % chunk::bits;\n\t\t\tfor (size_t n = top_chunk_idx + 1; n < chunks; n++)\n\t\t\t\tresult.data[n] = chunk::mask;\n\t\t\tif (amount.data[0] != 0)\n\t\t\t\tresult.data[top_chunk_idx] |= chunk::mask << top_chunk_bits;\n\t\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\t}\n\t\treturn result;\n\t}\n\n\ttemplate<size_t AmountBits>\n\tvalue<Bits> sshr(const value<AmountBits> &amount) const {\n\t\treturn shr<AmountBits, /*Signed=*/true>(amount);\n\t}\n\n\ttemplate<size_t ResultBits, size_t SelBits>\n\tvalue<ResultBits> bmux(const value<SelBits> &sel) const {\n\t\tstatic_assert(ResultBits << SelBits == Bits, \"invalid sizes used in bmux()\");\n\t\tsize_t amount = sel.data[0] * ResultBits;\n\t\tsize_t shift_chunks = amount / chunk::bits;\n\t\tsize_t shift_bits = amount % chunk::bits;\n\t\tvalue<ResultBits> result;\n\t\tchunk::type carry = 0;\n\t\tif (ResultBits % chunk::bits + shift_bits > chunk::bits)\n\t\t\tcarry = data[result.chunks + shift_chunks] << (chunk::bits - shift_bits);\n\t\tfor (size_t n = 0; n < result.chunks; n++) {\n\t\t\tresult.data[result.chunks - 1 - n] = carry | (data[result.chunks + shift_chunks - 1 - n] >> shift_bits);\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[result.chunks + shift_chunks - 1 - n] << (chunk::bits - shift_bits);\n\t\t}\n\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\treturn result;\n\t}\n\n\ttemplate<size_t ResultBits, size_t SelBits>\n\tvalue<ResultBits> demux(const value<SelBits> &sel) const {\n\t\tstatic_assert(Bits << SelBits == ResultBits, \"invalid sizes used in demux()\");\n\t\tsize_t amount = sel.data[0] * Bits;\n\t\tsize_t shift_chunks = amount / chunk::bits;\n\t\tsize_t shift_bits = amount % chunk::bits;\n\t\tvalue<ResultBits> result;\n\t\tchunk::type carry = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tresult.data[shift_chunks + n] = (data[n] << shift_bits) | carry;\n\t\t\tcarry = (shift_bits == 0) ? 0\n\t\t\t\t: data[n] >> (chunk::bits - shift_bits);\n\t\t}\n\t\tif (Bits % chunk::bits + shift_bits > chunk::bits)\n\t\t\tresult.data[shift_chunks + chunks] = carry;\n\t\treturn result;\n\t}\n\n\tsize_t ctpop() const {\n\t\tsize_t count = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\t// This loop implements the population count idiom as recognized by LLVM and GCC.\n\t\t\tfor (chunk::type x = data[n]; x != 0; count++)\n\t\t\t\tx = x & (x - 1);\n\t\t}\n\t\treturn count;\n\t}\n\n\tsize_t ctlz() const {\n\t\tsize_t count = 0;\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tchunk::type x = data[chunks - 1 - n];\n\t\t\t// First add to `count` as if the chunk is zero\n\t\t\tconstexpr size_t msb_chunk_bits = Bits % chunk::bits != 0 ? Bits % chunk::bits : chunk::bits;\n\t\t\tcount += (n == 0 ? msb_chunk_bits : chunk::bits);\n\t\t\t// If the chunk isn't zero, correct the `count` value and return\n\t\t\tif (x != 0) {\n\t\t\t\tfor (; x != 0; count--)\n\t\t\t\t\tx >>= 1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\ttemplate<bool Invert, bool CarryIn>\n\tstd::pair<value<Bits>, bool /*CarryOut*/> alu(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tbool carry = CarryIn;\n\t\tfor (size_t n = 0; n < result.chunks; n++) {\n\t\t\tresult.data[n] = data[n] + (Invert ? ~other.data[n] : other.data[n]) + carry;\n\t\t\tif (result.chunks - 1 == n)\n\t\t\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\t\tcarry = (result.data[n] < data[n]) ||\n\t\t\t (result.data[n] == data[n] && carry);\n\t\t}\n\t\treturn {result, carry};\n\t}\n\n\tvalue<Bits> add(const value<Bits> &other) const {\n\t\treturn alu</*Invert=*/false, /*CarryIn=*/false>(other).first;\n\t}\n\n\tvalue<Bits> sub(const value<Bits> &other) const {\n\t\treturn alu</*Invert=*/true, /*CarryIn=*/true>(other).first;\n\t}\n\n\tvalue<Bits> neg() const {\n\t\treturn value<Bits> { 0u }.sub(*this);\n\t}\n\n\tbool ucmp(const value<Bits> &other) const {\n\t\tbool carry;\n\t\tstd::tie(std::ignore, carry) = alu</*Invert=*/true, /*CarryIn=*/true>(other);\n\t\treturn !carry; // a.ucmp(b) ≡ a u< b\n\t}\n\n\tbool scmp(const value<Bits> &other) const {\n\t\tvalue<Bits> result;\n\t\tbool carry;\n\t\tstd::tie(result, carry) = alu</*Invert=*/true, /*CarryIn=*/true>(other);\n\t\tbool overflow = (is_neg() == !other.is_neg()) && (is_neg() != result.is_neg());\n\t\treturn result.is_neg() ^ overflow; // a.scmp(b) ≡ a s< b\n\t}\n\n\ttemplate<size_t ResultBits>\n\tvalue<ResultBits> mul(const value<Bits> &other) const {\n\t\tvalue<ResultBits> result;\n\t\twide_chunk_t wide_result[result.chunks + 1] = {};\n\t\tfor (size_t n = 0; n < chunks; n++) {\n\t\t\tfor (size_t m = 0; m < chunks && n + m < result.chunks; m++) {\n\t\t\t\twide_result[n + m] += wide_chunk_t(data[n]) * wide_chunk_t(other.data[m]);\n\t\t\t\twide_result[n + m + 1] += wide_result[n + m] >> chunk::bits;\n\t\t\t\twide_result[n + m] &= chunk::mask;\n\t\t\t}\n\t\t}\n\t\tfor (size_t n = 0; n < result.chunks; n++) {\n\t\t\tresult.data[n] = wide_result[n];\n\t\t}\n\t\tresult.data[result.chunks - 1] &= result.msb_mask;\n\t\treturn result;\n\t}\n\n\tstd::pair<value<Bits>, value<Bits>> udivmod(value<Bits> divisor) const {\n\t\tvalue<Bits> quotient;\n\t\tvalue<Bits> dividend = *this;\n\t\tif (dividend.ucmp(divisor))\n\t\t\treturn {/*quotient=*/value<Bits>{0u}, /*remainder=*/dividend};\n\t\tint64_t divisor_shift = divisor.ctlz() - dividend.ctlz();\n\t\tassert(divisor_shift >= 0);\n\t\tdivisor = divisor.shl(value<Bits>{(chunk::type) divisor_shift});\n\t\tfor (size_t step = 0; step <= divisor_shift; step++) {\n\t\t\tquotient = quotient.shl(value<Bits>{1u});\n\t\t\tif (!dividend.ucmp(divisor)) {\n\t\t\t\tdividend = dividend.sub(divisor);\n\t\t\t\tquotient.set_bit(0, true);\n\t\t\t}\n\t\t\tdivisor = divisor.shr(value<Bits>{1u});\n\t\t}\n\t\treturn {quotient, /*remainder=*/dividend};\n\t}\n\n\tstd::pair<value<Bits>, value<Bits>> sdivmod(const value<Bits> &other) const {\n\t\tvalue<Bits + 1> quotient;\n\t\tvalue<Bits + 1> remainder;\n\t\tvalue<Bits + 1> dividend = sext<Bits + 1>();\n\t\tvalue<Bits + 1> divisor = other.template sext<Bits + 1>();\n\t\tif (dividend.is_neg()) dividend = dividend.neg();\n\t\tif (divisor.is_neg()) divisor = divisor.neg();\n\t\tstd::tie(quotient, remainder) = dividend.udivmod(divisor);\n\t\tif (dividend.is_neg() != divisor.is_neg()) quotient = quotient.neg();\n\t\tif (dividend.is_neg()) remainder = remainder.neg();\n\t\treturn {quotient.template trunc<Bits>(), remainder.template trunc<Bits>()};\n\t}\n};\n\n// Expression template for a slice, usable as lvalue or rvalue, and composable with other expression templates here.\ntemplate<class T, size_t Stop, size_t Start>\nstruct slice_expr : public expr_base<slice_expr<T, Stop, Start>> {\n\tstatic_assert(Stop >= Start, \"slice_expr() may not reverse bit order\");\n\tstatic_assert(Start < T::bits && Stop < T::bits, \"slice_expr() must be within bounds\");\n\tstatic constexpr size_t bits = Stop - Start + 1;\n\n\tT &expr;\n\n\tslice_expr(T &expr) : expr(expr) {}\n\tslice_expr(const slice_expr<T, Stop, Start> &) = delete;\n\n\tCXXRTL_ALWAYS_INLINE\n\toperator value<bits>() const {\n\t\treturn static_cast<const value<T::bits> &>(expr)\n\t\t\t.template rtrunc<T::bits - Start>()\n\t\t\t.template trunc<bits>();\n\t}\n\n\tCXXRTL_ALWAYS_INLINE\n\tslice_expr<T, Stop, Start> &operator=(const value<bits> &rhs) {\n\t\t// Generic partial assignment implemented using a read-modify-write operation on the sliced expression.\n\t\texpr = static_cast<const value<T::bits> &>(expr)\n\t\t\t.template blit<Stop, Start>(rhs);\n\t\treturn *this;\n\t}\n\n\t// A helper that forces the cast to value<>, which allows deduction to work.\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<bits> val() const {\n\t\treturn static_cast<const value<bits> &>(*this);\n\t}\n};\n\n// Expression template for a concatenation, usable as lvalue or rvalue, and composable with other expression templates here.\ntemplate<class T, class U>\nstruct concat_expr : public expr_base<concat_expr<T, U>> {\n\tstatic constexpr size_t bits = T::bits + U::bits;\n\n\tT &ms_expr;\n\tU &ls_expr;\n\n\tconcat_expr(T &ms_expr, U &ls_expr) : ms_expr(ms_expr), ls_expr(ls_expr) {}\n\tconcat_expr(const concat_expr<T, U> &) = delete;\n\n\tCXXRTL_ALWAYS_INLINE\n\toperator value<bits>() const {\n\t\tvalue<bits> ms_shifted = static_cast<const value<T::bits> &>(ms_expr)\n\t\t\t.template rzext<bits>();\n\t\tvalue<bits> ls_extended = static_cast<const value<U::bits> &>(ls_expr)\n\t\t\t.template zext<bits>();\n\t\treturn ms_shifted.bit_or(ls_extended);\n\t}\n\n\tCXXRTL_ALWAYS_INLINE\n\tconcat_expr<T, U> &operator=(const value<bits> &rhs) {\n\t\tms_expr = rhs.template rtrunc<T::bits>();\n\t\tls_expr = rhs.template trunc<U::bits>();\n\t\treturn *this;\n\t}\n\n\t// A helper that forces the cast to value<>, which allows deduction to work.\n\tCXXRTL_ALWAYS_INLINE\n\tvalue<bits> val() const {\n\t\treturn static_cast<const value<bits> &>(*this);\n\t}\n};\n\n// Base class for expression templates, providing helper methods for operations that are valid on both rvalues and lvalues.\n//\n// Note that expression objects (slices and concatenations) constructed in this way should NEVER be captured because\n// they refer to temporaries that will, in general, only live until the end of the statement. For example, both of\n// these snippets perform use-after-free:\n//\n// const auto &a = val.slice<7,0>().slice<1>();\n// value<1> b = a;\n//\n// auto &&c = val.slice<7,0>().slice<1>();\n// c = value<1>{1u};\n//\n// An easy way to write code using slices and concatenations safely is to follow two simple rules:\n// * Never explicitly name any type except `value<W>` or `const value<W> &`.\n// * Never use a `const auto &` or `auto &&` in any such expression.\n// Then, any code that compiles will be well-defined.\ntemplate<class T>\nstruct expr_base {\n\ttemplate<size_t Stop, size_t Start = Stop>\n\tCXXRTL_ALWAYS_INLINE\n\tslice_expr<const T, Stop, Start> slice() const {\n\t\treturn {*static_cast<const T *>(this)};\n\t}\n\n\ttemplate<size_t Stop, size_t Start = Stop>\n\tCXXRTL_ALWAYS_INLINE\n\tslice_expr<T, Stop, Start> slice() {\n\t\treturn {*static_cast<T *>(this)};\n\t}\n\n\ttemplate<class U>\n\tCXXRTL_ALWAYS_INLINE\n\tconcat_expr<const T, typename std::remove_reference<const U>::type> concat(const U &other) const {\n\t\treturn {*static_cast<const T *>(this), other};\n\t}\n\n\ttemplate<class U>\n\tCXXRTL_ALWAYS_INLINE\n\tconcat_expr<T, typename std::remove_reference<U>::type> concat(U &&other) {\n\t\treturn {*static_cast<T *>(this), other};\n\t}\n};\n\ntemplate<size_t Bits>\nstd::ostream &operator<<(std::ostream &os, const value<Bits> &val) {\n\tauto old_flags = os.flags(std::ios::right);\n\tauto old_width = os.width(0);\n\tauto old_fill = os.fill('0');\n\tos << val.bits << '\\'' << std::hex;\n\tfor (size_t n = val.chunks - 1; n != (size_t)-1; n--) {\n\t\tif (n == val.chunks - 1 && Bits % value<Bits>::chunk::bits != 0)\n\t\t\tos.width((Bits % value<Bits>::chunk::bits + 3) / 4);\n\t\telse\n\t\t\tos.width((value<Bits>::chunk::bits + 3) / 4);\n\t\tos << val.data[n];\n\t}\n\tos.fill(old_fill);\n\tos.width(old_width);\n\tos.flags(old_flags);\n\treturn os;\n}\n\ntemplate<size_t Bits>\nstruct value_formatted {\n\tconst value<Bits> &val;\n\tbool character;\n\tbool justify_left;\n\tchar padding;\n\tint width;\n\tint base;\n\tbool signed_;\n\tbool plus;\n\n\tvalue_formatted(const value<Bits> &val, bool character, bool justify_left, char padding, int width, int base, bool signed_, bool plus) :\n\t\tval(val), character(character), justify_left(justify_left), padding(padding), width(width), base(base), signed_(signed_), plus(plus) {}\n\tvalue_formatted(const value_formatted<Bits> &) = delete;\n\tvalue_formatted<Bits> &operator=(const value_formatted<Bits> &rhs) = delete;\n};\n\ntemplate<size_t Bits>\nstd::ostream &operator<<(std::ostream &os, const value_formatted<Bits> &vf)\n{\n\tvalue<Bits> val = vf.val;\n\n\tstd::string buf;\n\n\t// We might want to replace some of these bit() calls with direct\n\t// chunk access if it turns out to be slow enough to matter.\n\n\tif (!vf.character) {\n\t\tsize_t width = Bits;\n\t\tif (vf.base != 10) {\n\t\t\twidth = 0;\n\t\t\tfor (size_t index = 0; index < Bits; index++)\n\t\t\t\tif (val.bit(index))\n\t\t\t\t\twidth = index + 1;\n\t\t}\n\n\t\tif (vf.base == 2) {\n\t\t\tfor (size_t i = width; i > 0; i--)\n\t\t\t\tbuf += (val.bit(i - 1) ? '1' : '0');\n\t\t} else if (vf.base == 8 || vf.base == 16) {\n\t\t\tsize_t step = (vf.base == 16) ? 4 : 3;\n\t\t\tfor (size_t index = 0; index < width; index += step) {\n\t\t\t\tuint8_t value = val.bit(index) | (val.bit(index + 1) << 1) | (val.bit(index + 2) << 2);\n\t\t\t\tif (step == 4)\n\t\t\t\t\tvalue |= val.bit(index + 3) << 3;\n\t\t\t\tbuf += \"0123456789abcdef\"[value];\n\t\t\t}\n\t\t\tstd::reverse(buf.begin(), buf.end());\n\t\t} else if (vf.base == 10) {\n\t\t\tbool negative = vf.signed_ && val.is_neg();\n\t\t\tif (negative)\n\t\t\t\tval = val.neg();\n\t\t\tif (val.is_zero())\n\t\t\t\tbuf += '0';\n\t\t\twhile (!val.is_zero()) {\n\t\t\t\tvalue<Bits> quotient, remainder;\n\t\t\t\tif (Bits >= 4)\n\t\t\t\t\tstd::tie(quotient, remainder) = val.udivmod(value<Bits>{10u});\n\t\t\t\telse\n\t\t\t\t\tstd::tie(quotient, remainder) = std::make_pair(value<Bits>{0u}, val);\n\t\t\t\tbuf += '0' + remainder.template trunc<(Bits > 4 ? 4 : Bits)>().val().template get<uint8_t>();\n\t\t\t\tval = quotient;\n\t\t\t}\n\t\t\tif (negative || vf.plus)\n\t\t\t\tbuf += negative ? '-' : '+';\n\t\t\tstd::reverse(buf.begin(), buf.end());\n\t\t} else assert(false);\n\t} else {\n\t\tbuf.reserve(Bits/8);\n\t\tfor (int i = 0; i < Bits; i += 8) {\n\t\t\tchar ch = 0;\n\t\t\tfor (int j = 0; j < 8 && i + j < int(Bits); j++)\n\t\t\t\tif (val.bit(i + j))\n\t\t\t\t\tch |= 1 << j;\n\t\t\tif (ch != 0)\n\t\t\t\tbuf.append({ch});\n\t\t}\n\t\tstd::reverse(buf.begin(), buf.end());\n\t}\n\n\tassert(vf.width == 0 || vf.padding != '\\0');\n\tif (!vf.justify_left && buf.size() < vf.width) {\n\t\tsize_t pad_width = vf.width - buf.size();\n\t\tif (vf.padding == '0' && (buf.front() == '+' || buf.front() == '-')) {\n\t\t\tos << buf.front();\n\t\t\tbuf.erase(0, 1);\n\t\t}\n\t\tos << std::string(pad_width, vf.padding);\n\t}\n\tos << buf;\n\tif (vf.justify_left && buf.size() < vf.width)\n\t\tos << std::string(vf.width - buf.size(), vf.padding);\n\n\treturn os;\n}\n\ntemplate<size_t Bits>\nstruct wire {\n\tstatic constexpr size_t bits = Bits;\n\n\tvalue<Bits> curr;\n\tvalue<Bits> next;\n\n\twire() = default;\n\texplicit constexpr wire(const value<Bits> &init) : curr(init), next(init) {}\n\ttemplate<typename... Init>\n\texplicit constexpr wire(Init ...init) : curr{init...}, next{init...} {}\n\n\t// Copying and copy-assigning values is natural. If, however, a value is replaced with a wire,\n\t// e.g. because a module is built with a different optimization level, then existing code could\n\t// unintentionally copy a wire instead, which would create a subtle but serious bug. To make sure\n\t// this doesn't happen, prohibit copying and copy-assigning wires.\n\twire(const wire<Bits> &) = delete;\n\twire<Bits> &operator=(const wire<Bits> &) = delete;\n\n\twire(wire<Bits> &&) = default;\n\twire<Bits> &operator=(wire<Bits> &&) = default;\n\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tIntegerT get() const {\n\t\treturn curr.template get<IntegerT>();\n\t}\n\n\ttemplate<class IntegerT>\n\tCXXRTL_ALWAYS_INLINE\n\tvoid set(IntegerT other) {\n\t\tnext.template set<IntegerT>(other);\n\t}\n\n\tbool commit() {\n\t\tif (curr != next) {\n\t\t\tcurr = next;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n};\n\ntemplate<size_t Bits>\nstd::ostream &operator<<(std::ostream &os, const wire<Bits> &val) {\n\tos << val.curr;\n\treturn os;\n}\n\ntemplate<size_t Width>\nstruct memory {\n\tconst size_t depth;\n\tstd::unique_ptr<value<Width>[]> data;\n\n\texplicit memory(size_t depth) : depth(depth), data(new value<Width>[depth]) {}\n\n\tmemory(const memory<Width> &) = delete;\n\tmemory<Width> &operator=(const memory<Width> &) = delete;\n\n\tmemory(memory<Width> &&) = default;\n\tmemory<Width> &operator=(memory<Width> &&other) {\n\t\tassert(depth == other.depth);\n\t\tdata = std::move(other.data);\n\t\twrite_queue = std::move(other.write_queue);\n\t\treturn *this;\n\t}\n\n\t// An operator for direct memory reads. May be used at any time during the simulation.\n\tconst value<Width> &operator [](size_t index) const {\n\t\tassert(index < depth);\n\t\treturn data[index];\n\t}\n\n\t// An operator for direct memory writes. May only be used before the simulation is started. If used\n\t// after the simulation is started, the design may malfunction.\n\tvalue<Width> &operator [](size_t index) {\n\t\tassert(index < depth);\n\t\treturn data[index];\n\t}\n\n\t// A simple way to make a writable memory would be to use an array of wires instead of an array of values.\n\t// However, there are two significant downsides to this approach: first, it has large overhead (2× space\n\t// overhead, and O(depth) time overhead during commit); second, it does not simplify handling write port\n\t// priorities. Although in principle write ports could be ordered or conditionally enabled in generated\n\t// code based on their priorities and selected addresses, the feedback arc set problem is computationally\n\t// expensive, and the heuristic based algorithms are not easily modified to guarantee (rather than prefer)\n\t// a particular write port evaluation order.\n\t//\n\t// The approach used here instead is to queue writes into a buffer during the eval phase, then perform\n\t// the writes during the commit phase in the priority order. This approach has low overhead, with both space\n\t// and time proportional to the amount of write ports. Because virtually every memory in a practical design\n\t// has at most two write ports, linear search is used on every write, being the fastest and simplest approach.\n\tstruct write {\n\t\tsize_t index;\n\t\tvalue<Width> val;\n\t\tvalue<Width> mask;\n\t\tint priority;\n\t};\n\tstd::vector<write> write_queue;\n\n\tvoid update(size_t index, const value<Width> &val, const value<Width> &mask, int priority = 0) {\n\t\tassert(index < depth);\n\t\t// Queue up the write while keeping the queue sorted by priority.\n\t\twrite_queue.insert(\n\t\t\tstd::upper_bound(write_queue.begin(), write_queue.end(), priority,\n\t\t\t\t[](const int a, const write& b) { return a < b.priority; }),\n\t\t\twrite { index, val, mask, priority });\n\t}\n\n\tbool commit() {\n\t\tbool changed = false;\n\t\tfor (const write &entry : write_queue) {\n\t\t\tvalue<Width> elem = data[entry.index];\n\t\t\telem = elem.update(entry.val, entry.mask);\n\t\t\tchanged |= (data[entry.index] != elem);\n\t\t\tdata[entry.index] = elem;\n\t\t}\n\t\twrite_queue.clear();\n\t\treturn changed;\n\t}\n};\n\nstruct metadata {\n\tconst enum {\n\t\tMISSING = 0,\n\t\tUINT \t= 1,\n\t\tSINT \t= 2,\n\t\tSTRING \t= 3,\n\t\tDOUBLE \t= 4,\n\t} value_type;\n\n\t// In debug mode, using the wrong .as_*() function will assert.\n\t// In release mode, using the wrong .as_*() function will safely return a default value.\n\tconst uint64_t uint_value = 0;\n\tconst int64_t sint_value = 0;\n\tconst std::string string_value = \"\";\n\tconst double double_value = 0.0;\n\n\tmetadata() : value_type(MISSING) {}\n\tmetadata(uint64_t value) : value_type(UINT), uint_value(value) {}\n\tmetadata(int64_t value) : value_type(SINT), sint_value(value) {}\n\tmetadata(const std::string &value) : value_type(STRING), string_value(value) {}\n\tmetadata(const char *value) : value_type(STRING), string_value(value) {}\n\tmetadata(double value) : value_type(DOUBLE), double_value(value) {}\n\n\tmetadata(const metadata &) = default;\n\tmetadata &operator=(const metadata &) = delete;\n\n\tuint64_t as_uint() const {\n\t\tassert(value_type == UINT);\n\t\treturn uint_value;\n\t}\n\n\tint64_t as_sint() const {\n\t\tassert(value_type == SINT);\n\t\treturn sint_value;\n\t}\n\n\tconst std::string &as_string() const {\n\t\tassert(value_type == STRING);\n\t\treturn string_value;\n\t}\n\n\tdouble as_double() const {\n\t\tassert(value_type == DOUBLE);\n\t\treturn double_value;\n\t}\n};\n\ntypedef std::map<std::string, metadata> metadata_map;\n\n// Tag class to disambiguate values/wires and their aliases.\nstruct debug_alias {};\n\n// Tag declaration to disambiguate values and debug outlines.\nusing debug_outline = ::_cxxrtl_outline;\n\n// This structure is intended for consumption via foreign function interfaces, like Python's ctypes.\n// Because of this it uses a C-style layout that is easy to parse rather than more idiomatic C++.\n//\n// To avoid violating strict aliasing rules, this structure has to be a subclass of the one used\n// in the C API, or it would not be possible to cast between the pointers to these.\n//\n// The `attrs` member cannot be owned by this structure because a `cxxrtl_object` can be created\n// from external C code.\nstruct debug_item : ::cxxrtl_object {\n\t// Object types.\n\tenum : uint32_t {\n\t\tVALUE = CXXRTL_VALUE,\n\t\tWIRE = CXXRTL_WIRE,\n\t\tMEMORY = CXXRTL_MEMORY,\n\t\tALIAS = CXXRTL_ALIAS,\n\t\tOUTLINE = CXXRTL_OUTLINE,\n\t};\n\n\t// Object flags.\n\tenum : uint32_t {\n\t\tINPUT = CXXRTL_INPUT,\n\t\tOUTPUT = CXXRTL_OUTPUT,\n\t\tINOUT = CXXRTL_INOUT,\n\t\tDRIVEN_SYNC = CXXRTL_DRIVEN_SYNC,\n\t\tDRIVEN_COMB = CXXRTL_DRIVEN_COMB,\n\t\tUNDRIVEN = CXXRTL_UNDRIVEN,\n\t};\n\n\tdebug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {}\n\n\ttemplate<size_t Bits>\n\tdebug_item(value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = VALUE;\n\t\tflags = flags_;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = item.data;\n\t\tnext = item.data;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(const value<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = VALUE;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.data);\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(wire<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {\n\t\tstatic_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&\n\t\t sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"wire<Bits> is not compatible with C layout\");\n\t\ttype = WIRE;\n\t\tflags = flags_;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = item.curr.data;\n\t\tnext = item.next.data;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Width>\n\tdebug_item(memory<Width> &item, size_t zero_offset = 0) {\n\t\tstatic_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t),\n\t\t \"memory<Width> is not compatible with C layout\");\n\t\ttype = MEMORY;\n\t\tflags = 0;\n\t\twidth = Width;\n\t\tlsb_at = 0;\n\t\tdepth = item.depth;\n\t\tzero_at = zero_offset;\n\t\tcurr = item.data ? item.data[0].data : nullptr;\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(debug_alias, const value<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = ALIAS;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.data);\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(debug_alias, const wire<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&\n\t\t sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"wire<Bits> is not compatible with C layout\");\n\t\ttype = ALIAS;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.curr.data);\n\t\tnext = nullptr;\n\t\toutline = nullptr;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits>\n\tdebug_item(debug_outline &group, const value<Bits> &item, size_t lsb_offset = 0) {\n\t\tstatic_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),\n\t\t \"value<Bits> is not compatible with C layout\");\n\t\ttype = OUTLINE;\n\t\tflags = DRIVEN_COMB;\n\t\twidth = Bits;\n\t\tlsb_at = lsb_offset;\n\t\tdepth = 1;\n\t\tzero_at = 0;\n\t\tcurr = const_cast<chunk_t*>(item.data);\n\t\tnext = nullptr;\n\t\toutline = &group;\n\t\tattrs = nullptr;\n\t}\n\n\ttemplate<size_t Bits, class IntegerT>\n\tIntegerT get() const {\n\t\tassert(width == Bits && depth == 1);\n\t\tvalue<Bits> item;\n\t\tstd::copy(curr, curr + value<Bits>::chunks, item.data);\n\t\treturn item.template get<IntegerT>();\n\t}\n\n\ttemplate<size_t Bits, class IntegerT>\n\tvoid set(IntegerT other) const {\n\t\tassert(width == Bits && depth == 1);\n\t\tvalue<Bits> item;\n\t\titem.template set<IntegerT>(other);\n\t\tstd::copy(item.data, item.data + value<Bits>::chunks, next);\n\t}\n};\nstatic_assert(std::is_standard_layout<debug_item>::value, \"debug_item is not compatible with C layout\");\n\n} // namespace cxxrtl\n\ntypedef struct _cxxrtl_attr_set {\n\tcxxrtl::metadata_map map;\n} *cxxrtl_attr_set;\n\nnamespace cxxrtl {\n\n// Representation of an attribute set in the C++ interface.\nusing debug_attrs = ::_cxxrtl_attr_set;\n\nstruct debug_items {\n\tstd::map<std::string, std::vector<debug_item>> table;\n\tstd::map<std::string, std::unique_ptr<debug_attrs>> attrs_table;\n\n\tvoid add(const std::string &name, debug_item &&item, metadata_map &&item_attrs = {}) {\n\t\tstd::unique_ptr<debug_attrs> &attrs = attrs_table[name];\n\t\tif (attrs.get() == nullptr)\n\t\t\tattrs = std::unique_ptr<debug_attrs>(new debug_attrs);\n\t\tfor (auto attr : item_attrs)\n\t\t\tattrs->map.insert(attr);\n\t\titem.attrs = attrs.get();\n\t\tstd::vector<debug_item> &parts = table[name];\n\t\tparts.emplace_back(item);\n\t\tstd::sort(parts.begin(), parts.end(),\n\t\t\t[](const debug_item &a, const debug_item &b) {\n\t\t\t\treturn a.lsb_at < b.lsb_at;\n\t\t\t});\n\t}\n\n\tsize_t count(const std::string &name) const {\n\t\tif (table.count(name) == 0)\n\t\t\treturn 0;\n\t\treturn table.at(name).size();\n\t}\n\n\tconst std::vector<debug_item> &parts_at(const std::string &name) const {\n\t\treturn table.at(name);\n\t}\n\n\tconst debug_item &at(const std::string &name) const {\n\t\tconst std::vector<debug_item> &parts = table.at(name);\n\t\tassert(parts.size() == 1);\n\t\treturn parts.at(0);\n\t}\n\n\tconst debug_item &operator [](const std::string &name) const {\n\t\treturn at(name);\n\t}\n\n\tconst metadata_map &attrs(const std::string &name) const {\n\t\treturn attrs_table.at(name)->map;\n\t}\n};\n\n// Tag class to disambiguate the default constructor used by the toplevel module that calls reset(),\n// and the constructor of interior modules that should not call it.\nstruct interior {};\n\nstruct module {\n\tmodule() {}\n\tvirtual ~module() {}\n\n\t// Modules with black boxes cannot be copied. Although not all designs include black boxes,\n\t// delete the copy constructor and copy assignment operator to make sure that any downstream\n\t// code that manipulates modules doesn't accidentally depend on their availability.\n\tmodule(const module &) = delete;\n\tmodule &operator=(const module &) = delete;\n\n\tmodule(module &&) = default;\n\tmodule &operator=(module &&) = default;\n\n\tvirtual void reset() = 0;\n\n\tvirtual bool eval() = 0;\n\tvirtual bool commit() = 0;\n\n\tunsigned int steps = 0;\n\n\tsize_t step() {\n\t\t++steps;\n\t\tsize_t deltas = 0;\n\t\tbool converged = false;\n\t\tdo {\n\t\t\tconverged = eval();\n\t\t\tdeltas++;\n\t\t} while (commit() && !converged);\n\t\treturn deltas;\n\t}\n\n\tvirtual void debug_info(debug_items &items, std::string path = \"\") {\n\t\t(void)items, (void)path;\n\t}\n};\n\n} // namespace cxxrtl\n\n// Internal structures used to communicate with the implementation of the C interface.\n\ntypedef struct _cxxrtl_toplevel {\n\tstd::unique_ptr<cxxrtl::module> module;\n} *cxxrtl_toplevel;\n\ntypedef struct _cxxrtl_outline {\n\tstd::function<void()> eval;\n} *cxxrtl_outline;\n\n// Definitions of internal Yosys cells. Other than the functions in this namespace, CXXRTL is fully generic\n// and indepenent of Yosys implementation details.\n//\n// The `write_cxxrtl` pass translates internal cells (cells with names that start with `$`) to calls of these\n// functions. All of Yosys arithmetic and logical cells perform sign or zero extension on their operands,\n// whereas basic operations on arbitrary width values require operands to be of the same width. These functions\n// bridge the gap by performing the necessary casts. They are named similar to `cell_A[B]`, where A and B are `u`\n// if the corresponding operand is unsigned, and `s` if it is signed.\nnamespace cxxrtl_yosys {\n\nusing namespace cxxrtl;\n\n// std::max isn't constexpr until C++14 for no particular reason (it's an oversight), so we define our own.\ntemplate<class T>\nCXXRTL_ALWAYS_INLINE\nconstexpr T max(const T &a, const T &b) {\n\treturn a > b ? a : b;\n}\n\n// Logic operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> logic_not(const value<BitsA> &a) {\n\treturn value<BitsY> { a ? 0u : 1u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> logic_and(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn value<BitsY> { (bool(a) && bool(b)) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> logic_or(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn value<BitsY> { (bool(a) || bool(b)) ? 1u : 0u };\n}\n\n// Reduction operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_and(const value<BitsA> &a) {\n\treturn value<BitsY> { a.bit_not().is_zero() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_or(const value<BitsA> &a) {\n\treturn value<BitsY> { a ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_xor(const value<BitsA> &a) {\n\treturn value<BitsY> { (a.ctpop() % 2) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_xnor(const value<BitsA> &a) {\n\treturn value<BitsY> { (a.ctpop() % 2) ? 0u : 1u };\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> reduce_bool(const value<BitsA> &a) {\n\treturn value<BitsY> { a ? 1u : 0u };\n}\n\n// Bitwise operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> not_u(const value<BitsA> &a) {\n\treturn a.template zcast<BitsY>().bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> not_s(const value<BitsA> &a) {\n\treturn a.template scast<BitsY>().bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> and_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_and(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> and_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_and(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> or_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_or(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> or_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_or(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_xor(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_xor(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xnor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().bit_xor(b.template zcast<BitsY>()).bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> xnor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().bit_xor(b.template scast<BitsY>()).bit_not();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shl_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shl_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshl_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshl_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().shl(b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shr_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.shr(b).template zcast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shr_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.shr(b).template scast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshr_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.shr(b).template zcast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sshr_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.sshr(b).template scast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shr_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shr_su<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_us(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn b.is_neg() ? shl_uu<BitsY>(a, b.template sext<BitsB + 1>().neg()) : shr_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shift_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn b.is_neg() ? shl_su<BitsY>(a, b.template sext<BitsB + 1>().neg()) : shr_su<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_su(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_su<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_us(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_us<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> shiftx_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn shift_ss<BitsY>(a, b);\n}\n\n// Comparison operations\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eq_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template zext<BitsExt>() == b.template zext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eq_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template sext<BitsExt>() == b.template sext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ne_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template zext<BitsExt>() != b.template zext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ne_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY>{ a.template sext<BitsExt>() != b.template sext<BitsExt>() ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eqx_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn eq_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> eqx_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn eq_ss<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> nex_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn ne_uu<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> nex_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn ne_ss<BitsY>(a, b);\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> gt_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { b.template zext<BitsExt>().ucmp(a.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> gt_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { b.template sext<BitsExt>().scmp(a.template sext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ge_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !a.template zext<BitsExt>().ucmp(b.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> ge_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !a.template sext<BitsExt>().scmp(b.template sext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> lt_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { a.template zext<BitsExt>().ucmp(b.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> lt_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { a.template sext<BitsExt>().scmp(b.template sext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> le_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !b.template zext<BitsExt>().ucmp(a.template zext<BitsExt>()) ? 1u : 0u };\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> le_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsExt = max(BitsA, BitsB);\n\treturn value<BitsY> { !b.template sext<BitsExt>().scmp(a.template sext<BitsExt>()) ? 1u : 0u };\n}\n\n// Arithmetic operations\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> pos_u(const value<BitsA> &a) {\n\treturn a.template zcast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> pos_s(const value<BitsA> &a) {\n\treturn a.template scast<BitsY>();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> neg_u(const value<BitsA> &a) {\n\treturn a.template zcast<BitsY>().neg();\n}\n\ntemplate<size_t BitsY, size_t BitsA>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> neg_s(const value<BitsA> &a) {\n\treturn a.template scast<BitsY>().neg();\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> add_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().add(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> add_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().add(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sub_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template zcast<BitsY>().sub(b.template zcast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> sub_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().sub(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mul_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t BitsM = BitsA >= BitsB ? BitsA : BitsB;\n\treturn a.template zcast<BitsM>().template mul<BitsY>(b.template zcast<BitsM>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mul_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn a.template scast<BitsY>().template mul<BitsY>(b.template scast<BitsY>());\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nstd::pair<value<BitsY>, value<BitsY>> divmod_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t Bits = max(BitsY, max(BitsA, BitsB));\n\tvalue<Bits> quotient;\n\tvalue<Bits> remainder;\n\tvalue<Bits> dividend = a.template zext<Bits>();\n\tvalue<Bits> divisor = b.template zext<Bits>();\n\tstd::tie(quotient, remainder) = dividend.udivmod(divisor);\n\treturn {quotient.template trunc<BitsY>(), remainder.template trunc<BitsY>()};\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nstd::pair<value<BitsY>, value<BitsY>> divmod_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tconstexpr size_t Bits = max(BitsY, max(BitsA, BitsB));\n\tvalue<Bits> quotient;\n\tvalue<Bits> remainder;\n\tvalue<Bits> dividend = a.template sext<Bits>();\n\tvalue<Bits> divisor = b.template sext<Bits>();\n\tstd::tie(quotient, remainder) = dividend.sdivmod(divisor);\n\treturn {quotient.template trunc<BitsY>(), remainder.template trunc<BitsY>()};\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> div_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).first;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> div_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_ss<BitsY>(a, b).first;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mod_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).second;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> mod_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_ss<BitsY>(a, b).second;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> modfloor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).second;\n}\n\n// GHDL Modfloor operator. Returns r=a mod b, such that r has the same sign as b and\n// a=b*N+r where N is some integer\n// In practical terms, when a and b have different signs and the remainder returned by divmod_ss is not 0\n// then return the remainder + b\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> modfloor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tvalue<BitsY> r;\n\tr = divmod_ss<BitsY>(a, b).second;\n\tif((b.is_neg() != a.is_neg()) && !r.is_zero())\n\t\treturn add_ss<BitsY>(b, r);\n\treturn r;\n}\n\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> divfloor_uu(const value<BitsA> &a, const value<BitsB> &b) {\n\treturn divmod_uu<BitsY>(a, b).first;\n}\n\n// Divfloor. Similar to above: returns q=a//b, where q has the sign of a*b and a=b*q+N.\n// In other words, returns (truncating) a/b, except if a and b have different signs\n// and there's non-zero remainder, subtract one more towards floor.\ntemplate<size_t BitsY, size_t BitsA, size_t BitsB>\nCXXRTL_ALWAYS_INLINE\nvalue<BitsY> divfloor_ss(const value<BitsA> &a, const value<BitsB> &b) {\n\tvalue<BitsY> q, r;\n\tstd::tie(q, r) = divmod_ss<BitsY>(a, b);\n\tif ((b.is_neg() != a.is_neg()) && !r.is_zero())\n\t\treturn sub_uu<BitsY>(q, value<1> { 1u });\n\treturn q;\n\n}\n\n// Memory helper\nstruct memory_index {\n\tbool valid;\n\tsize_t index;\n\n\ttemplate<size_t BitsAddr>\n\tmemory_index(const value<BitsAddr> &addr, size_t offset, size_t depth) {\n\t\tstatic_assert(value<BitsAddr>::chunks <= 1, \"memory address is too wide\");\n\t\tsize_t offset_index = addr.data[0];\n\n\t\tvalid = (offset_index >= offset && offset_index < offset + depth);\n\t\tindex = offset_index - offset;\n\t}\n};\n\n} // namespace cxxrtl_yosys\n\n#endif\n",
|
|
136
136
|
"cxxrtl_vcd.h": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2020 whitequark <whitequark@whitequark.org>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n#ifndef CXXRTL_VCD_H\n#define CXXRTL_VCD_H\n\n#include <cxxrtl/cxxrtl.h>\n\nnamespace cxxrtl {\n\nclass vcd_writer {\n\tstruct variable {\n\t\tsize_t ident;\n\t\tsize_t width;\n\t\tchunk_t *curr;\n\t\tsize_t cache_offset;\n\t\tdebug_outline *outline;\n\t\tbool *outline_warm;\n\t};\n\n\tstd::vector<std::string> current_scope;\n\tstd::map<debug_outline*, bool> outlines;\n\tstd::vector<variable> variables;\n\tstd::vector<chunk_t> cache;\n\tstd::map<chunk_t*, size_t> aliases;\n\tbool streaming = false;\n\n\tvoid emit_timescale(unsigned number, const std::string &unit) {\n\t\tassert(!streaming);\n\t\tassert(number == 1 || number == 10 || number == 100);\n\t\tassert(unit == \"s\" || unit == \"ms\" || unit == \"us\" ||\n\t\t unit == \"ns\" || unit == \"ps\" || unit == \"fs\");\n\t\tbuffer += \"$timescale \" + std::to_string(number) + \" \" + unit + \" $end\\n\";\n\t}\n\n\tvoid emit_scope(const std::vector<std::string> &scope) {\n\t\tassert(!streaming);\n\t\twhile (current_scope.size() > scope.size() ||\n\t\t (current_scope.size() > 0 &&\n\t\t\tcurrent_scope[current_scope.size() - 1] != scope[current_scope.size() - 1])) {\n\t\t\tbuffer += \"$upscope $end\\n\";\n\t\t\tcurrent_scope.pop_back();\n\t\t}\n\t\twhile (current_scope.size() < scope.size()) {\n\t\t\tbuffer += \"$scope module \" + scope[current_scope.size()] + \" $end\\n\";\n\t\t\tcurrent_scope.push_back(scope[current_scope.size()]);\n\t\t}\n\t}\n\n\tvoid emit_ident(size_t ident) {\n\t\tdo {\n\t\t\tbuffer += '!' + ident % 94; // \"base94\"\n\t\t\tident /= 94;\n\t\t} while (ident != 0);\n\t}\n\n\tvoid emit_name(const std::string &name) {\n\t\tfor (char c : name) {\n\t\t\tif (c == ':') {\n\t\t\t\t// Due to a bug, GTKWave cannot parse a colon in the variable name, causing the VCD file\n\t\t\t\t// to be unreadable. It cannot be escaped either, so replace it with the sideways colon.\n\t\t\t\tbuffer += \"..\";\n\t\t\t} else {\n\t\t\t\tbuffer += c;\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid emit_var(const variable &var, const std::string &type, const std::string &name,\n\t size_t lsb_at, bool multipart) {\n\t\tassert(!streaming);\n\t\tbuffer += \"$var \" + type + \" \" + std::to_string(var.width) + \" \";\n\t\temit_ident(var.ident);\n\t\tbuffer += \" \";\n\t\temit_name(name);\n\t\tif (multipart || name.back() == ']' || lsb_at != 0) {\n\t\t\tif (var.width == 1)\n\t\t\t\tbuffer += \" [\" + std::to_string(lsb_at) + \"]\";\n\t\t\telse\n\t\t\t\tbuffer += \" [\" + std::to_string(lsb_at + var.width - 1) + \":\" + std::to_string(lsb_at) + \"]\";\n\t\t}\n\t\tbuffer += \" $end\\n\";\n\t}\n\n\tvoid emit_enddefinitions() {\n\t\tassert(!streaming);\n\t\tbuffer += \"$enddefinitions $end\\n\";\n\t\tstreaming = true;\n\t}\n\n\tvoid emit_time(uint64_t timestamp) {\n\t\tassert(streaming);\n\t\tbuffer += \"#\" + std::to_string(timestamp) + \"\\n\";\n\t}\n\n\tvoid emit_scalar(const variable &var) {\n\t\tassert(streaming);\n\t\tassert(var.width == 1);\n\t\tbuffer += (*var.curr ? '1' : '0');\n\t\temit_ident(var.ident);\n\t\tbuffer += '\\n';\n\t}\n\n\tvoid emit_vector(const variable &var) {\n\t\tassert(streaming);\n\t\tbuffer += 'b';\n\t\tfor (size_t bit = var.width - 1; bit != (size_t)-1; bit--) {\n\t\t\tbool bit_curr = var.curr[bit / (8 * sizeof(chunk_t))] & (1 << (bit % (8 * sizeof(chunk_t))));\n\t\t\tbuffer += (bit_curr ? '1' : '0');\n\t\t}\n\t\tbuffer += ' ';\n\t\temit_ident(var.ident);\n\t\tbuffer += '\\n';\n\t}\n\n\tvoid reset_outlines() {\n\t\tfor (auto &outline_it : outlines)\n\t\t\toutline_it.second = /*warm=*/(outline_it.first == nullptr);\n\t}\n\n\tvariable ®ister_variable(size_t width, chunk_t *curr, bool constant = false, debug_outline *outline = nullptr) {\n\t\tif (aliases.count(curr)) {\n\t\t\treturn variables[aliases[curr]];\n\t\t} else {\n\t\t\tauto outline_it = outlines.emplace(outline, /*warm=*/(outline == nullptr)).first;\n\t\t\tconst size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8);\n\t\t\taliases[curr] = variables.size();\n\t\t\tif (constant) {\n\t\t\t\tvariables.emplace_back(variable { variables.size(), width, curr, (size_t)-1, outline_it->first, &outline_it->second });\n\t\t\t} else {\n\t\t\t\tvariables.emplace_back(variable { variables.size(), width, curr, cache.size(), outline_it->first, &outline_it->second });\n\t\t\t\tcache.insert(cache.end(), &curr[0], &curr[chunks]);\n\t\t\t}\n\t\t\treturn variables.back();\n\t\t}\n\t}\n\n\tbool test_variable(const variable &var) {\n\t\tif (var.cache_offset == (size_t)-1)\n\t\t\treturn false; // constant\n\t\tif (!*var.outline_warm) {\n\t\t\tvar.outline->eval();\n\t\t\t*var.outline_warm = true;\n\t\t}\n\t\tconst size_t chunks = (var.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8);\n\t\tif (std::equal(&var.curr[0], &var.curr[chunks], &cache[var.cache_offset])) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tstd::copy(&var.curr[0], &var.curr[chunks], &cache[var.cache_offset]);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tstatic std::vector<std::string> split_hierarchy(const std::string &hier_name) {\n\t\tstd::vector<std::string> hierarchy;\n\t\tsize_t prev = 0;\n\t\twhile (true) {\n\t\t\tsize_t curr = hier_name.find_first_of(' ', prev);\n\t\t\tif (curr == std::string::npos) {\n\t\t\t\thierarchy.push_back(hier_name.substr(prev));\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\thierarchy.push_back(hier_name.substr(prev, curr - prev));\n\t\t\t\tprev = curr + 1;\n\t\t\t}\n\t\t}\n\t\treturn hierarchy;\n\t}\n\npublic:\n\tstd::string buffer;\n\n\tvoid timescale(unsigned number, const std::string &unit) {\n\t\temit_timescale(number, unit);\n\t}\n\n\tvoid add(const std::string &hier_name, const debug_item &item, bool multipart = false) {\n\t\tstd::vector<std::string> scope = split_hierarchy(hier_name);\n\t\tstd::string name = scope.back();\n\t\tscope.pop_back();\n\n\t\temit_scope(scope);\n\t\tswitch (item.type) {\n\t\t\t// Not the best naming but oh well...\n\t\t\tcase debug_item::VALUE:\n\t\t\t\temit_var(register_variable(item.width, item.curr, /*constant=*/item.next == nullptr),\n\t\t\t\t \"wire\", name, item.lsb_at, multipart);\n\t\t\t\tbreak;\n\t\t\tcase debug_item::WIRE:\n\t\t\t\temit_var(register_variable(item.width, item.curr),\n\t\t\t\t \"reg\", name, item.lsb_at, multipart);\n\t\t\t\tbreak;\n\t\t\tcase debug_item::MEMORY: {\n\t\t\t\tconst size_t stride = (item.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8);\n\t\t\t\tfor (size_t index = 0; index < item.depth; index++) {\n\t\t\t\t\tchunk_t *nth_curr = &item.curr[stride * index];\n\t\t\t\t\tstd::string nth_name = name + '[' + std::to_string(index) + ']';\n\t\t\t\t\temit_var(register_variable(item.width, nth_curr),\n\t\t\t\t\t \"reg\", nth_name, item.lsb_at, multipart);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase debug_item::ALIAS:\n\t\t\t\t// Like VALUE, but, even though `item.next == nullptr` always holds, the underlying value\n\t\t\t\t// can actually change, and must be tracked. In most cases the VCD identifier will be\n\t\t\t\t// unified with the aliased reg, but we should handle the case where only the alias is\n\t\t\t\t// added to the VCD writer, too.\n\t\t\t\temit_var(register_variable(item.width, item.curr),\n\t\t\t\t \"wire\", name, item.lsb_at, multipart);\n\t\t\t\tbreak;\n\t\t\tcase debug_item::OUTLINE:\n\t\t\t\temit_var(register_variable(item.width, item.curr, /*constant=*/false, item.outline),\n\t\t\t\t \"wire\", name, item.lsb_at, multipart);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\ttemplate<class Filter>\n\tvoid add(const debug_items &items, const Filter &filter) {\n\t\t// `debug_items` is a map, so the items are already sorted in an order optimal for emitting\n\t\t// VCD scope sections.\n\t\tfor (auto &it : items.table)\n\t\t\tfor (auto &part : it.second)\n\t\t\t\tif (filter(it.first, part))\n\t\t\t\t\tadd(it.first, part, it.second.size() > 1);\n\t}\n\n\tvoid add(const debug_items &items) {\n\t\tthis->add(items, [](const std::string &, const debug_item &) {\n\t\t\treturn true;\n\t\t});\n\t}\n\n\tvoid add_without_memories(const debug_items &items) {\n\t\tthis->add(items, [](const std::string &, const debug_item &item) {\n\t\t\treturn item.type != debug_item::MEMORY;\n\t\t});\n\t}\n\n\tvoid sample(uint64_t timestamp) {\n\t\tbool first_sample = !streaming;\n\t\tif (first_sample) {\n\t\t\temit_scope({});\n\t\t\temit_enddefinitions();\n\t\t}\n\t\treset_outlines();\n\t\temit_time(timestamp);\n\t\tfor (auto var : variables)\n\t\t\tif (test_variable(var) || first_sample) {\n\t\t\t\tif (var.width == 1)\n\t\t\t\t\temit_scalar(var);\n\t\t\t\telse\n\t\t\t\t\temit_vector(var);\n\t\t\t}\n\t}\n};\n\n}\n\n#endif\n",
|
|
137
137
|
},
|
|
138
138
|
},
|
|
@@ -251,9 +251,9 @@ export const filesystem = {
|
|
|
251
251
|
"arith_map_ccu2c.v": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>\n * Copyright (C) 2018 gatecat <gatecat@ds0.me>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n(* techmap_celltype = \"$alu\" *)\nmodule _80_ccu2c_alu (A, B, CI, BI, X, Y, CO);\n\tparameter A_SIGNED = 0;\n\tparameter B_SIGNED = 0;\n\tparameter A_WIDTH = 1;\n\tparameter B_WIDTH = 1;\n\tparameter Y_WIDTH = 1;\n\n\t(* force_downto *)\n\tinput [A_WIDTH-1:0] A;\n\t(* force_downto *)\n\tinput [B_WIDTH-1:0] B;\n\t(* force_downto *)\n\toutput [Y_WIDTH-1:0] X, Y;\n\n\tinput CI, BI;\n\t(* force_downto *)\n\toutput [Y_WIDTH-1:0] CO;\n\n\twire _TECHMAP_FAIL_ = Y_WIDTH <= 4;\n\n\t(* force_downto *)\n\twire [Y_WIDTH-1:0] A_buf, B_buf;\n\t\\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));\n\t\\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));\n\n\tfunction integer round_up2;\n\t\tinput integer N;\n\t\tbegin\n\t\t\tround_up2 = ((N + 1) / 2) * 2;\n\t\tend\n\tendfunction\n\n\tlocalparam Y_WIDTH2 = round_up2(Y_WIDTH);\n\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] AA = A_buf;\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] BX = B_buf;\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] C = {CO, CI};\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] FCO, Y1;\n\n\tgenvar i;\n\tgenerate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice\n\t\tCCU2C #(\n\t\t\t.INIT0(16'b1001011010101010),\n\t\t\t.INIT1(16'b1001011010101010),\n\t\t\t.INJECT1_0(\"NO\"),\n\t\t\t.INJECT1_1(\"NO\")\n\t ) ccu2c_i (\n\t\t\t.CIN(C[i]),\n\t\t\t.A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),\n\t\t\t.A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),\n\t\t\t.S0(Y[i]), .S1(Y1[i]),\n\t\t\t.COUT(FCO[i])\n\t\t);\n\n\t\tassign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));\n\t\tif (i+1 < Y_WIDTH) begin\n\t\t\tassign CO[i+1] = FCO[i];\n\t\t\tassign Y[i+1] = Y1[i];\n\t\tend\n\tend endgenerate\n\n\tassign X = AA ^ BB;\nendmodule\n",
|
|
252
252
|
"arith_map_ccu2d.v": "/*\n * yosys -- Yosys Open SYnthesis Suite\n *\n * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>\n * Copyright (C) 2018 gatecat <gatecat@ds0.me>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n */\n\n(* techmap_celltype = \"$alu\" *)\nmodule _80_ccu2d_alu (A, B, CI, BI, X, Y, CO);\n\tparameter A_SIGNED = 0;\n\tparameter B_SIGNED = 0;\n\tparameter A_WIDTH = 1;\n\tparameter B_WIDTH = 1;\n\tparameter Y_WIDTH = 1;\n\n\t(* force_downto *)\n\tinput [A_WIDTH-1:0] A;\n\t(* force_downto *)\n\tinput [B_WIDTH-1:0] B;\n\t(* force_downto *)\n\toutput [Y_WIDTH-1:0] X, Y;\n\n\tinput CI, BI;\n\t(* force_downto *)\n\toutput [Y_WIDTH-1:0] CO;\n\n\twire _TECHMAP_FAIL_ = Y_WIDTH <= 4;\n\n\t(* force_downto *)\n\twire [Y_WIDTH-1:0] A_buf, B_buf;\n\t\\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));\n\t\\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));\n\n\tfunction integer round_up2;\n\t\tinput integer N;\n\t\tbegin\n\t\t\tround_up2 = ((N + 1) / 2) * 2;\n\t\tend\n\tendfunction\n\n\tlocalparam Y_WIDTH2 = round_up2(Y_WIDTH);\n\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] AA = A_buf;\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] BX = B_buf;\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] C = {CO, CI};\n\t(* force_downto *)\n\twire [Y_WIDTH2-1:0] FCO, Y1;\n\n\tgenvar i;\n\tgenerate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice\n\t\tCCU2D #(\n\t\t\t.INIT0(16'b0101_1010_1001_0110),\n\t\t\t.INIT1(16'b0101_1010_1001_0110),\n\t\t\t.INJECT1_0(\"NO\"),\n\t\t\t.INJECT1_1(\"NO\")\n\t\t) ccu2d_i (\n\t\t\t.CIN(C[i]),\n\t\t\t.A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b0),\n\t\t\t.A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b0),\n\t\t\t.S0(Y[i]), .S1(Y1[i]),\n\t\t\t.COUT(FCO[i])\n\t\t);\n\n\t\tassign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));\n\t\tif (i+1 < Y_WIDTH) begin\n\t\t\tassign CO[i+1] = FCO[i];\n\t\t\tassign Y[i+1] = Y1[i];\n\t\tend\n\tend endgenerate\n\n\tassign X = AA ^ BB;\nendmodule\n",
|
|
253
253
|
"brams_16kd.txt": "ram block $__DP16KD_ {\n\tabits 14;\n\twidths 1 2 4 9 18 per_port;\n\tbyte 9;\n\tcost 128;\n\tinit no_undef;\n\tport srsw \"A\" \"B\" {\n\t\tclock anyedge;\n\t\tclken;\n\t\twrbe_separate;\n\t\tportoption \"WRITEMODE\" \"NORMAL\" {\n\t\t\trdwr no_change;\n\t\t}\n\t\tportoption \"WRITEMODE\" \"WRITETHROUGH\" {\n\t\t\trdwr new;\n\t\t}\n\t\tportoption \"WRITEMODE\" \"READBEFOREWRITE\" {\n\t\t\trdwr old;\n\t\t}\n\t\toption \"RESETMODE\" \"SYNC\" {\n\t\t\trdsrst zero ungated block_wr;\n\t\t}\n\t\toption \"RESETMODE\" \"ASYNC\" {\n\t\t\trdarst zero;\n\t\t}\n\t\trdinit zero;\n\t}\n}\n\nram block $__PDPW16KD_ {\n\tabits 14;\n\twidths 1 2 4 9 18 36 per_port;\n\tbyte 9;\n\tcost 128;\n\tinit no_undef;\n\tport sr \"R\" {\n\t\tclock anyedge;\n\t\tclken;\n\t\toption \"RESETMODE\" \"SYNC\" {\n\t\t\trdsrst zero ungated;\n\t\t}\n\t\toption \"RESETMODE\" \"ASYNC\" {\n\t\t\trdarst zero;\n\t\t}\n\t\trdinit zero;\n\t}\n\tport sw \"W\" {\n\t\twidth 36;\n\t\tclock anyedge;\n\t\tclken;\n\t}\n}\n",
|
|
254
|
-
"brams_8kc.txt": "ram block $__DP8KC_ {\n\tabits 13;\n\twidths 1 2 4 9 per_port;\n\tcost 64;\n\tinit no_undef;\n\tport srsw \"A\" \"B\" {\n\t\tclock posedge;\n\t\tclken;\n\t\tportoption \"WRITEMODE\" \"NORMAL\" {\n\t\t\trdwr no_change;\n\t\t}\n\t\tportoption \"WRITEMODE\" \"WRITETHROUGH\" {\n\t\t\trdwr new;\n\t\t}\n\t\tportoption \"WRITEMODE\" \"READBEFOREWRITE\" {\n\t\t\trdwr old;\n\t\t}\n\t\toption \"RESETMODE\" \"SYNC\" {\n\t\t\trdsrst zero ungated block_wr;\n\t\t}\n\t\toption \"RESETMODE\" \"ASYNC\" {\n\t\t\trdarst zero;\n\t\t}\n\t\trdinit zero;\n\t}\n}\n\nram block $__PDPW8KC_ {\n\tabits 13;\n\twidths 1 2 4 9 18 per_port;\n\tbyte 9;\n\tcost 64;\n\tinit no_undef;\n\tport sr \"R\" {\n\t\tclock posedge;\n\t\tclken;\n\t\toption \"RESETMODE\" \"SYNC\" {\n\t\t\trdsrst zero ungated;\n\t\t}\n\t\toption \"RESETMODE\" \"ASYNC\" {\n\t\t\trdarst zero;\n\t\t}\n\t\trdinit zero;\n\t}\n\tport sw \"W\" {\n\t\twidth 18;\n\t\tclock posedge;\n\t\tclken;\n\t}\n}\n",
|
|
254
|
+
"brams_8kc.txt": "ram block $__DP8KC_ {\n\tabits 13;\n\twidths 1 2 4 9 per_port;\n\tcost 64;\n\tinit no_undef;\n\tport srsw \"A\" \"B\" {\n\t\tclock posedge;\n\t\tclken;\n\t\tportoption \"WRITEMODE\" \"NORMAL\" {\n\t\t\trdwr no_change;\n\t\t}\n\t\tportoption \"WRITEMODE\" \"WRITETHROUGH\" {\n\t\t\trdwr new;\n\t\t}\n\t\tportoption \"WRITEMODE\" \"READBEFOREWRITE\" {\n\t\t\trdwr old;\n\t\t}\n\t\toption \"RESETMODE\" \"SYNC\" {\n\t\t\trdsrst zero ungated block_wr;\n\t\t}\n\t\toption \"RESETMODE\" \"ASYNC\" {\n\t\t\trdarst zero;\n\t\t}\n\t\trdinit zero;\n\t}\n}\n\nram block $__PDPW8KC_ {\n\tabits 13;\n\twidths 1 2 4 9 18 per_port;\n\tbyte 9;\n\tcost 64;\n\tinit no_undef;\n\tport sr \"R\" {\n\t\t# width 2 cannot be supported because of quirks\n\t\t# of the primitive, and memlib requires us to\n\t\t# remove width 1 as well\n\t\twidth 4 9 18;\n\t\tclock posedge;\n\t\tclken;\n\t\toption \"RESETMODE\" \"SYNC\" {\n\t\t\trdsrst zero ungated;\n\t\t}\n\t\toption \"RESETMODE\" \"ASYNC\" {\n\t\t\trdarst zero;\n\t\t}\n\t\trdinit zero;\n\t}\n\tport sw \"W\" {\n\t\twidth 18;\n\t\tclock posedge;\n\t\tclken;\n\t}\n}\n",
|
|
255
255
|
"brams_map_16kd.v": "module $__DP16KD_ (...);\n\nparameter INIT = 0;\nparameter OPTION_RESETMODE = \"SYNC\";\n\nparameter PORT_A_WIDTH = 18;\nparameter PORT_A_WR_BE_WIDTH = 2;\nparameter PORT_A_CLK_POL = 1;\nparameter PORT_A_OPTION_WRITEMODE = \"NORMAL\";\n\ninput PORT_A_CLK;\ninput PORT_A_CLK_EN;\ninput PORT_A_WR_EN;\ninput PORT_A_RD_SRST;\ninput PORT_A_RD_ARST;\ninput [13:0] PORT_A_ADDR;\ninput [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;\ninput [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;\noutput [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;\n\nparameter PORT_B_WIDTH = 18;\nparameter PORT_B_WR_BE_WIDTH = 2;\nparameter PORT_B_CLK_POL = 1;\nparameter PORT_B_OPTION_WRITEMODE = \"NORMAL\";\n\ninput PORT_B_CLK;\ninput PORT_B_CLK_EN;\ninput PORT_B_WR_EN;\ninput PORT_B_RD_SRST;\ninput PORT_B_RD_ARST;\ninput [13:0] PORT_B_ADDR;\ninput [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;\ninput [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;\noutput [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;\n\nfunction [319:0] init_slice;\n\tinput integer idx;\n\tinteger i, j;\n\tinit_slice = 0;\n\tfor (i = 0; i < 16; i = i + 1) begin\n\t\tinit_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];\n\tend\nendfunction\n\nwire [17:0] DOA;\nwire [17:0] DOB;\nwire [17:0] DIA = PORT_A_WR_DATA;\nwire [17:0] DIB = PORT_B_WR_DATA;\n\nassign PORT_A_RD_DATA = DOA;\nassign PORT_B_RD_DATA = DOB;\n\nDP16KD #(\n\t.INITVAL_00(init_slice('h00)),\n\t.INITVAL_01(init_slice('h01)),\n\t.INITVAL_02(init_slice('h02)),\n\t.INITVAL_03(init_slice('h03)),\n\t.INITVAL_04(init_slice('h04)),\n\t.INITVAL_05(init_slice('h05)),\n\t.INITVAL_06(init_slice('h06)),\n\t.INITVAL_07(init_slice('h07)),\n\t.INITVAL_08(init_slice('h08)),\n\t.INITVAL_09(init_slice('h09)),\n\t.INITVAL_0A(init_slice('h0a)),\n\t.INITVAL_0B(init_slice('h0b)),\n\t.INITVAL_0C(init_slice('h0c)),\n\t.INITVAL_0D(init_slice('h0d)),\n\t.INITVAL_0E(init_slice('h0e)),\n\t.INITVAL_0F(init_slice('h0f)),\n\t.INITVAL_10(init_slice('h10)),\n\t.INITVAL_11(init_slice('h11)),\n\t.INITVAL_12(init_slice('h12)),\n\t.INITVAL_13(init_slice('h13)),\n\t.INITVAL_14(init_slice('h14)),\n\t.INITVAL_15(init_slice('h15)),\n\t.INITVAL_16(init_slice('h16)),\n\t.INITVAL_17(init_slice('h17)),\n\t.INITVAL_18(init_slice('h18)),\n\t.INITVAL_19(init_slice('h19)),\n\t.INITVAL_1A(init_slice('h1a)),\n\t.INITVAL_1B(init_slice('h1b)),\n\t.INITVAL_1C(init_slice('h1c)),\n\t.INITVAL_1D(init_slice('h1d)),\n\t.INITVAL_1E(init_slice('h1e)),\n\t.INITVAL_1F(init_slice('h1f)),\n\t.INITVAL_20(init_slice('h20)),\n\t.INITVAL_21(init_slice('h21)),\n\t.INITVAL_22(init_slice('h22)),\n\t.INITVAL_23(init_slice('h23)),\n\t.INITVAL_24(init_slice('h24)),\n\t.INITVAL_25(init_slice('h25)),\n\t.INITVAL_26(init_slice('h26)),\n\t.INITVAL_27(init_slice('h27)),\n\t.INITVAL_28(init_slice('h28)),\n\t.INITVAL_29(init_slice('h29)),\n\t.INITVAL_2A(init_slice('h2a)),\n\t.INITVAL_2B(init_slice('h2b)),\n\t.INITVAL_2C(init_slice('h2c)),\n\t.INITVAL_2D(init_slice('h2d)),\n\t.INITVAL_2E(init_slice('h2e)),\n\t.INITVAL_2F(init_slice('h2f)),\n\t.INITVAL_30(init_slice('h30)),\n\t.INITVAL_31(init_slice('h31)),\n\t.INITVAL_32(init_slice('h32)),\n\t.INITVAL_33(init_slice('h33)),\n\t.INITVAL_34(init_slice('h34)),\n\t.INITVAL_35(init_slice('h35)),\n\t.INITVAL_36(init_slice('h36)),\n\t.INITVAL_37(init_slice('h37)),\n\t.INITVAL_38(init_slice('h38)),\n\t.INITVAL_39(init_slice('h39)),\n\t.INITVAL_3A(init_slice('h3a)),\n\t.INITVAL_3B(init_slice('h3b)),\n\t.INITVAL_3C(init_slice('h3c)),\n\t.INITVAL_3D(init_slice('h3d)),\n\t.INITVAL_3E(init_slice('h3e)),\n\t.INITVAL_3F(init_slice('h3f)),\n\t.DATA_WIDTH_A(PORT_A_WIDTH),\n\t.DATA_WIDTH_B(PORT_B_WIDTH),\n\t.REGMODE_A(\"NOREG\"),\n\t.REGMODE_B(\"NOREG\"),\n\t.RESETMODE(OPTION_RESETMODE),\n\t.ASYNC_RESET_RELEASE(OPTION_RESETMODE),\n\t.CSDECODE_A(\"0b000\"),\n\t.CSDECODE_B(\"0b000\"),\n\t.CLKAMUX(PORT_A_CLK_POL ? \"CLKA\" : \"INV\"),\n\t.CLKBMUX(PORT_B_CLK_POL ? \"CLKB\" : \"INV\"),\n\t.WRITEMODE_A(PORT_A_OPTION_WRITEMODE),\n\t.WRITEMODE_B(PORT_B_OPTION_WRITEMODE),\n\t.GSR(\"AUTO\")\n) _TECHMAP_REPLACE_ (\n\t.CLKA(PORT_A_CLK),\n\t.WEA(PORT_A_WIDTH == 18 ? PORT_A_WR_EN : (PORT_A_WR_EN | PORT_A_WR_BE[0])),\n\t.CEA(PORT_A_CLK_EN),\n\t.OCEA(1'b1),\n\t.RSTA(OPTION_RESETMODE == \"SYNC\" ? PORT_A_RD_SRST : PORT_A_RD_ARST),\n\t.CSA0(1'b0),\n\t.CSA1(1'b0),\n\t.CSA2(1'b0),\n\t.ADA0(PORT_A_WIDTH == 18 ? PORT_A_WR_BE[0] : PORT_A_ADDR[0]),\n\t.ADA1(PORT_A_WIDTH == 18 ? PORT_A_WR_BE[1] : PORT_A_ADDR[1]),\n\t.ADA2(PORT_A_ADDR[2]),\n\t.ADA3(PORT_A_ADDR[3]),\n\t.ADA4(PORT_A_ADDR[4]),\n\t.ADA5(PORT_A_ADDR[5]),\n\t.ADA6(PORT_A_ADDR[6]),\n\t.ADA7(PORT_A_ADDR[7]),\n\t.ADA8(PORT_A_ADDR[8]),\n\t.ADA9(PORT_A_ADDR[9]),\n\t.ADA10(PORT_A_ADDR[10]),\n\t.ADA11(PORT_A_ADDR[11]),\n\t.ADA12(PORT_A_ADDR[12]),\n\t.ADA13(PORT_A_ADDR[13]),\n\t.DIA0(DIA[0]),\n\t.DIA1(DIA[1]),\n\t.DIA2(DIA[2]),\n\t.DIA3(DIA[3]),\n\t.DIA4(DIA[4]),\n\t.DIA5(DIA[5]),\n\t.DIA6(DIA[6]),\n\t.DIA7(DIA[7]),\n\t.DIA8(DIA[8]),\n\t.DIA9(DIA[9]),\n\t.DIA10(DIA[10]),\n\t.DIA11(DIA[11]),\n\t.DIA12(DIA[12]),\n\t.DIA13(DIA[13]),\n\t.DIA14(DIA[14]),\n\t.DIA15(DIA[15]),\n\t.DIA16(DIA[16]),\n\t.DIA17(DIA[17]),\n\t.DOA0(DOA[0]),\n\t.DOA1(DOA[1]),\n\t.DOA2(DOA[2]),\n\t.DOA3(DOA[3]),\n\t.DOA4(DOA[4]),\n\t.DOA5(DOA[5]),\n\t.DOA6(DOA[6]),\n\t.DOA7(DOA[7]),\n\t.DOA8(DOA[8]),\n\t.DOA9(DOA[9]),\n\t.DOA10(DOA[10]),\n\t.DOA11(DOA[11]),\n\t.DOA12(DOA[12]),\n\t.DOA13(DOA[13]),\n\t.DOA14(DOA[14]),\n\t.DOA15(DOA[15]),\n\t.DOA16(DOA[16]),\n\t.DOA17(DOA[17]),\n\n\t.CLKB(PORT_B_CLK),\n\t.WEB(PORT_B_WIDTH == 18 ? PORT_B_WR_EN : (PORT_B_WR_EN | PORT_B_WR_BE[0])),\n\t.CEB(PORT_B_CLK_EN),\n\t.OCEB(1'b1),\n\t.RSTB(OPTION_RESETMODE == \"SYNC\" ? PORT_B_RD_SRST : PORT_B_RD_ARST),\n\t.CSB0(1'b0),\n\t.CSB1(1'b0),\n\t.CSB2(1'b0),\n\t.ADB0(PORT_B_WIDTH == 18 ? PORT_B_WR_BE[0] : PORT_B_ADDR[0]),\n\t.ADB1(PORT_B_WIDTH == 18 ? PORT_B_WR_BE[1] : PORT_B_ADDR[1]),\n\t.ADB2(PORT_B_ADDR[2]),\n\t.ADB3(PORT_B_ADDR[3]),\n\t.ADB4(PORT_B_ADDR[4]),\n\t.ADB5(PORT_B_ADDR[5]),\n\t.ADB6(PORT_B_ADDR[6]),\n\t.ADB7(PORT_B_ADDR[7]),\n\t.ADB8(PORT_B_ADDR[8]),\n\t.ADB9(PORT_B_ADDR[9]),\n\t.ADB10(PORT_B_ADDR[10]),\n\t.ADB11(PORT_B_ADDR[11]),\n\t.ADB12(PORT_B_ADDR[12]),\n\t.ADB13(PORT_B_ADDR[13]),\n\t.DIB0(DIB[0]),\n\t.DIB1(DIB[1]),\n\t.DIB2(DIB[2]),\n\t.DIB3(DIB[3]),\n\t.DIB4(DIB[4]),\n\t.DIB5(DIB[5]),\n\t.DIB6(DIB[6]),\n\t.DIB7(DIB[7]),\n\t.DIB8(DIB[8]),\n\t.DIB9(DIB[9]),\n\t.DIB10(DIB[10]),\n\t.DIB11(DIB[11]),\n\t.DIB12(DIB[12]),\n\t.DIB13(DIB[13]),\n\t.DIB14(DIB[14]),\n\t.DIB15(DIB[15]),\n\t.DIB16(DIB[16]),\n\t.DIB17(DIB[17]),\n\t.DOB0(DOB[0]),\n\t.DOB1(DOB[1]),\n\t.DOB2(DOB[2]),\n\t.DOB3(DOB[3]),\n\t.DOB4(DOB[4]),\n\t.DOB5(DOB[5]),\n\t.DOB6(DOB[6]),\n\t.DOB7(DOB[7]),\n\t.DOB8(DOB[8]),\n\t.DOB9(DOB[9]),\n\t.DOB10(DOB[10]),\n\t.DOB11(DOB[11]),\n\t.DOB12(DOB[12]),\n\t.DOB13(DOB[13]),\n\t.DOB14(DOB[14]),\n\t.DOB15(DOB[15]),\n\t.DOB16(DOB[16]),\n\t.DOB17(DOB[17]),\n);\n\nendmodule\n\n\nmodule $__PDPW16KD_ (...);\n\nparameter INIT = 0;\nparameter OPTION_RESETMODE = \"SYNC\";\n\nparameter PORT_R_WIDTH = 36;\nparameter PORT_R_CLK_POL = 1;\n\ninput PORT_R_CLK;\ninput PORT_R_CLK_EN;\ninput PORT_R_RD_SRST;\ninput PORT_R_RD_ARST;\ninput [13:0] PORT_R_ADDR;\noutput [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;\n\nparameter PORT_W_WIDTH = 36;\nparameter PORT_W_WR_EN_WIDTH = 4;\nparameter PORT_W_CLK_POL = 1;\n\ninput PORT_W_CLK;\ninput PORT_W_CLK_EN;\ninput [13:0] PORT_W_ADDR;\ninput [PORT_W_WR_EN_WIDTH-1:0] PORT_W_WR_EN;\ninput [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;\n\nfunction [319:0] init_slice;\n\tinput integer idx;\n\tinteger i, j;\n\tinit_slice = 0;\n\tfor (i = 0; i < 16; i = i + 1) begin\n\t\tinit_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];\n\tend\nendfunction\n\nwire [35:0] DI = PORT_W_WR_DATA;\nwire [35:0] DO;\n\nassign PORT_R_RD_DATA = PORT_R_WIDTH == 36 ? DO : DO[35:18];\n\nDP16KD #(\n\t.INITVAL_00(init_slice('h00)),\n\t.INITVAL_01(init_slice('h01)),\n\t.INITVAL_02(init_slice('h02)),\n\t.INITVAL_03(init_slice('h03)),\n\t.INITVAL_04(init_slice('h04)),\n\t.INITVAL_05(init_slice('h05)),\n\t.INITVAL_06(init_slice('h06)),\n\t.INITVAL_07(init_slice('h07)),\n\t.INITVAL_08(init_slice('h08)),\n\t.INITVAL_09(init_slice('h09)),\n\t.INITVAL_0A(init_slice('h0a)),\n\t.INITVAL_0B(init_slice('h0b)),\n\t.INITVAL_0C(init_slice('h0c)),\n\t.INITVAL_0D(init_slice('h0d)),\n\t.INITVAL_0E(init_slice('h0e)),\n\t.INITVAL_0F(init_slice('h0f)),\n\t.INITVAL_10(init_slice('h10)),\n\t.INITVAL_11(init_slice('h11)),\n\t.INITVAL_12(init_slice('h12)),\n\t.INITVAL_13(init_slice('h13)),\n\t.INITVAL_14(init_slice('h14)),\n\t.INITVAL_15(init_slice('h15)),\n\t.INITVAL_16(init_slice('h16)),\n\t.INITVAL_17(init_slice('h17)),\n\t.INITVAL_18(init_slice('h18)),\n\t.INITVAL_19(init_slice('h19)),\n\t.INITVAL_1A(init_slice('h1a)),\n\t.INITVAL_1B(init_slice('h1b)),\n\t.INITVAL_1C(init_slice('h1c)),\n\t.INITVAL_1D(init_slice('h1d)),\n\t.INITVAL_1E(init_slice('h1e)),\n\t.INITVAL_1F(init_slice('h1f)),\n\t.INITVAL_20(init_slice('h20)),\n\t.INITVAL_21(init_slice('h21)),\n\t.INITVAL_22(init_slice('h22)),\n\t.INITVAL_23(init_slice('h23)),\n\t.INITVAL_24(init_slice('h24)),\n\t.INITVAL_25(init_slice('h25)),\n\t.INITVAL_26(init_slice('h26)),\n\t.INITVAL_27(init_slice('h27)),\n\t.INITVAL_28(init_slice('h28)),\n\t.INITVAL_29(init_slice('h29)),\n\t.INITVAL_2A(init_slice('h2a)),\n\t.INITVAL_2B(init_slice('h2b)),\n\t.INITVAL_2C(init_slice('h2c)),\n\t.INITVAL_2D(init_slice('h2d)),\n\t.INITVAL_2E(init_slice('h2e)),\n\t.INITVAL_2F(init_slice('h2f)),\n\t.INITVAL_30(init_slice('h30)),\n\t.INITVAL_31(init_slice('h31)),\n\t.INITVAL_32(init_slice('h32)),\n\t.INITVAL_33(init_slice('h33)),\n\t.INITVAL_34(init_slice('h34)),\n\t.INITVAL_35(init_slice('h35)),\n\t.INITVAL_36(init_slice('h36)),\n\t.INITVAL_37(init_slice('h37)),\n\t.INITVAL_38(init_slice('h38)),\n\t.INITVAL_39(init_slice('h39)),\n\t.INITVAL_3A(init_slice('h3a)),\n\t.INITVAL_3B(init_slice('h3b)),\n\t.INITVAL_3C(init_slice('h3c)),\n\t.INITVAL_3D(init_slice('h3d)),\n\t.INITVAL_3E(init_slice('h3e)),\n\t.INITVAL_3F(init_slice('h3f)),\n\t.DATA_WIDTH_A(PORT_W_WIDTH),\n\t.DATA_WIDTH_B(PORT_R_WIDTH),\n\t.REGMODE_A(\"NOREG\"),\n\t.REGMODE_B(\"NOREG\"),\n\t.RESETMODE(OPTION_RESETMODE),\n\t.ASYNC_RESET_RELEASE(OPTION_RESETMODE),\n\t.CSDECODE_A(\"0b000\"),\n\t.CSDECODE_B(\"0b000\"),\n\t.CLKAMUX(PORT_W_CLK_POL ? \"CLKA\" : \"INV\"),\n\t.CLKBMUX(PORT_R_CLK_POL ? \"CLKB\" : \"INV\"),\n\t.GSR(\"AUTO\")\n) _TECHMAP_REPLACE_ (\n\t.CLKA(PORT_W_CLK),\n\t.WEA(PORT_W_WIDTH >= 18 ? 1'b1 : PORT_W_WR_EN[0]),\n\t.CEA(PORT_W_CLK_EN),\n\t.OCEA(1'b0),\n\t.RSTA(1'b0),\n\t.CSA0(1'b0),\n\t.CSA1(1'b0),\n\t.CSA2(1'b0),\n\t.ADA0(PORT_W_WIDTH >= 18 ? PORT_W_WR_EN[0] : PORT_W_ADDR[0]),\n\t.ADA1(PORT_W_WIDTH >= 18 ? PORT_W_WR_EN[1] : PORT_W_ADDR[1]),\n\t.ADA2(PORT_W_WIDTH >= 36 ? PORT_W_WR_EN[2] : PORT_W_ADDR[2]),\n\t.ADA3(PORT_W_WIDTH >= 36 ? PORT_W_WR_EN[3] : PORT_W_ADDR[3]),\n\t.ADA4(PORT_W_ADDR[4]),\n\t.ADA5(PORT_W_ADDR[5]),\n\t.ADA6(PORT_W_ADDR[6]),\n\t.ADA7(PORT_W_ADDR[7]),\n\t.ADA8(PORT_W_ADDR[8]),\n\t.ADA9(PORT_W_ADDR[9]),\n\t.ADA10(PORT_W_ADDR[10]),\n\t.ADA11(PORT_W_ADDR[11]),\n\t.ADA12(PORT_W_ADDR[12]),\n\t.ADA13(PORT_W_ADDR[13]),\n\t.DIA0(DI[0]),\n\t.DIA1(DI[1]),\n\t.DIA2(DI[2]),\n\t.DIA3(DI[3]),\n\t.DIA4(DI[4]),\n\t.DIA5(DI[5]),\n\t.DIA6(DI[6]),\n\t.DIA7(DI[7]),\n\t.DIA8(DI[8]),\n\t.DIA9(DI[9]),\n\t.DIA10(DI[10]),\n\t.DIA11(DI[11]),\n\t.DIA12(DI[12]),\n\t.DIA13(DI[13]),\n\t.DIA14(DI[14]),\n\t.DIA15(DI[15]),\n\t.DIA16(DI[16]),\n\t.DIA17(DI[17]),\n\t.DIB0(DI[18]),\n\t.DIB1(DI[19]),\n\t.DIB2(DI[20]),\n\t.DIB3(DI[21]),\n\t.DIB4(DI[22]),\n\t.DIB5(DI[23]),\n\t.DIB6(DI[24]),\n\t.DIB7(DI[25]),\n\t.DIB8(DI[26]),\n\t.DIB9(DI[27]),\n\t.DIB10(DI[28]),\n\t.DIB11(DI[29]),\n\t.DIB12(DI[30]),\n\t.DIB13(DI[31]),\n\t.DIB14(DI[32]),\n\t.DIB15(DI[33]),\n\t.DIB16(DI[34]),\n\t.DIB17(DI[35]),\n\n\t.CLKB(PORT_R_CLK),\n\t.WEB(1'b0),\n\t.CEB(PORT_R_CLK_EN),\n\t.OCEB(1'b1),\n\t.RSTB(OPTION_RESETMODE == \"SYNC\" ? PORT_R_RD_SRST : PORT_R_RD_ARST),\n\t.CSB0(1'b0),\n\t.CSB1(1'b0),\n\t.CSB2(1'b0),\n\t.ADB0(PORT_R_ADDR[0]),\n\t.ADB1(PORT_R_ADDR[1]),\n\t.ADB2(PORT_R_ADDR[2]),\n\t.ADB3(PORT_R_ADDR[3]),\n\t.ADB4(PORT_R_ADDR[4]),\n\t.ADB5(PORT_R_ADDR[5]),\n\t.ADB6(PORT_R_ADDR[6]),\n\t.ADB7(PORT_R_ADDR[7]),\n\t.ADB8(PORT_R_ADDR[8]),\n\t.ADB9(PORT_R_ADDR[9]),\n\t.ADB10(PORT_R_ADDR[10]),\n\t.ADB11(PORT_R_ADDR[11]),\n\t.ADB12(PORT_R_ADDR[12]),\n\t.ADB13(PORT_R_ADDR[13]),\n\t.DOA0(DO[0]),\n\t.DOA1(DO[1]),\n\t.DOA2(DO[2]),\n\t.DOA3(DO[3]),\n\t.DOA4(DO[4]),\n\t.DOA5(DO[5]),\n\t.DOA6(DO[6]),\n\t.DOA7(DO[7]),\n\t.DOA8(DO[8]),\n\t.DOA9(DO[9]),\n\t.DOA10(DO[10]),\n\t.DOA11(DO[11]),\n\t.DOA12(DO[12]),\n\t.DOA13(DO[13]),\n\t.DOA14(DO[14]),\n\t.DOA15(DO[15]),\n\t.DOA16(DO[16]),\n\t.DOA17(DO[17]),\n\t.DOB0(DO[18]),\n\t.DOB1(DO[19]),\n\t.DOB2(DO[20]),\n\t.DOB3(DO[21]),\n\t.DOB4(DO[22]),\n\t.DOB5(DO[23]),\n\t.DOB6(DO[24]),\n\t.DOB7(DO[25]),\n\t.DOB8(DO[26]),\n\t.DOB9(DO[27]),\n\t.DOB10(DO[28]),\n\t.DOB11(DO[29]),\n\t.DOB12(DO[30]),\n\t.DOB13(DO[31]),\n\t.DOB14(DO[32]),\n\t.DOB15(DO[33]),\n\t.DOB16(DO[34]),\n\t.DOB17(DO[35]),\n);\n\nendmodule\n",
|
|
256
|
-
"brams_map_8kc.v": "module $__DP8KC_ (...);\n\nparameter INIT = 0;\nparameter OPTION_RESETMODE = \"SYNC\";\n\nparameter PORT_A_WIDTH = 18;\nparameter PORT_A_OPTION_WRITEMODE = \"NORMAL\";\n\ninput PORT_A_CLK;\ninput PORT_A_CLK_EN;\ninput PORT_A_WR_EN;\ninput PORT_A_RD_SRST;\ninput PORT_A_RD_ARST;\ninput [12:0] PORT_A_ADDR;\ninput [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;\noutput [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;\n\nparameter PORT_B_WIDTH = 18;\nparameter PORT_B_OPTION_WRITEMODE = \"NORMAL\";\n\ninput PORT_B_CLK;\ninput PORT_B_CLK_EN;\ninput PORT_B_WR_EN;\ninput PORT_B_RD_SRST;\ninput PORT_B_RD_ARST;\ninput [12:0] PORT_B_ADDR;\ninput [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;\noutput [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;\n\nfunction [319:0] init_slice;\n\tinput integer idx;\n\tinteger i, j;\n\tinit_slice = 0;\n\tfor (i = 0; i < 16; i = i + 1) begin\n\t\tinit_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];\n\tend\nendfunction\n\nwire [8:0] DOA;\nwire [8:0] DOB;\nwire [8:0] DIA = PORT_A_WR_DATA;\
|
|
256
|
+
"brams_map_8kc.v": "module $__DP8KC_ (...);\n\nparameter INIT = 0;\nparameter OPTION_RESETMODE = \"SYNC\";\n\nparameter PORT_A_WIDTH = 18;\nparameter PORT_A_OPTION_WRITEMODE = \"NORMAL\";\n\ninput PORT_A_CLK;\ninput PORT_A_CLK_EN;\ninput PORT_A_WR_EN;\ninput PORT_A_RD_SRST;\ninput PORT_A_RD_ARST;\ninput [12:0] PORT_A_ADDR;\ninput [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;\noutput [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;\n\nparameter PORT_B_WIDTH = 18;\nparameter PORT_B_OPTION_WRITEMODE = \"NORMAL\";\n\ninput PORT_B_CLK;\ninput PORT_B_CLK_EN;\ninput PORT_B_WR_EN;\ninput PORT_B_RD_SRST;\ninput PORT_B_RD_ARST;\ninput [12:0] PORT_B_ADDR;\ninput [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;\noutput [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;\n\nfunction [319:0] init_slice;\n\tinput integer idx;\n\tinteger i, j;\n\tinit_slice = 0;\n\tfor (i = 0; i < 16; i = i + 1) begin\n\t\tinit_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];\n\tend\nendfunction\n\nwire [8:0] DOA;\nwire [8:0] DOB;\nwire [8:0] DIA;\nwire [8:0] DIB;\n\ncase(PORT_A_WIDTH)\n\t1: assign DIA = {7'bx, PORT_A_WR_DATA[0], 1'bx};\n\t2: assign DIA = {3'bx, PORT_A_WR_DATA[1], 2'bx, PORT_A_WR_DATA[0], 2'bx};\n\tdefault: assign DIA = PORT_A_WR_DATA;\nendcase\n\ncase(PORT_B_WIDTH)\n\t1: assign DIB = {7'bx, PORT_B_WR_DATA[0], 1'bx};\n\t2: assign DIB = {3'bx, PORT_B_WR_DATA[1], 2'bx, PORT_B_WR_DATA[0], 2'bx};\n\tdefault: assign DIB = PORT_B_WR_DATA;\nendcase\n\nassign PORT_A_RD_DATA = DOA;\nassign PORT_B_RD_DATA = DOB;\n\nDP8KC #(\n\t.INITVAL_00(init_slice('h00)),\n\t.INITVAL_01(init_slice('h01)),\n\t.INITVAL_02(init_slice('h02)),\n\t.INITVAL_03(init_slice('h03)),\n\t.INITVAL_04(init_slice('h04)),\n\t.INITVAL_05(init_slice('h05)),\n\t.INITVAL_06(init_slice('h06)),\n\t.INITVAL_07(init_slice('h07)),\n\t.INITVAL_08(init_slice('h08)),\n\t.INITVAL_09(init_slice('h09)),\n\t.INITVAL_0A(init_slice('h0a)),\n\t.INITVAL_0B(init_slice('h0b)),\n\t.INITVAL_0C(init_slice('h0c)),\n\t.INITVAL_0D(init_slice('h0d)),\n\t.INITVAL_0E(init_slice('h0e)),\n\t.INITVAL_0F(init_slice('h0f)),\n\t.INITVAL_10(init_slice('h10)),\n\t.INITVAL_11(init_slice('h11)),\n\t.INITVAL_12(init_slice('h12)),\n\t.INITVAL_13(init_slice('h13)),\n\t.INITVAL_14(init_slice('h14)),\n\t.INITVAL_15(init_slice('h15)),\n\t.INITVAL_16(init_slice('h16)),\n\t.INITVAL_17(init_slice('h17)),\n\t.INITVAL_18(init_slice('h18)),\n\t.INITVAL_19(init_slice('h19)),\n\t.INITVAL_1A(init_slice('h1a)),\n\t.INITVAL_1B(init_slice('h1b)),\n\t.INITVAL_1C(init_slice('h1c)),\n\t.INITVAL_1D(init_slice('h1d)),\n\t.INITVAL_1E(init_slice('h1e)),\n\t.INITVAL_1F(init_slice('h1f)),\n\t.DATA_WIDTH_A(PORT_A_WIDTH),\n\t.DATA_WIDTH_B(PORT_B_WIDTH),\n\t.REGMODE_A(\"NOREG\"),\n\t.REGMODE_B(\"NOREG\"),\n\t.RESETMODE(OPTION_RESETMODE),\n\t.ASYNC_RESET_RELEASE(OPTION_RESETMODE),\n\t.CSDECODE_A(\"0b000\"),\n\t.CSDECODE_B(\"0b000\"),\n\t.WRITEMODE_A(PORT_A_OPTION_WRITEMODE),\n\t.WRITEMODE_B(PORT_B_OPTION_WRITEMODE),\n\t.GSR(\"AUTO\")\n) _TECHMAP_REPLACE_ (\n\t.CLKA(PORT_A_CLK),\n\t.WEA(PORT_A_WR_EN),\n\t.CEA(PORT_A_CLK_EN),\n\t.OCEA(1'b1),\n\t.RSTA(OPTION_RESETMODE == \"SYNC\" ? PORT_A_RD_SRST : PORT_A_RD_ARST),\n\t.CSA0(1'b0),\n\t.CSA1(1'b0),\n\t.CSA2(1'b0),\n\t.ADA0(PORT_A_WIDTH == 9 ? 1'b1 : PORT_A_ADDR[0]),\n\t.ADA1(PORT_A_ADDR[1]),\n\t.ADA2(PORT_A_ADDR[2]),\n\t.ADA3(PORT_A_ADDR[3]),\n\t.ADA4(PORT_A_ADDR[4]),\n\t.ADA5(PORT_A_ADDR[5]),\n\t.ADA6(PORT_A_ADDR[6]),\n\t.ADA7(PORT_A_ADDR[7]),\n\t.ADA8(PORT_A_ADDR[8]),\n\t.ADA9(PORT_A_ADDR[9]),\n\t.ADA10(PORT_A_ADDR[10]),\n\t.ADA11(PORT_A_ADDR[11]),\n\t.ADA12(PORT_A_ADDR[12]),\n\t.DIA0(DIA[0]),\n\t.DIA1(DIA[1]),\n\t.DIA2(DIA[2]),\n\t.DIA3(DIA[3]),\n\t.DIA4(DIA[4]),\n\t.DIA5(DIA[5]),\n\t.DIA6(DIA[6]),\n\t.DIA7(DIA[7]),\n\t.DIA8(DIA[8]),\n\t.DOA0(DOA[0]),\n\t.DOA1(DOA[1]),\n\t.DOA2(DOA[2]),\n\t.DOA3(DOA[3]),\n\t.DOA4(DOA[4]),\n\t.DOA5(DOA[5]),\n\t.DOA6(DOA[6]),\n\t.DOA7(DOA[7]),\n\t.DOA8(DOA[8]),\n\n\t.CLKB(PORT_B_CLK),\n\t.WEB(PORT_B_WR_EN),\n\t.CEB(PORT_B_CLK_EN),\n\t.OCEB(1'b1),\n\t.RSTB(OPTION_RESETMODE == \"SYNC\" ? PORT_B_RD_SRST : PORT_B_RD_ARST),\n\t.CSB0(1'b0),\n\t.CSB1(1'b0),\n\t.CSB2(1'b0),\n\t.ADB0(PORT_B_WIDTH == 9 ? 1'b1 : PORT_B_ADDR[0]),\n\t.ADB1(PORT_B_ADDR[1]),\n\t.ADB2(PORT_B_ADDR[2]),\n\t.ADB3(PORT_B_ADDR[3]),\n\t.ADB4(PORT_B_ADDR[4]),\n\t.ADB5(PORT_B_ADDR[5]),\n\t.ADB6(PORT_B_ADDR[6]),\n\t.ADB7(PORT_B_ADDR[7]),\n\t.ADB8(PORT_B_ADDR[8]),\n\t.ADB9(PORT_B_ADDR[9]),\n\t.ADB10(PORT_B_ADDR[10]),\n\t.ADB11(PORT_B_ADDR[11]),\n\t.ADB12(PORT_B_ADDR[12]),\n\t.DIB0(DIB[0]),\n\t.DIB1(DIB[1]),\n\t.DIB2(DIB[2]),\n\t.DIB3(DIB[3]),\n\t.DIB4(DIB[4]),\n\t.DIB5(DIB[5]),\n\t.DIB6(DIB[6]),\n\t.DIB7(DIB[7]),\n\t.DIB8(DIB[8]),\n\t.DOB0(DOB[0]),\n\t.DOB1(DOB[1]),\n\t.DOB2(DOB[2]),\n\t.DOB3(DOB[3]),\n\t.DOB4(DOB[4]),\n\t.DOB5(DOB[5]),\n\t.DOB6(DOB[6]),\n\t.DOB7(DOB[7]),\n\t.DOB8(DOB[8]),\n);\n\nendmodule\n\n\nmodule $__PDPW8KC_ (...);\n\nparameter INIT = 0;\nparameter OPTION_RESETMODE = \"SYNC\";\n\nparameter PORT_R_WIDTH = 18;\n\ninput PORT_R_CLK;\ninput PORT_R_CLK_EN;\ninput PORT_R_RD_SRST;\ninput PORT_R_RD_ARST;\ninput [12:0] PORT_R_ADDR;\noutput [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;\n\nparameter PORT_W_WIDTH = 18;\nparameter PORT_W_WR_EN_WIDTH = 2;\n\ninput PORT_W_CLK;\ninput PORT_W_CLK_EN;\ninput [12:0] PORT_W_ADDR;\ninput [PORT_W_WR_EN_WIDTH-1:0] PORT_W_WR_EN;\ninput [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;\n\nfunction [319:0] init_slice;\n\tinput integer idx;\n\tinteger i, j;\n\tinit_slice = 0;\n\tfor (i = 0; i < 16; i = i + 1) begin\n\t\tinit_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];\n\tend\nendfunction\n\nwire [17:0] DI = PORT_W_WR_DATA;\nwire [17:0] DO;\n\nassign PORT_R_RD_DATA = PORT_R_WIDTH == 18 ? DO : DO[17:9];\n\nDP8KC #(\n\t.INITVAL_00(init_slice('h00)),\n\t.INITVAL_01(init_slice('h01)),\n\t.INITVAL_02(init_slice('h02)),\n\t.INITVAL_03(init_slice('h03)),\n\t.INITVAL_04(init_slice('h04)),\n\t.INITVAL_05(init_slice('h05)),\n\t.INITVAL_06(init_slice('h06)),\n\t.INITVAL_07(init_slice('h07)),\n\t.INITVAL_08(init_slice('h08)),\n\t.INITVAL_09(init_slice('h09)),\n\t.INITVAL_0A(init_slice('h0a)),\n\t.INITVAL_0B(init_slice('h0b)),\n\t.INITVAL_0C(init_slice('h0c)),\n\t.INITVAL_0D(init_slice('h0d)),\n\t.INITVAL_0E(init_slice('h0e)),\n\t.INITVAL_0F(init_slice('h0f)),\n\t.INITVAL_10(init_slice('h10)),\n\t.INITVAL_11(init_slice('h11)),\n\t.INITVAL_12(init_slice('h12)),\n\t.INITVAL_13(init_slice('h13)),\n\t.INITVAL_14(init_slice('h14)),\n\t.INITVAL_15(init_slice('h15)),\n\t.INITVAL_16(init_slice('h16)),\n\t.INITVAL_17(init_slice('h17)),\n\t.INITVAL_18(init_slice('h18)),\n\t.INITVAL_19(init_slice('h19)),\n\t.INITVAL_1A(init_slice('h1a)),\n\t.INITVAL_1B(init_slice('h1b)),\n\t.INITVAL_1C(init_slice('h1c)),\n\t.INITVAL_1D(init_slice('h1d)),\n\t.INITVAL_1E(init_slice('h1e)),\n\t.INITVAL_1F(init_slice('h1f)),\n\t.DATA_WIDTH_A(PORT_W_WIDTH),\n\t.DATA_WIDTH_B(PORT_R_WIDTH),\n\t.REGMODE_A(\"NOREG\"),\n\t.REGMODE_B(\"NOREG\"),\n\t.RESETMODE(OPTION_RESETMODE),\n\t.ASYNC_RESET_RELEASE(OPTION_RESETMODE),\n\t.CSDECODE_A(\"0b000\"),\n\t.CSDECODE_B(\"0b000\"),\n\t.GSR(\"AUTO\")\n) _TECHMAP_REPLACE_ (\n\t.CLKA(PORT_W_CLK),\n\t.WEA(PORT_W_WIDTH >= 9 ? 1'b1 : PORT_W_WR_EN[0]),\n\t.CEA(PORT_W_CLK_EN),\n\t.OCEA(1'b0),\n\t.RSTA(1'b0),\n\t.CSA0(1'b0),\n\t.CSA1(1'b0),\n\t.CSA2(1'b0),\n\t.ADA0(PORT_W_WIDTH >= 9 ? PORT_W_WR_EN[0] : PORT_W_ADDR[0]),\n\t.ADA1(PORT_W_WIDTH >= 18 ? PORT_W_WR_EN[1] : PORT_W_ADDR[1]),\n\t.ADA2(PORT_W_ADDR[2]),\n\t.ADA3(PORT_W_ADDR[3]),\n\t.ADA4(PORT_W_ADDR[4]),\n\t.ADA5(PORT_W_ADDR[5]),\n\t.ADA6(PORT_W_ADDR[6]),\n\t.ADA7(PORT_W_ADDR[7]),\n\t.ADA8(PORT_W_ADDR[8]),\n\t.ADA9(PORT_W_ADDR[9]),\n\t.ADA10(PORT_W_ADDR[10]),\n\t.ADA11(PORT_W_ADDR[11]),\n\t.ADA12(PORT_W_ADDR[12]),\n\t.DIA0(DI[0]),\n\t.DIA1(DI[1]),\n\t.DIA2(DI[2]),\n\t.DIA3(DI[3]),\n\t.DIA4(DI[4]),\n\t.DIA5(DI[5]),\n\t.DIA6(DI[6]),\n\t.DIA7(DI[7]),\n\t.DIA8(DI[8]),\n\t.DIB0(DI[9]),\n\t.DIB1(DI[10]),\n\t.DIB2(DI[11]),\n\t.DIB3(DI[12]),\n\t.DIB4(DI[13]),\n\t.DIB5(DI[14]),\n\t.DIB6(DI[15]),\n\t.DIB7(DI[16]),\n\t.DIB8(DI[17]),\n\n\t.CLKB(PORT_R_CLK),\n\t.WEB(1'b0),\n\t.CEB(PORT_R_CLK_EN),\n\t.OCEB(1'b1),\n\t.RSTB(OPTION_RESETMODE == \"SYNC\" ? PORT_R_RD_SRST : PORT_R_RD_ARST),\n\t.CSB0(1'b0),\n\t.CSB1(1'b0),\n\t.CSB2(1'b0),\n\t.ADB0(PORT_R_ADDR[0]),\n\t.ADB1(PORT_R_ADDR[1]),\n\t.ADB2(PORT_R_ADDR[2]),\n\t.ADB3(PORT_R_ADDR[3]),\n\t.ADB4(PORT_R_ADDR[4]),\n\t.ADB5(PORT_R_ADDR[5]),\n\t.ADB6(PORT_R_ADDR[6]),\n\t.ADB7(PORT_R_ADDR[7]),\n\t.ADB8(PORT_R_ADDR[8]),\n\t.ADB9(PORT_R_ADDR[9]),\n\t.ADB10(PORT_R_ADDR[10]),\n\t.ADB11(PORT_R_ADDR[11]),\n\t.ADB12(PORT_R_ADDR[12]),\n\t.DOA0(DO[0]),\n\t.DOA1(DO[1]),\n\t.DOA2(DO[2]),\n\t.DOA3(DO[3]),\n\t.DOA4(DO[4]),\n\t.DOA5(DO[5]),\n\t.DOA6(DO[6]),\n\t.DOA7(DO[7]),\n\t.DOA8(DO[8]),\n\t.DOB0(DO[9]),\n\t.DOB1(DO[10]),\n\t.DOB2(DO[11]),\n\t.DOB3(DO[12]),\n\t.DOB4(DO[13]),\n\t.DOB5(DO[14]),\n\t.DOB6(DO[15]),\n\t.DOB7(DO[16]),\n\t.DOB8(DO[17]),\n);\n\nendmodule\n",
|
|
257
257
|
"ccu2c_sim.vh": "// ---------------------------------------\n(* abc9_box, lib_whitebox *)\nmodule CCU2C(\n\t(* abc9_carry *)\n\tinput CIN,\n\tinput A0, B0, C0, D0, A1, B1, C1, D1,\n\toutput S0, S1,\n\t(* abc9_carry *)\n\toutput COUT\n);\n\tparameter [15:0] INIT0 = 16'h0000;\n\tparameter [15:0] INIT1 = 16'h0000;\n\tparameter INJECT1_0 = \"YES\";\n\tparameter INJECT1_1 = \"YES\";\n\n\t// First half\n\twire LUT4_0, LUT2_0;\n\tLUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));\n\tLUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));\n\twire gated_cin_0 = (INJECT1_0 == \"YES\") ? 1'b0 : CIN;\n\tassign S0 = LUT4_0 ^ gated_cin_0;\n\n\twire gated_lut2_0 = (INJECT1_0 == \"YES\") ? 1'b0 : LUT2_0;\n\twire cout_0 = (~LUT4_0 & gated_lut2_0) | (LUT4_0 & CIN);\n\n\t// Second half\n\twire LUT4_1, LUT2_1;\n\tLUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));\n\tLUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));\n\twire gated_cin_1 = (INJECT1_1 == \"YES\") ? 1'b0 : cout_0;\n\tassign S1 = LUT4_1 ^ gated_cin_1;\n\n\twire gated_lut2_1 = (INJECT1_1 == \"YES\") ? 1'b0 : LUT2_1;\n\tassign COUT = (~LUT4_1 & gated_lut2_1) | (LUT4_1 & cout_0);\n\n\tspecify\n\t\t(A0 => S0) = 379;\n\t\t(B0 => S0) = 379;\n\t\t(C0 => S0) = 275;\n\t\t(D0 => S0) = 141;\n\t\t(CIN => S0) = 257;\n\t\t(A0 => S1) = 630;\n\t\t(B0 => S1) = 630;\n\t\t(C0 => S1) = 526;\n\t\t(D0 => S1) = 392;\n\t\t(A1 => S1) = 379;\n\t\t(B1 => S1) = 379;\n\t\t(C1 => S1) = 275;\n\t\t(D1 => S1) = 141;\n\t\t(CIN => S1) = 273;\n\t\t(A0 => COUT) = 516;\n\t\t(B0 => COUT) = 516;\n\t\t(C0 => COUT) = 412;\n\t\t(D0 => COUT) = 278;\n\t\t(A1 => COUT) = 516;\n\t\t(B1 => COUT) = 516;\n\t\t(C1 => COUT) = 412;\n\t\t(D1 => COUT) = 278;\n\t\t(CIN => COUT) = 43;\n\tendspecify\nendmodule\n",
|
|
258
258
|
"ccu2d_sim.vh": "// ---------------------------------------\n(* lib_whitebox *)\nmodule CCU2D (\n\tinput CIN,\n\tinput A0, B0, C0, D0, A1, B1, C1, D1,\n\toutput S0, S1,\n\toutput COUT\n);\n\tparameter [15:0] INIT0 = 16'h0000;\n\tparameter [15:0] INIT1 = 16'h0000;\n\tparameter INJECT1_0 = \"YES\";\n\tparameter INJECT1_1 = \"YES\";\n\n\t// First half\n\twire LUT4_0, LUT2_0;\n\tLUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));\n\tLUT2 #(.INIT(~INIT0[15:12])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));\n\twire gated_cin_0 = (INJECT1_0 == \"YES\") ? 1'b0 : CIN;\n\tassign S0 = LUT4_0 ^ gated_cin_0;\n\n\twire gated_lut2_0 = (INJECT1_0 == \"YES\") ? 1'b0 : LUT2_0;\n\twire cout_0 = (~LUT4_0 & gated_lut2_0) | (LUT4_0 & CIN);\n\n\t// Second half\n\twire LUT4_1, LUT2_1;\n\tLUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));\n\tLUT2 #(.INIT(~INIT1[15:12])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));\n\twire gated_cin_1 = (INJECT1_1 == \"YES\") ? 1'b0 : cout_0;\n\tassign S1 = LUT4_1 ^ gated_cin_1;\n\n\twire gated_lut2_1 = (INJECT1_1 == \"YES\") ? 1'b0 : LUT2_1;\n\tassign COUT = (~LUT4_1 & gated_lut2_1) | (LUT4_1 & cout_0);\nendmodule\n",
|
|
259
259
|
"cells_bb_ecp5.v": "// Created by cells_xtra.py from Lattice models\n\n(* blackbox *) (* keep *)\nmodule GSR (...);\n input GSR;\nendmodule\n\n(* blackbox *)\nmodule PUR (...);\n parameter RST_PULSE = 1;\n input PUR;\nendmodule\n\n(* blackbox *) (* keep *)\nmodule SGSR (...);\n input GSR;\n input CLK;\nendmodule\n\n(* blackbox *)\nmodule DP16KD (...);\n parameter DATA_WIDTH_A = 18;\n parameter DATA_WIDTH_B = 18;\n parameter REGMODE_A = \"NOREG\";\n parameter REGMODE_B = \"NOREG\";\n parameter RESETMODE = \"SYNC\";\n parameter ASYNC_RESET_RELEASE = \"SYNC\";\n parameter WRITEMODE_A = \"NORMAL\";\n parameter WRITEMODE_B = \"NORMAL\";\n parameter CSDECODE_A = \"0b000\";\n parameter CSDECODE_B = \"0b000\";\n parameter GSR = \"ENABLED\";\n parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INIT_DATA = \"STATIC\";\n input DIA17;\n input DIA16;\n input DIA15;\n input DIA14;\n input DIA13;\n input DIA12;\n input DIA11;\n input DIA10;\n input DIA9;\n input DIA8;\n input DIA7;\n input DIA6;\n input DIA5;\n input DIA4;\n input DIA3;\n input DIA2;\n input DIA1;\n input DIA0;\n input ADA13;\n input ADA12;\n input ADA11;\n input ADA10;\n input ADA9;\n input ADA8;\n input ADA7;\n input ADA6;\n input ADA5;\n input ADA4;\n input ADA3;\n input ADA2;\n input ADA1;\n input ADA0;\n input CEA;\n input OCEA;\n input CLKA;\n input WEA;\n input CSA2;\n input CSA1;\n input CSA0;\n input RSTA;\n input DIB17;\n input DIB16;\n input DIB15;\n input DIB14;\n input DIB13;\n input DIB12;\n input DIB11;\n input DIB10;\n input DIB9;\n input DIB8;\n input DIB7;\n input DIB6;\n input DIB5;\n input DIB4;\n input DIB3;\n input DIB2;\n input DIB1;\n input DIB0;\n input ADB13;\n input ADB12;\n input ADB11;\n input ADB10;\n input ADB9;\n input ADB8;\n input ADB7;\n input ADB6;\n input ADB5;\n input ADB4;\n input ADB3;\n input ADB2;\n input ADB1;\n input ADB0;\n input CEB;\n input OCEB;\n input CLKB;\n input WEB;\n input CSB2;\n input CSB1;\n input CSB0;\n input RSTB;\n output DOA17;\n output DOA16;\n output DOA15;\n output DOA14;\n output DOA13;\n output DOA12;\n output DOA11;\n output DOA10;\n output DOA9;\n output DOA8;\n output DOA7;\n output DOA6;\n output DOA5;\n output DOA4;\n output DOA3;\n output DOA2;\n output DOA1;\n output DOA0;\n output DOB17;\n output DOB16;\n output DOB15;\n output DOB14;\n output DOB13;\n output DOB12;\n output DOB11;\n output DOB10;\n output DOB9;\n output DOB8;\n output DOB7;\n output DOB6;\n output DOB5;\n output DOB4;\n output DOB3;\n output DOB2;\n output DOB1;\n output DOB0;\nendmodule\n\n(* blackbox *)\nmodule PDPW16KD (...);\n parameter DATA_WIDTH_W = 36;\n parameter DATA_WIDTH_R = 36;\n parameter GSR = \"ENABLED\";\n parameter REGMODE = \"NOREG\";\n parameter RESETMODE = \"SYNC\";\n parameter ASYNC_RESET_RELEASE = \"SYNC\";\n parameter CSDECODE_W = \"0b000\";\n parameter CSDECODE_R = \"0b000\";\n parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;\n parameter INIT_DATA = \"STATIC\";\n input DI35;\n input DI34;\n input DI33;\n input DI32;\n input DI31;\n input DI30;\n input DI29;\n input DI28;\n input DI27;\n input DI26;\n input DI25;\n input DI24;\n input DI23;\n input DI22;\n input DI21;\n input DI20;\n input DI19;\n input DI18;\n input DI17;\n input DI16;\n input DI15;\n input DI14;\n input DI13;\n input DI12;\n input DI11;\n input DI10;\n input DI9;\n input DI8;\n input DI7;\n input DI6;\n input DI5;\n input DI4;\n input DI3;\n input DI2;\n input DI1;\n input DI0;\n input ADW8;\n input ADW7;\n input ADW6;\n input ADW5;\n input ADW4;\n input ADW3;\n input ADW2;\n input ADW1;\n input ADW0;\n input BE3;\n input BE2;\n input BE1;\n input BE0;\n input CEW;\n input CLKW;\n input CSW2;\n input CSW1;\n input CSW0;\n input ADR13;\n input ADR12;\n input ADR11;\n input ADR10;\n input ADR9;\n input ADR8;\n input ADR7;\n input ADR6;\n input ADR5;\n input ADR4;\n input ADR3;\n input ADR2;\n input ADR1;\n input ADR0;\n input CER;\n input OCER;\n input CLKR;\n input CSR2;\n input CSR1;\n input CSR0;\n input RST;\n output DO35;\n output DO34;\n output DO33;\n output DO32;\n output DO31;\n output DO30;\n output DO29;\n output DO28;\n output DO27;\n output DO26;\n output DO25;\n output DO24;\n output DO23;\n output DO22;\n output DO21;\n output DO20;\n output DO19;\n output DO18;\n output DO17;\n output DO16;\n output DO15;\n output DO14;\n output DO13;\n output DO12;\n output DO11;\n output DO10;\n output DO9;\n output DO8;\n output DO7;\n output DO6;\n output DO5;\n output DO4;\n output DO3;\n output DO2;\n output DO1;\n output DO0;\nendmodule\n\n(* blackbox *)\nmodule MULT18X18D (...);\n parameter REG_INPUTA_CLK = \"NONE\";\n parameter REG_INPUTA_CE = \"CE0\";\n parameter REG_INPUTA_RST = \"RST0\";\n parameter REG_INPUTB_CLK = \"NONE\";\n parameter REG_INPUTB_CE = \"CE0\";\n parameter REG_INPUTB_RST = \"RST0\";\n parameter REG_INPUTC_CLK = \"NONE\";\n parameter REG_INPUTC_CE = \"CE0\";\n parameter REG_INPUTC_RST = \"RST0\";\n parameter REG_PIPELINE_CLK = \"NONE\";\n parameter REG_PIPELINE_CE = \"CE0\";\n parameter REG_PIPELINE_RST = \"RST0\";\n parameter REG_OUTPUT_CLK = \"NONE\";\n parameter REG_OUTPUT_CE = \"CE0\";\n parameter REG_OUTPUT_RST = \"RST0\";\n parameter CLK0_DIV = \"ENABLED\";\n parameter CLK1_DIV = \"ENABLED\";\n parameter CLK2_DIV = \"ENABLED\";\n parameter CLK3_DIV = \"ENABLED\";\n parameter HIGHSPEED_CLK = \"NONE\";\n parameter GSR = \"ENABLED\";\n parameter CAS_MATCH_REG = \"FALSE\";\n parameter SOURCEB_MODE = \"B_SHIFT\";\n parameter MULT_BYPASS = \"DISABLED\";\n parameter RESETMODE = \"SYNC\";\n input A17;\n input A16;\n input A15;\n input A14;\n input A13;\n input A12;\n input A11;\n input A10;\n input A9;\n input A8;\n input A7;\n input A6;\n input A5;\n input A4;\n input A3;\n input A2;\n input A1;\n input A0;\n input B17;\n input B16;\n input B15;\n input B14;\n input B13;\n input B12;\n input B11;\n input B10;\n input B9;\n input B8;\n input B7;\n input B6;\n input B5;\n input B4;\n input B3;\n input B2;\n input B1;\n input B0;\n input C17;\n input C16;\n input C15;\n input C14;\n input C13;\n input C12;\n input C11;\n input C10;\n input C9;\n input C8;\n input C7;\n input C6;\n input C5;\n input C4;\n input C3;\n input C2;\n input C1;\n input C0;\n input SIGNEDA;\n input SIGNEDB;\n input SOURCEA;\n input SOURCEB;\n input CLK3;\n input CLK2;\n input CLK1;\n input CLK0;\n input CE3;\n input CE2;\n input CE1;\n input CE0;\n input RST3;\n input RST2;\n input RST1;\n input RST0;\n input SRIA17;\n input SRIA16;\n input SRIA15;\n input SRIA14;\n input SRIA13;\n input SRIA12;\n input SRIA11;\n input SRIA10;\n input SRIA9;\n input SRIA8;\n input SRIA7;\n input SRIA6;\n input SRIA5;\n input SRIA4;\n input SRIA3;\n input SRIA2;\n input SRIA1;\n input SRIA0;\n input SRIB17;\n input SRIB16;\n input SRIB15;\n input SRIB14;\n input SRIB13;\n input SRIB12;\n input SRIB11;\n input SRIB10;\n input SRIB9;\n input SRIB8;\n input SRIB7;\n input SRIB6;\n input SRIB5;\n input SRIB4;\n input SRIB3;\n input SRIB2;\n input SRIB1;\n input SRIB0;\n output SROA17;\n output SROA16;\n output SROA15;\n output SROA14;\n output SROA13;\n output SROA12;\n output SROA11;\n output SROA10;\n output SROA9;\n output SROA8;\n output SROA7;\n output SROA6;\n output SROA5;\n output SROA4;\n output SROA3;\n output SROA2;\n output SROA1;\n output SROA0;\n output SROB17;\n output SROB16;\n output SROB15;\n output SROB14;\n output SROB13;\n output SROB12;\n output SROB11;\n output SROB10;\n output SROB9;\n output SROB8;\n output SROB7;\n output SROB6;\n output SROB5;\n output SROB4;\n output SROB3;\n output SROB2;\n output SROB1;\n output SROB0;\n output ROA17;\n output ROA16;\n output ROA15;\n output ROA14;\n output ROA13;\n output ROA12;\n output ROA11;\n output ROA10;\n output ROA9;\n output ROA8;\n output ROA7;\n output ROA6;\n output ROA5;\n output ROA4;\n output ROA3;\n output ROA2;\n output ROA1;\n output ROA0;\n output ROB17;\n output ROB16;\n output ROB15;\n output ROB14;\n output ROB13;\n output ROB12;\n output ROB11;\n output ROB10;\n output ROB9;\n output ROB8;\n output ROB7;\n output ROB6;\n output ROB5;\n output ROB4;\n output ROB3;\n output ROB2;\n output ROB1;\n output ROB0;\n output ROC17;\n output ROC16;\n output ROC15;\n output ROC14;\n output ROC13;\n output ROC12;\n output ROC11;\n output ROC10;\n output ROC9;\n output ROC8;\n output ROC7;\n output ROC6;\n output ROC5;\n output ROC4;\n output ROC3;\n output ROC2;\n output ROC1;\n output ROC0;\n output P35;\n output P34;\n output P33;\n output P32;\n output P31;\n output P30;\n output P29;\n output P28;\n output P27;\n output P26;\n output P25;\n output P24;\n output P23;\n output P22;\n output P21;\n output P20;\n output P19;\n output P18;\n output P17;\n output P16;\n output P15;\n output P14;\n output P13;\n output P12;\n output P11;\n output P10;\n output P9;\n output P8;\n output P7;\n output P6;\n output P5;\n output P4;\n output P3;\n output P2;\n output P1;\n output P0;\n output SIGNEDP;\nendmodule\n\n(* blackbox *)\nmodule ALU54B (...);\n parameter REG_INPUTC0_CLK = \"NONE\";\n parameter REG_INPUTC0_CE = \"CE0\";\n parameter REG_INPUTC0_RST = \"RST0\";\n parameter REG_INPUTC1_CLK = \"NONE\";\n parameter REG_INPUTC1_CE = \"CE0\";\n parameter REG_INPUTC1_RST = \"RST0\";\n parameter REG_OPCODEOP0_0_CLK = \"NONE\";\n parameter REG_OPCODEOP0_0_CE = \"CE0\";\n parameter REG_OPCODEOP0_0_RST = \"RST0\";\n parameter REG_OPCODEOP1_0_CLK = \"NONE\";\n parameter REG_OPCODEOP0_1_CLK = \"NONE\";\n parameter REG_OPCODEOP0_1_CE = \"CE0\";\n parameter REG_OPCODEOP0_1_RST = \"RST0\";\n parameter REG_OPCODEOP1_1_CLK = \"NONE\";\n parameter REG_OPCODEIN_0_CLK = \"NONE\";\n parameter REG_OPCODEIN_0_CE = \"CE0\";\n parameter REG_OPCODEIN_0_RST = \"RST0\";\n parameter REG_OPCODEIN_1_CLK = \"NONE\";\n parameter REG_OPCODEIN_1_CE = \"CE0\";\n parameter REG_OPCODEIN_1_RST = \"RST0\";\n parameter REG_OUTPUT0_CLK = \"NONE\";\n parameter REG_OUTPUT0_CE = \"CE0\";\n parameter REG_OUTPUT0_RST = \"RST0\";\n parameter REG_OUTPUT1_CLK = \"NONE\";\n parameter REG_OUTPUT1_CE = \"CE0\";\n parameter REG_OUTPUT1_RST = \"RST0\";\n parameter REG_FLAG_CLK = \"NONE\";\n parameter REG_FLAG_CE = \"CE0\";\n parameter REG_FLAG_RST = \"RST0\";\n parameter MCPAT_SOURCE = \"STATIC\";\n parameter MASKPAT_SOURCE = \"STATIC\";\n parameter MASK01 = \"0x00000000000000\";\n parameter REG_INPUTCFB_CLK = \"NONE\";\n parameter REG_INPUTCFB_CE = \"CE0\";\n parameter REG_INPUTCFB_RST = \"RST0\";\n parameter CLK0_DIV = \"ENABLED\";\n parameter CLK1_DIV = \"ENABLED\";\n parameter CLK2_DIV = \"ENABLED\";\n parameter CLK3_DIV = \"ENABLED\";\n parameter MCPAT = \"0x00000000000000\";\n parameter MASKPAT = \"0x00000000000000\";\n parameter RNDPAT = \"0x00000000000000\";\n parameter GSR = \"ENABLED\";\n parameter RESETMODE = \"SYNC\";\n parameter MULT9_MODE = \"DISABLED\";\n parameter FORCE_ZERO_BARREL_SHIFT = \"DISABLED\";\n parameter LEGACY = \"DISABLED\";\n input CE3;\n input CE2;\n input CE1;\n input CE0;\n input CLK3;\n input CLK2;\n input CLK1;\n input CLK0;\n input RST3;\n input RST2;\n input RST1;\n input RST0;\n input SIGNEDIA;\n input SIGNEDIB;\n input SIGNEDCIN;\n input A35;\n input A34;\n input A33;\n input A32;\n input A31;\n input A30;\n input A29;\n input A28;\n input A27;\n input A26;\n input A25;\n input A24;\n input A23;\n input A22;\n input A21;\n input A20;\n input A19;\n input A18;\n input A17;\n input A16;\n input A15;\n input A14;\n input A13;\n input A12;\n input A11;\n input A10;\n input A9;\n input A8;\n input A7;\n input A6;\n input A5;\n input A4;\n input A3;\n input A2;\n input A1;\n input A0;\n input B35;\n input B34;\n input B33;\n input B32;\n input B31;\n input B30;\n input B29;\n input B28;\n input B27;\n input B26;\n input B25;\n input B24;\n input B23;\n input B22;\n input B21;\n input B20;\n input B19;\n input B18;\n input B17;\n input B16;\n input B15;\n input B14;\n input B13;\n input B12;\n input B11;\n input B10;\n input B9;\n input B8;\n input B7;\n input B6;\n input B5;\n input B4;\n input B3;\n input B2;\n input B1;\n input B0;\n input C53;\n input C52;\n input C51;\n input C50;\n input C49;\n input C48;\n input C47;\n input C46;\n input C45;\n input C44;\n input C43;\n input C42;\n input C41;\n input C40;\n input C39;\n input C38;\n input C37;\n input C36;\n input C35;\n input C34;\n input C33;\n input C32;\n input C31;\n input C30;\n input C29;\n input C28;\n input C27;\n input C26;\n input C25;\n input C24;\n input C23;\n input C22;\n input C21;\n input C20;\n input C19;\n input C18;\n input C17;\n input C16;\n input C15;\n input C14;\n input C13;\n input C12;\n input C11;\n input C10;\n input C9;\n input C8;\n input C7;\n input C6;\n input C5;\n input C4;\n input C3;\n input C2;\n input C1;\n input C0;\n input CFB53;\n input CFB52;\n input CFB51;\n input CFB50;\n input CFB49;\n input CFB48;\n input CFB47;\n input CFB46;\n input CFB45;\n input CFB44;\n input CFB43;\n input CFB42;\n input CFB41;\n input CFB40;\n input CFB39;\n input CFB38;\n input CFB37;\n input CFB36;\n input CFB35;\n input CFB34;\n input CFB33;\n input CFB32;\n input CFB31;\n input CFB30;\n input CFB29;\n input CFB28;\n input CFB27;\n input CFB26;\n input CFB25;\n input CFB24;\n input CFB23;\n input CFB22;\n input CFB21;\n input CFB20;\n input CFB19;\n input CFB18;\n input CFB17;\n input CFB16;\n input CFB15;\n input CFB14;\n input CFB13;\n input CFB12;\n input CFB11;\n input CFB10;\n input CFB9;\n input CFB8;\n input CFB7;\n input CFB6;\n input CFB5;\n input CFB4;\n input CFB3;\n input CFB2;\n input CFB1;\n input CFB0;\n input MA35;\n input MA34;\n input MA33;\n input MA32;\n input MA31;\n input MA30;\n input MA29;\n input MA28;\n input MA27;\n input MA26;\n input MA25;\n input MA24;\n input MA23;\n input MA22;\n input MA21;\n input MA20;\n input MA19;\n input MA18;\n input MA17;\n input MA16;\n input MA15;\n input MA14;\n input MA13;\n input MA12;\n input MA11;\n input MA10;\n input MA9;\n input MA8;\n input MA7;\n input MA6;\n input MA5;\n input MA4;\n input MA3;\n input MA2;\n input MA1;\n input MA0;\n input MB35;\n input MB34;\n input MB33;\n input MB32;\n input MB31;\n input MB30;\n input MB29;\n input MB28;\n input MB27;\n input MB26;\n input MB25;\n input MB24;\n input MB23;\n input MB22;\n input MB21;\n input MB20;\n input MB19;\n input MB18;\n input MB17;\n input MB16;\n input MB15;\n input MB14;\n input MB13;\n input MB12;\n input MB11;\n input MB10;\n input MB9;\n input MB8;\n input MB7;\n input MB6;\n input MB5;\n input MB4;\n input MB3;\n input MB2;\n input MB1;\n input MB0;\n input CIN53;\n input CIN52;\n input CIN51;\n input CIN50;\n input CIN49;\n input CIN48;\n input CIN47;\n input CIN46;\n input CIN45;\n input CIN44;\n input CIN43;\n input CIN42;\n input CIN41;\n input CIN40;\n input CIN39;\n input CIN38;\n input CIN37;\n input CIN36;\n input CIN35;\n input CIN34;\n input CIN33;\n input CIN32;\n input CIN31;\n input CIN30;\n input CIN29;\n input CIN28;\n input CIN27;\n input CIN26;\n input CIN25;\n input CIN24;\n input CIN23;\n input CIN22;\n input CIN21;\n input CIN20;\n input CIN19;\n input CIN18;\n input CIN17;\n input CIN16;\n input CIN15;\n input CIN14;\n input CIN13;\n input CIN12;\n input CIN11;\n input CIN10;\n input CIN9;\n input CIN8;\n input CIN7;\n input CIN6;\n input CIN5;\n input CIN4;\n input CIN3;\n input CIN2;\n input CIN1;\n input CIN0;\n input OP10;\n input OP9;\n input OP8;\n input OP7;\n input OP6;\n input OP5;\n input OP4;\n input OP3;\n input OP2;\n input OP1;\n input OP0;\n output R53;\n output R52;\n output R51;\n output R50;\n output R49;\n output R48;\n output R47;\n output R46;\n output R45;\n output R44;\n output R43;\n output R42;\n output R41;\n output R40;\n output R39;\n output R38;\n output R37;\n output R36;\n output R35;\n output R34;\n output R33;\n output R32;\n output R31;\n output R30;\n output R29;\n output R28;\n output R27;\n output R26;\n output R25;\n output R24;\n output R23;\n output R22;\n output R21;\n output R20;\n output R19;\n output R18;\n output R17;\n output R16;\n output R15;\n output R14;\n output R13;\n output R12;\n output R11;\n output R10;\n output R9;\n output R8;\n output R7;\n output R6;\n output R5;\n output R4;\n output R3;\n output R2;\n output R1;\n output R0;\n output CO53;\n output CO52;\n output CO51;\n output CO50;\n output CO49;\n output CO48;\n output CO47;\n output CO46;\n output CO45;\n output CO44;\n output CO43;\n output CO42;\n output CO41;\n output CO40;\n output CO39;\n output CO38;\n output CO37;\n output CO36;\n output CO35;\n output CO34;\n output CO33;\n output CO32;\n output CO31;\n output CO30;\n output CO29;\n output CO28;\n output CO27;\n output CO26;\n output CO25;\n output CO24;\n output CO23;\n output CO22;\n output CO21;\n output CO20;\n output CO19;\n output CO18;\n output CO17;\n output CO16;\n output CO15;\n output CO14;\n output CO13;\n output CO12;\n output CO11;\n output CO10;\n output CO9;\n output CO8;\n output CO7;\n output CO6;\n output CO5;\n output CO4;\n output CO3;\n output CO2;\n output CO1;\n output CO0;\n output EQZ;\n output EQZM;\n output EQOM;\n output EQPAT;\n output EQPATB;\n output OVER;\n output UNDER;\n output OVERUNDER;\n output SIGNEDR;\nendmodule\n\n(* blackbox *)\nmodule CLKDIVF (...);\n parameter GSR = \"DISABLED\";\n parameter DIV = \"2.0\";\n input CLKI;\n input RST;\n input ALIGNWD;\n output CDIVX;\nendmodule\n\n(* blackbox *)\nmodule PCSCLKDIV (...);\n parameter GSR = \"DISABLED\";\n input CLKI;\n input RST;\n input SEL2;\n input SEL1;\n input SEL0;\n output CDIV1;\n output CDIVX;\nendmodule\n\n(* blackbox *)\nmodule DCSC (...);\n parameter DCSMODE = \"POS\";\n input CLK1;\n input CLK0;\n input SEL1;\n input SEL0;\n input MODESEL;\n output DCSOUT;\nendmodule\n\n(* blackbox *)\nmodule DCCA (...);\n input CLKI;\n input CE;\n output CLKO;\nendmodule\n\n(* blackbox *)\nmodule ECLKSYNCB (...);\n input ECLKI;\n input STOP;\n output ECLKO;\nendmodule\n\n(* blackbox *)\nmodule ECLKBRIDGECS (...);\n input CLK0;\n input CLK1;\n input SEL;\n output ECSOUT;\nendmodule\n\n(* blackbox *)\nmodule DELAYF (...);\n parameter DEL_MODE = \"USER_DEFINED\";\n parameter DEL_VALUE = 0;\n input A;\n input LOADN;\n input MOVE;\n input DIRECTION;\n output Z;\n output CFLAG;\nendmodule\n\n(* blackbox *)\nmodule DELAYG (...);\n parameter DEL_MODE = \"USER_DEFINED\";\n parameter DEL_VALUE = 0;\n input A;\n output Z;\nendmodule\n\n(* blackbox *) (* keep *)\nmodule USRMCLK (...);\n input USRMCLKI;\n input USRMCLKTS;\nendmodule\n\n(* blackbox *)\nmodule DQSBUFM (...);\n parameter DQS_LI_DEL_VAL = 4;\n parameter DQS_LI_DEL_ADJ = \"FACTORYONLY\";\n parameter DQS_LO_DEL_VAL = 0;\n parameter DQS_LO_DEL_ADJ = \"FACTORYONLY\";\n parameter GSR = \"ENABLED\";\n input DQSI;\n input READ1;\n input READ0;\n input READCLKSEL2;\n input READCLKSEL1;\n input READCLKSEL0;\n input DDRDEL;\n input ECLK;\n input SCLK;\n input RST;\n input DYNDELAY7;\n input DYNDELAY6;\n input DYNDELAY5;\n input DYNDELAY4;\n input DYNDELAY3;\n input DYNDELAY2;\n input DYNDELAY1;\n input DYNDELAY0;\n input PAUSE;\n input RDLOADN;\n input RDMOVE;\n input RDDIRECTION;\n input WRLOADN;\n input WRMOVE;\n input WRDIRECTION;\n output DQSR90;\n output DQSW;\n output DQSW270;\n output RDPNTR2;\n output RDPNTR1;\n output RDPNTR0;\n output WRPNTR2;\n output WRPNTR1;\n output WRPNTR0;\n output DATAVALID;\n output BURSTDET;\n output RDCFLAG;\n output WRCFLAG;\nendmodule\n\n(* blackbox *)\nmodule DDRDLLA (...);\n parameter FORCE_MAX_DELAY = \"NO\";\n parameter GSR = \"ENABLED\";\n input CLK;\n input RST;\n input UDDCNTLN;\n input FREEZE;\n output DDRDEL;\n output LOCK;\n output DCNTL7;\n output DCNTL6;\n output DCNTL5;\n output DCNTL4;\n output DCNTL3;\n output DCNTL2;\n output DCNTL1;\n output DCNTL0;\nendmodule\n\n(* blackbox *)\nmodule DLLDELD (...);\n input A;\n input DDRDEL;\n input LOADN;\n input MOVE;\n input DIRECTION;\n output Z;\n output CFLAG;\nendmodule\n\n(* blackbox *)\nmodule IDDRX1F (...);\n parameter GSR = \"ENABLED\";\n input D;\n input SCLK;\n input RST;\n output Q0;\n output Q1;\nendmodule\n\n(* blackbox *)\nmodule IDDRX2F (...);\n parameter GSR = \"ENABLED\";\n input D;\n input SCLK;\n input ECLK;\n input RST;\n input ALIGNWD;\n output Q3;\n output Q2;\n output Q1;\n output Q0;\nendmodule\n\n(* blackbox *)\nmodule IDDR71B (...);\n parameter GSR = \"ENABLED\";\n input D;\n input SCLK;\n input ECLK;\n input RST;\n input ALIGNWD;\n output Q6;\n output Q5;\n output Q4;\n output Q3;\n output Q2;\n output Q1;\n output Q0;\nendmodule\n\n(* blackbox *)\nmodule IDDRX2DQA (...);\n parameter GSR = \"ENABLED\";\n input SCLK;\n input ECLK;\n input DQSR90;\n input D;\n input RST;\n input RDPNTR2;\n input RDPNTR1;\n input RDPNTR0;\n input WRPNTR2;\n input WRPNTR1;\n input WRPNTR0;\n output Q3;\n output Q2;\n output Q1;\n output Q0;\n output QWL;\nendmodule\n\n(* blackbox *)\nmodule ODDRX1F (...);\n parameter GSR = \"ENABLED\";\n input SCLK;\n input RST;\n input D0;\n input D1;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule ODDRX2F (...);\n parameter GSR = \"ENABLED\";\n input SCLK;\n input ECLK;\n input RST;\n input D3;\n input D2;\n input D1;\n input D0;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule ODDR71B (...);\n parameter GSR = \"ENABLED\";\n input SCLK;\n input ECLK;\n input RST;\n input D6;\n input D5;\n input D4;\n input D3;\n input D2;\n input D1;\n input D0;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule OSHX2A (...);\n parameter GSR = \"ENABLED\";\n input D1;\n input D0;\n input SCLK;\n input ECLK;\n input RST;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule TSHX2DQA (...);\n parameter GSR = \"ENABLED\";\n parameter REGSET = \"SET\";\n input T1;\n input T0;\n input SCLK;\n input ECLK;\n input DQSW270;\n input RST;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule TSHX2DQSA (...);\n parameter GSR = \"ENABLED\";\n parameter REGSET = \"SET\";\n input T1;\n input T0;\n input SCLK;\n input ECLK;\n input DQSW;\n input RST;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule ODDRX2DQA (...);\n parameter GSR = \"ENABLED\";\n input D3;\n input D2;\n input D1;\n input D0;\n input DQSW270;\n input SCLK;\n input ECLK;\n input RST;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule ODDRX2DQSB (...);\n parameter GSR = \"ENABLED\";\n input D3;\n input D2;\n input D1;\n input D0;\n input SCLK;\n input ECLK;\n input DQSW;\n input RST;\n output Q;\nendmodule\n\n(* blackbox *)\nmodule EHXPLLL (...);\n parameter CLKI_DIV = 1;\n parameter CLKFB_DIV = 1;\n parameter CLKOP_DIV = 8;\n parameter CLKOS_DIV = 8;\n parameter CLKOS2_DIV = 8;\n parameter CLKOS3_DIV = 8;\n parameter CLKOP_ENABLE = \"ENABLED\";\n parameter CLKOS_ENABLE = \"DISABLED\";\n parameter CLKOS2_ENABLE = \"DISABLED\";\n parameter CLKOS3_ENABLE = \"DISABLED\";\n parameter CLKOP_CPHASE = 0;\n parameter CLKOS_CPHASE = 0;\n parameter CLKOS2_CPHASE = 0;\n parameter CLKOS3_CPHASE = 0;\n parameter CLKOP_FPHASE = 0;\n parameter CLKOS_FPHASE = 0;\n parameter CLKOS2_FPHASE = 0;\n parameter CLKOS3_FPHASE = 0;\n parameter FEEDBK_PATH = \"CLKOP\";\n parameter CLKOP_TRIM_POL = \"RISING\";\n parameter CLKOP_TRIM_DELAY = 0;\n parameter CLKOS_TRIM_POL = \"RISING\";\n parameter CLKOS_TRIM_DELAY = 0;\n parameter OUTDIVIDER_MUXA = \"DIVA\";\n parameter OUTDIVIDER_MUXB = \"DIVB\";\n parameter OUTDIVIDER_MUXC = \"DIVC\";\n parameter OUTDIVIDER_MUXD = \"DIVD\";\n parameter PLL_LOCK_MODE = 0;\n parameter PLL_LOCK_DELAY = 200;\n parameter STDBY_ENABLE = \"DISABLED\";\n parameter REFIN_RESET = \"DISABLED\";\n parameter SYNC_ENABLE = \"DISABLED\";\n parameter INT_LOCK_STICKY = \"ENABLED\";\n parameter DPHASE_SOURCE = \"DISABLED\";\n parameter PLLRST_ENA = \"DISABLED\";\n parameter INTFB_WAKE = \"DISABLED\";\n input CLKI;\n input CLKFB;\n input PHASESEL1;\n input PHASESEL0;\n input PHASEDIR;\n input PHASESTEP;\n input PHASELOADREG;\n input STDBY;\n input PLLWAKESYNC;\n input RST;\n input ENCLKOP;\n input ENCLKOS;\n input ENCLKOS2;\n input ENCLKOS3;\n output CLKOP;\n output CLKOS;\n output CLKOS2;\n output CLKOS3;\n output LOCK;\n output INTLOCK;\n output REFCLK;\n output CLKINTFB;\nendmodule\n\n(* blackbox *)\nmodule DTR (...);\n parameter DTR_TEMP = 25;\n input STARTPULSE;\n output DTROUT7;\n output DTROUT6;\n output DTROUT5;\n output DTROUT4;\n output DTROUT3;\n output DTROUT2;\n output DTROUT1;\n output DTROUT0;\nendmodule\n\n(* blackbox *)\nmodule OSCG (...);\n parameter DIV = 128;\n output OSC;\nendmodule\n\n(* blackbox *)\nmodule EXTREFB (...);\n parameter REFCK_PWDNB = \"DONTCARE\";\n parameter REFCK_RTERM = \"DONTCARE\";\n parameter REFCK_DCBIAS_EN = \"DONTCARE\";\n (* iopad_external_pin *)\n input REFCLKP;\n (* iopad_external_pin *)\n input REFCLKN;\n output REFCLKO;\nendmodule\n\n(* blackbox *) (* keep *)\nmodule JTAGG (...);\n parameter ER1 = \"ENABLED\";\n parameter ER2 = \"ENABLED\";\n (* iopad_external_pin *)\n input TCK;\n (* iopad_external_pin *)\n input TMS;\n (* iopad_external_pin *)\n input TDI;\n input JTDO2;\n input JTDO1;\n (* iopad_external_pin *)\n output TDO;\n output JTDI;\n output JTCK;\n output JRTI2;\n output JRTI1;\n output JSHIFT;\n output JUPDATE;\n output JRSTN;\n output JCE2;\n output JCE1;\nendmodule\n\n(* blackbox *) (* keep *)\nmodule DCUA (...);\n parameter D_MACROPDB = \"DONTCARE\";\n parameter D_IB_PWDNB = \"DONTCARE\";\n parameter D_XGE_MODE = \"DONTCARE\";\n parameter D_LOW_MARK = \"DONTCARE\";\n parameter D_HIGH_MARK = \"DONTCARE\";\n parameter D_BUS8BIT_SEL = \"DONTCARE\";\n parameter D_CDR_LOL_SET = \"DONTCARE\";\n parameter D_BITCLK_LOCAL_EN = \"DONTCARE\";\n parameter D_BITCLK_ND_EN = \"DONTCARE\";\n parameter D_BITCLK_FROM_ND_EN = \"DONTCARE\";\n parameter D_SYNC_LOCAL_EN = \"DONTCARE\";\n parameter D_SYNC_ND_EN = \"DONTCARE\";\n parameter CH0_UC_MODE = \"DONTCARE\";\n parameter CH1_UC_MODE = \"DONTCARE\";\n parameter CH0_PCIE_MODE = \"DONTCARE\";\n parameter CH1_PCIE_MODE = \"DONTCARE\";\n parameter CH0_RIO_MODE = \"DONTCARE\";\n parameter CH1_RIO_MODE = \"DONTCARE\";\n parameter CH0_WA_MODE = \"DONTCARE\";\n parameter CH1_WA_MODE = \"DONTCARE\";\n parameter CH0_INVERT_RX = \"DONTCARE\";\n parameter CH1_INVERT_RX = \"DONTCARE\";\n parameter CH0_INVERT_TX = \"DONTCARE\";\n parameter CH1_INVERT_TX = \"DONTCARE\";\n parameter CH0_PRBS_SELECTION = \"DONTCARE\";\n parameter CH1_PRBS_SELECTION = \"DONTCARE\";\n parameter CH0_GE_AN_ENABLE = \"DONTCARE\";\n parameter CH1_GE_AN_ENABLE = \"DONTCARE\";\n parameter CH0_PRBS_LOCK = \"DONTCARE\";\n parameter CH1_PRBS_LOCK = \"DONTCARE\";\n parameter CH0_PRBS_ENABLE = \"DONTCARE\";\n parameter CH1_PRBS_ENABLE = \"DONTCARE\";\n parameter CH0_ENABLE_CG_ALIGN = \"DONTCARE\";\n parameter CH1_ENABLE_CG_ALIGN = \"DONTCARE\";\n parameter CH0_TX_GEAR_MODE = \"DONTCARE\";\n parameter CH1_TX_GEAR_MODE = \"DONTCARE\";\n parameter CH0_RX_GEAR_MODE = \"DONTCARE\";\n parameter CH1_RX_GEAR_MODE = \"DONTCARE\";\n parameter CH0_PCS_DET_TIME_SEL = \"DONTCARE\";\n parameter CH1_PCS_DET_TIME_SEL = \"DONTCARE\";\n parameter CH0_PCIE_EI_EN = \"DONTCARE\";\n parameter CH1_PCIE_EI_EN = \"DONTCARE\";\n parameter CH0_TX_GEAR_BYPASS = \"DONTCARE\";\n parameter CH1_TX_GEAR_BYPASS = \"DONTCARE\";\n parameter CH0_ENC_BYPASS = \"DONTCARE\";\n parameter CH1_ENC_BYPASS = \"DONTCARE\";\n parameter CH0_SB_BYPASS = \"DONTCARE\";\n parameter CH1_SB_BYPASS = \"DONTCARE\";\n parameter CH0_RX_SB_BYPASS = \"DONTCARE\";\n parameter CH1_RX_SB_BYPASS = \"DONTCARE\";\n parameter CH0_WA_BYPASS = \"DONTCARE\";\n parameter CH1_WA_BYPASS = \"DONTCARE\";\n parameter CH0_DEC_BYPASS = \"DONTCARE\";\n parameter CH1_DEC_BYPASS = \"DONTCARE\";\n parameter CH0_CTC_BYPASS = \"DONTCARE\";\n parameter CH1_CTC_BYPASS = \"DONTCARE\";\n parameter CH0_RX_GEAR_BYPASS = \"DONTCARE\";\n parameter CH1_RX_GEAR_BYPASS = \"DONTCARE\";\n parameter CH0_LSM_DISABLE = \"DONTCARE\";\n parameter CH1_LSM_DISABLE = \"DONTCARE\";\n parameter CH0_MATCH_2_ENABLE = \"DONTCARE\";\n parameter CH1_MATCH_2_ENABLE = \"DONTCARE\";\n parameter CH0_MATCH_4_ENABLE = \"DONTCARE\";\n parameter CH1_MATCH_4_ENABLE = \"DONTCARE\";\n parameter CH0_MIN_IPG_CNT = \"DONTCARE\";\n parameter CH1_MIN_IPG_CNT = \"DONTCARE\";\n parameter CH0_CC_MATCH_1 = \"DONTCARE\";\n parameter CH1_CC_MATCH_1 = \"DONTCARE\";\n parameter CH0_CC_MATCH_2 = \"DONTCARE\";\n parameter CH1_CC_MATCH_2 = \"DONTCARE\";\n parameter CH0_CC_MATCH_3 = \"DONTCARE\";\n parameter CH1_CC_MATCH_3 = \"DONTCARE\";\n parameter CH0_CC_MATCH_4 = \"DONTCARE\";\n parameter CH1_CC_MATCH_4 = \"DONTCARE\";\n parameter CH0_UDF_COMMA_MASK = \"DONTCARE\";\n parameter CH1_UDF_COMMA_MASK = \"DONTCARE\";\n parameter CH0_UDF_COMMA_A = \"DONTCARE\";\n parameter CH1_UDF_COMMA_A = \"DONTCARE\";\n parameter CH0_UDF_COMMA_B = \"DONTCARE\";\n parameter CH1_UDF_COMMA_B = \"DONTCARE\";\n parameter CH0_RX_DCO_CK_DIV = \"DONTCARE\";\n parameter CH1_RX_DCO_CK_DIV = \"DONTCARE\";\n parameter CH0_RCV_DCC_EN = \"DONTCARE\";\n parameter CH1_RCV_DCC_EN = \"DONTCARE\";\n parameter CH0_REQ_LVL_SET = \"DONTCARE\";\n parameter CH1_REQ_LVL_SET = \"DONTCARE\";\n parameter CH0_REQ_EN = \"DONTCARE\";\n parameter CH1_REQ_EN = \"DONTCARE\";\n parameter CH0_RTERM_RX = \"DONTCARE\";\n parameter CH1_RTERM_RX = \"DONTCARE\";\n parameter CH0_PDEN_SEL = \"DONTCARE\";\n parameter CH1_PDEN_SEL = \"DONTCARE\";\n parameter CH0_LDR_RX2CORE_SEL = \"DONTCARE\";\n parameter CH1_LDR_RX2CORE_SEL = \"DONTCARE\";\n parameter CH0_LDR_CORE2TX_SEL = \"DONTCARE\";\n parameter CH1_LDR_CORE2TX_SEL = \"DONTCARE\";\n parameter CH0_TPWDNB = \"DONTCARE\";\n parameter CH1_TPWDNB = \"DONTCARE\";\n parameter CH0_RATE_MODE_TX = \"DONTCARE\";\n parameter CH1_RATE_MODE_TX = \"DONTCARE\";\n parameter CH0_RTERM_TX = \"DONTCARE\";\n parameter CH1_RTERM_TX = \"DONTCARE\";\n parameter CH0_TX_CM_SEL = \"DONTCARE\";\n parameter CH1_TX_CM_SEL = \"DONTCARE\";\n parameter CH0_TDRV_PRE_EN = \"DONTCARE\";\n parameter CH1_TDRV_PRE_EN = \"DONTCARE\";\n parameter CH0_TDRV_SLICE0_SEL = \"DONTCARE\";\n parameter CH1_TDRV_SLICE0_SEL = \"DONTCARE\";\n parameter CH0_TDRV_SLICE1_SEL = \"DONTCARE\";\n parameter CH1_TDRV_SLICE1_SEL = \"DONTCARE\";\n parameter CH0_TDRV_SLICE2_SEL = \"DONTCARE\";\n parameter CH1_TDRV_SLICE2_SEL = \"DONTCARE\";\n parameter CH0_TDRV_SLICE3_SEL = \"DONTCARE\";\n parameter CH1_TDRV_SLICE3_SEL = \"DONTCARE\";\n parameter CH0_TDRV_SLICE4_SEL = \"DONTCARE\";\n parameter CH1_TDRV_SLICE4_SEL = \"DONTCARE\";\n parameter CH0_TDRV_SLICE5_SEL = \"DONTCARE\";\n parameter CH1_TDRV_SLICE5_SEL = \"DONTCARE\";\n parameter CH0_TDRV_SLICE0_CUR = \"DONTCARE\";\n parameter CH1_TDRV_SLICE0_CUR = \"DONTCARE\";\n parameter CH0_TDRV_SLICE1_CUR = \"DONTCARE\";\n parameter CH1_TDRV_SLICE1_CUR = \"DONTCARE\";\n parameter CH0_TDRV_SLICE2_CUR = \"DONTCARE\";\n parameter CH1_TDRV_SLICE2_CUR = \"DONTCARE\";\n parameter CH0_TDRV_SLICE3_CUR = \"DONTCARE\";\n parameter CH1_TDRV_SLICE3_CUR = \"DONTCARE\";\n parameter CH0_TDRV_SLICE4_CUR = \"DONTCARE\";\n parameter CH1_TDRV_SLICE4_CUR = \"DONTCARE\";\n parameter CH0_TDRV_SLICE5_CUR = \"DONTCARE\";\n parameter CH1_TDRV_SLICE5_CUR = \"DONTCARE\";\n parameter CH0_TDRV_DAT_SEL = \"DONTCARE\";\n parameter CH1_TDRV_DAT_SEL = \"DONTCARE\";\n parameter CH0_TX_DIV11_SEL = \"DONTCARE\";\n parameter CH1_TX_DIV11_SEL = \"DONTCARE\";\n parameter CH0_RPWDNB = \"DONTCARE\";\n parameter CH1_RPWDNB = \"DONTCARE\";\n parameter CH0_RATE_MODE_RX = \"DONTCARE\";\n parameter CH1_RATE_MODE_RX = \"DONTCARE\";\n parameter CH0_RLOS_SEL = \"DONTCARE\";\n parameter CH1_RLOS_SEL = \"DONTCARE\";\n parameter CH0_RX_LOS_LVL = \"DONTCARE\";\n parameter CH1_RX_LOS_LVL = \"DONTCARE\";\n parameter CH0_RX_LOS_CEQ = \"DONTCARE\";\n parameter CH1_RX_LOS_CEQ = \"DONTCARE\";\n parameter CH0_RX_LOS_HYST_EN = \"DONTCARE\";\n parameter CH1_RX_LOS_HYST_EN = \"DONTCARE\";\n parameter CH0_RX_LOS_EN = \"DONTCARE\";\n parameter CH1_RX_LOS_EN = \"DONTCARE\";\n parameter CH0_RX_DIV11_SEL = \"DONTCARE\";\n parameter CH1_RX_DIV11_SEL = \"DONTCARE\";\n parameter CH0_SEL_SD_RX_CLK = \"DONTCARE\";\n parameter CH1_SEL_SD_RX_CLK = \"DONTCARE\";\n parameter CH0_FF_RX_H_CLK_EN = \"DONTCARE\";\n parameter CH1_FF_RX_H_CLK_EN = \"DONTCARE\";\n parameter CH0_FF_RX_F_CLK_DIS = \"DONTCARE\";\n parameter CH1_FF_RX_F_CLK_DIS = \"DONTCARE\";\n parameter CH0_FF_TX_H_CLK_EN = \"DONTCARE\";\n parameter CH1_FF_TX_H_CLK_EN = \"DONTCARE\";\n parameter CH0_FF_TX_F_CLK_DIS = \"DONTCARE\";\n parameter CH1_FF_TX_F_CLK_DIS = \"DONTCARE\";\n parameter CH0_RX_RATE_SEL = \"DONTCARE\";\n parameter CH1_RX_RATE_SEL = \"DONTCARE\";\n parameter CH0_TDRV_POST_EN = \"DONTCARE\";\n parameter CH1_TDRV_POST_EN = \"DONTCARE\";\n parameter CH0_TX_POST_SIGN = \"DONTCARE\";\n parameter CH1_TX_POST_SIGN = \"DONTCARE\";\n parameter CH0_TX_PRE_SIGN = \"DONTCARE\";\n parameter CH1_TX_PRE_SIGN = \"DONTCARE\";\n parameter CH0_RXTERM_CM = \"DONTCARE\";\n parameter CH1_RXTERM_CM = \"DONTCARE\";\n parameter CH0_RXIN_CM = \"DONTCARE\";\n parameter CH1_RXIN_CM = \"DONTCARE\";\n parameter CH0_LEQ_OFFSET_SEL = \"DONTCARE\";\n parameter CH1_LEQ_OFFSET_SEL = \"DONTCARE\";\n parameter CH0_LEQ_OFFSET_TRIM = \"DONTCARE\";\n parameter CH1_LEQ_OFFSET_TRIM = \"DONTCARE\";\n parameter D_TX_MAX_RATE = \"DONTCARE\";\n parameter CH0_CDR_MAX_RATE = \"DONTCARE\";\n parameter CH1_CDR_MAX_RATE = \"DONTCARE\";\n parameter CH0_TXAMPLITUDE = \"DONTCARE\";\n parameter CH1_TXAMPLITUDE = \"DONTCARE\";\n parameter CH0_TXDEPRE = \"DONTCARE\";\n parameter CH1_TXDEPRE = \"DONTCARE\";\n parameter CH0_TXDEPOST = \"DONTCARE\";\n parameter CH1_TXDEPOST = \"DONTCARE\";\n parameter CH0_PROTOCOL = \"DONTCARE\";\n parameter CH1_PROTOCOL = \"DONTCARE\";\n parameter D_ISETLOS = \"DONTCARE\";\n parameter D_SETIRPOLY_AUX = \"DONTCARE\";\n parameter D_SETICONST_AUX = \"DONTCARE\";\n parameter D_SETIRPOLY_CH = \"DONTCARE\";\n parameter D_SETICONST_CH = \"DONTCARE\";\n parameter D_REQ_ISET = \"DONTCARE\";\n parameter D_PD_ISET = \"DONTCARE\";\n parameter D_DCO_CALIB_TIME_SEL = \"DONTCARE\";\n parameter CH0_DCOCTLGI = \"DONTCARE\";\n parameter CH1_DCOCTLGI = \"DONTCARE\";\n parameter CH0_DCOATDDLY = \"DONTCARE\";\n parameter CH1_DCOATDDLY = \"DONTCARE\";\n parameter CH0_DCOATDCFG = \"DONTCARE\";\n parameter CH1_DCOATDCFG = \"DONTCARE\";\n parameter CH0_DCOBYPSATD = \"DONTCARE\";\n parameter CH1_DCOBYPSATD = \"DONTCARE\";\n parameter CH0_DCOSCALEI = \"DONTCARE\";\n parameter CH1_DCOSCALEI = \"DONTCARE\";\n parameter CH0_DCOITUNE4LSB = \"DONTCARE\";\n parameter CH1_DCOITUNE4LSB = \"DONTCARE\";\n parameter CH0_DCOIOSTUNE = \"DONTCARE\";\n parameter CH1_DCOIOSTUNE = \"DONTCARE\";\n parameter CH0_DCODISBDAVOID = \"DONTCARE\";\n parameter CH1_DCODISBDAVOID = \"DONTCARE\";\n parameter CH0_DCOCALDIV = \"DONTCARE\";\n parameter CH1_DCOCALDIV = \"DONTCARE\";\n parameter CH0_DCONUOFLSB = \"DONTCARE\";\n parameter CH1_DCONUOFLSB = \"DONTCARE\";\n parameter CH0_DCOIUPDNX2 = \"DONTCARE\";\n parameter CH1_DCOIUPDNX2 = \"DONTCARE\";\n parameter CH0_DCOSTEP = \"DONTCARE\";\n parameter CH1_DCOSTEP = \"DONTCARE\";\n parameter CH0_DCOSTARTVAL = \"DONTCARE\";\n parameter CH1_DCOSTARTVAL = \"DONTCARE\";\n parameter CH0_DCOFLTDAC = \"DONTCARE\";\n parameter CH1_DCOFLTDAC = \"DONTCARE\";\n parameter CH0_DCOITUNE = \"DONTCARE\";\n parameter CH1_DCOITUNE = \"DONTCARE\";\n parameter CH0_DCOFTNRG = \"DONTCARE\";\n parameter CH1_DCOFTNRG = \"DONTCARE\";\n parameter CH0_CDR_CNT4SEL = \"DONTCARE\";\n parameter CH1_CDR_CNT4SEL = \"DONTCARE\";\n parameter CH0_CDR_CNT8SEL = \"DONTCARE\";\n parameter CH1_CDR_CNT8SEL = \"DONTCARE\";\n parameter CH0_BAND_THRESHOLD = \"DONTCARE\";\n parameter CH1_BAND_THRESHOLD = \"DONTCARE\";\n parameter CH0_AUTO_FACQ_EN = \"DONTCARE\";\n parameter CH1_AUTO_FACQ_EN = \"DONTCARE\";\n parameter CH0_AUTO_CALIB_EN = \"DONTCARE\";\n parameter CH1_AUTO_CALIB_EN = \"DONTCARE\";\n parameter CH0_CALIB_CK_MODE = \"DONTCARE\";\n parameter CH1_CALIB_CK_MODE = \"DONTCARE\";\n parameter CH0_REG_BAND_OFFSET = \"DONTCARE\";\n parameter CH1_REG_BAND_OFFSET = \"DONTCARE\";\n parameter CH0_REG_BAND_SEL = \"DONTCARE\";\n parameter CH1_REG_BAND_SEL = \"DONTCARE\";\n parameter CH0_REG_IDAC_SEL = \"DONTCARE\";\n parameter CH1_REG_IDAC_SEL = \"DONTCARE\";\n parameter CH0_REG_IDAC_EN = \"DONTCARE\";\n parameter CH1_REG_IDAC_EN = \"DONTCARE\";\n parameter D_TXPLL_PWDNB = \"DONTCARE\";\n parameter D_SETPLLRC = \"DONTCARE\";\n parameter D_REFCK_MODE = \"DONTCARE\";\n parameter D_TX_VCO_CK_DIV = \"DONTCARE\";\n parameter D_PLL_LOL_SET = \"DONTCARE\";\n parameter D_RG_EN = \"DONTCARE\";\n parameter D_RG_SET = \"DONTCARE\";\n parameter D_CMUSETISCL4VCO = \"DONTCARE\";\n parameter D_CMUSETI4VCO = \"DONTCARE\";\n parameter D_CMUSETINITVCT = \"DONTCARE\";\n parameter D_CMUSETZGM = \"DONTCARE\";\n parameter D_CMUSETP2AGM = \"DONTCARE\";\n parameter D_CMUSETP1GM = \"DONTCARE\";\n parameter D_CMUSETI4CPZ = \"DONTCARE\";\n parameter D_CMUSETI4CPP = \"DONTCARE\";\n parameter D_CMUSETICP4Z = \"DONTCARE\";\n parameter D_CMUSETICP4P = \"DONTCARE\";\n parameter D_CMUSETBIASI = \"DONTCARE\";\n (* iopad_external_pin *)\n (* iopad_external_pin *)\n input CH0_HDINP;\n (* iopad_external_pin *)\n input CH1_HDINP;\n (* iopad_external_pin *)\n input CH0_HDINN;\n (* iopad_external_pin *)\n input CH1_HDINN;\n input D_TXBIT_CLKP_FROM_ND;\n input D_TXBIT_CLKN_FROM_ND;\n input D_SYNC_ND;\n input D_TXPLL_LOL_FROM_ND;\n input CH0_RX_REFCLK;\n input CH1_RX_REFCLK;\n input CH0_FF_RXI_CLK;\n input CH1_FF_RXI_CLK;\n input CH0_FF_TXI_CLK;\n input CH1_FF_TXI_CLK;\n input CH0_FF_EBRD_CLK;\n input CH1_FF_EBRD_CLK;\n input CH0_FF_TX_D_0;\n input CH1_FF_TX_D_0;\n input CH0_FF_TX_D_1;\n input CH1_FF_TX_D_1;\n input CH0_FF_TX_D_2;\n input CH1_FF_TX_D_2;\n input CH0_FF_TX_D_3;\n input CH1_FF_TX_D_3;\n input CH0_FF_TX_D_4;\n input CH1_FF_TX_D_4;\n input CH0_FF_TX_D_5;\n input CH1_FF_TX_D_5;\n input CH0_FF_TX_D_6;\n input CH1_FF_TX_D_6;\n input CH0_FF_TX_D_7;\n input CH1_FF_TX_D_7;\n input CH0_FF_TX_D_8;\n input CH1_FF_TX_D_8;\n input CH0_FF_TX_D_9;\n input CH1_FF_TX_D_9;\n input CH0_FF_TX_D_10;\n input CH1_FF_TX_D_10;\n input CH0_FF_TX_D_11;\n input CH1_FF_TX_D_11;\n input CH0_FF_TX_D_12;\n input CH1_FF_TX_D_12;\n input CH0_FF_TX_D_13;\n input CH1_FF_TX_D_13;\n input CH0_FF_TX_D_14;\n input CH1_FF_TX_D_14;\n input CH0_FF_TX_D_15;\n input CH1_FF_TX_D_15;\n input CH0_FF_TX_D_16;\n input CH1_FF_TX_D_16;\n input CH0_FF_TX_D_17;\n input CH1_FF_TX_D_17;\n input CH0_FF_TX_D_18;\n input CH1_FF_TX_D_18;\n input CH0_FF_TX_D_19;\n input CH1_FF_TX_D_19;\n input CH0_FF_TX_D_20;\n input CH1_FF_TX_D_20;\n input CH0_FF_TX_D_21;\n input CH1_FF_TX_D_21;\n input CH0_FF_TX_D_22;\n input CH1_FF_TX_D_22;\n input CH0_FF_TX_D_23;\n input CH1_FF_TX_D_23;\n input CH0_FFC_EI_EN;\n input CH1_FFC_EI_EN;\n input CH0_FFC_PCIE_DET_EN;\n input CH1_FFC_PCIE_DET_EN;\n input CH0_FFC_PCIE_CT;\n input CH1_FFC_PCIE_CT;\n input CH0_FFC_SB_INV_RX;\n input CH1_FFC_SB_INV_RX;\n input CH0_FFC_ENABLE_CGALIGN;\n input CH1_FFC_ENABLE_CGALIGN;\n input CH0_FFC_SIGNAL_DETECT;\n input CH1_FFC_SIGNAL_DETECT;\n input CH0_FFC_FB_LOOPBACK;\n input CH1_FFC_FB_LOOPBACK;\n input CH0_FFC_SB_PFIFO_LP;\n input CH1_FFC_SB_PFIFO_LP;\n input CH0_FFC_PFIFO_CLR;\n input CH1_FFC_PFIFO_CLR;\n input CH0_FFC_RATE_MODE_RX;\n input CH1_FFC_RATE_MODE_RX;\n input CH0_FFC_RATE_MODE_TX;\n input CH1_FFC_RATE_MODE_TX;\n input CH0_FFC_DIV11_MODE_RX;\n input CH1_FFC_DIV11_MODE_RX;\n input CH0_FFC_RX_GEAR_MODE;\n input CH1_FFC_RX_GEAR_MODE;\n input CH0_FFC_TX_GEAR_MODE;\n input CH1_FFC_TX_GEAR_MODE;\n input CH0_FFC_DIV11_MODE_TX;\n input CH1_FFC_DIV11_MODE_TX;\n input CH0_FFC_LDR_CORE2TX_EN;\n input CH1_FFC_LDR_CORE2TX_EN;\n input CH0_FFC_LANE_TX_RST;\n input CH1_FFC_LANE_TX_RST;\n input CH0_FFC_LANE_RX_RST;\n input CH1_FFC_LANE_RX_RST;\n input CH0_FFC_RRST;\n input CH1_FFC_RRST;\n input CH0_FFC_TXPWDNB;\n input CH1_FFC_TXPWDNB;\n input CH0_FFC_RXPWDNB;\n input CH1_FFC_RXPWDNB;\n input CH0_LDR_CORE2TX;\n input CH1_LDR_CORE2TX;\n input D_SCIWDATA0;\n input D_SCIWDATA1;\n input D_SCIWDATA2;\n input D_SCIWDATA3;\n input D_SCIWDATA4;\n input D_SCIWDATA5;\n input D_SCIWDATA6;\n input D_SCIWDATA7;\n input D_SCIADDR0;\n input D_SCIADDR1;\n input D_SCIADDR2;\n input D_SCIADDR3;\n input D_SCIADDR4;\n input D_SCIADDR5;\n input D_SCIENAUX;\n input D_SCISELAUX;\n input CH0_SCIEN;\n input CH1_SCIEN;\n input CH0_SCISEL;\n input CH1_SCISEL;\n input D_SCIRD;\n input D_SCIWSTN;\n input D_CYAWSTN;\n input D_FFC_SYNC_TOGGLE;\n input D_FFC_DUAL_RST;\n input D_FFC_MACRO_RST;\n input D_FFC_MACROPDB;\n input D_FFC_TRST;\n input CH0_FFC_CDR_EN_BITSLIP;\n input CH1_FFC_CDR_EN_BITSLIP;\n input D_SCAN_ENABLE;\n input D_SCAN_IN_0;\n input D_SCAN_IN_1;\n input D_SCAN_IN_2;\n input D_SCAN_IN_3;\n input D_SCAN_IN_4;\n input D_SCAN_IN_5;\n input D_SCAN_IN_6;\n input D_SCAN_IN_7;\n input D_SCAN_MODE;\n input D_SCAN_RESET;\n input D_CIN0;\n input D_CIN1;\n input D_CIN2;\n input D_CIN3;\n input D_CIN4;\n input D_CIN5;\n input D_CIN6;\n input D_CIN7;\n input D_CIN8;\n input D_CIN9;\n input D_CIN10;\n input D_CIN11;\n output CH0_HDOUTP;\n output CH1_HDOUTP;\n output CH0_HDOUTN;\n output CH1_HDOUTN;\n output D_TXBIT_CLKP_TO_ND;\n output D_TXBIT_CLKN_TO_ND;\n output D_SYNC_PULSE2ND;\n output D_TXPLL_LOL_TO_ND;\n output CH0_FF_RX_F_CLK;\n output CH1_FF_RX_F_CLK;\n output CH0_FF_RX_H_CLK;\n output CH1_FF_RX_H_CLK;\n output CH0_FF_TX_F_CLK;\n output CH1_FF_TX_F_CLK;\n output CH0_FF_TX_H_CLK;\n output CH1_FF_TX_H_CLK;\n output CH0_FF_RX_PCLK;\n output CH1_FF_RX_PCLK;\n output CH0_FF_TX_PCLK;\n output CH1_FF_TX_PCLK;\n output CH0_FF_RX_D_0;\n output CH1_FF_RX_D_0;\n output CH0_FF_RX_D_1;\n output CH1_FF_RX_D_1;\n output CH0_FF_RX_D_2;\n output CH1_FF_RX_D_2;\n output CH0_FF_RX_D_3;\n output CH1_FF_RX_D_3;\n output CH0_FF_RX_D_4;\n output CH1_FF_RX_D_4;\n output CH0_FF_RX_D_5;\n output CH1_FF_RX_D_5;\n output CH0_FF_RX_D_6;\n output CH1_FF_RX_D_6;\n output CH0_FF_RX_D_7;\n output CH1_FF_RX_D_7;\n output CH0_FF_RX_D_8;\n output CH1_FF_RX_D_8;\n output CH0_FF_RX_D_9;\n output CH1_FF_RX_D_9;\n output CH0_FF_RX_D_10;\n output CH1_FF_RX_D_10;\n output CH0_FF_RX_D_11;\n output CH1_FF_RX_D_11;\n output CH0_FF_RX_D_12;\n output CH1_FF_RX_D_12;\n output CH0_FF_RX_D_13;\n output CH1_FF_RX_D_13;\n output CH0_FF_RX_D_14;\n output CH1_FF_RX_D_14;\n output CH0_FF_RX_D_15;\n output CH1_FF_RX_D_15;\n output CH0_FF_RX_D_16;\n output CH1_FF_RX_D_16;\n output CH0_FF_RX_D_17;\n output CH1_FF_RX_D_17;\n output CH0_FF_RX_D_18;\n output CH1_FF_RX_D_18;\n output CH0_FF_RX_D_19;\n output CH1_FF_RX_D_19;\n output CH0_FF_RX_D_20;\n output CH1_FF_RX_D_20;\n output CH0_FF_RX_D_21;\n output CH1_FF_RX_D_21;\n output CH0_FF_RX_D_22;\n output CH1_FF_RX_D_22;\n output CH0_FF_RX_D_23;\n output CH1_FF_RX_D_23;\n output CH0_FFS_PCIE_DONE;\n output CH1_FFS_PCIE_DONE;\n output CH0_FFS_PCIE_CON;\n output CH1_FFS_PCIE_CON;\n output CH0_FFS_RLOS;\n output CH1_FFS_RLOS;\n output CH0_FFS_LS_SYNC_STATUS;\n output CH1_FFS_LS_SYNC_STATUS;\n output CH0_FFS_CC_UNDERRUN;\n output CH1_FFS_CC_UNDERRUN;\n output CH0_FFS_CC_OVERRUN;\n output CH1_FFS_CC_OVERRUN;\n output CH0_FFS_RXFBFIFO_ERROR;\n output CH1_FFS_RXFBFIFO_ERROR;\n output CH0_FFS_TXFBFIFO_ERROR;\n output CH1_FFS_TXFBFIFO_ERROR;\n output CH0_FFS_RLOL;\n output CH1_FFS_RLOL;\n output CH0_FFS_SKP_ADDED;\n output CH1_FFS_SKP_ADDED;\n output CH0_FFS_SKP_DELETED;\n output CH1_FFS_SKP_DELETED;\n output CH0_LDR_RX2CORE;\n output CH1_LDR_RX2CORE;\n output D_SCIRDATA0;\n output D_SCIRDATA1;\n output D_SCIRDATA2;\n output D_SCIRDATA3;\n output D_SCIRDATA4;\n output D_SCIRDATA5;\n output D_SCIRDATA6;\n output D_SCIRDATA7;\n output D_SCIINT;\n output D_SCAN_OUT_0;\n output D_SCAN_OUT_1;\n output D_SCAN_OUT_2;\n output D_SCAN_OUT_3;\n output D_SCAN_OUT_4;\n output D_SCAN_OUT_5;\n output D_SCAN_OUT_6;\n output D_SCAN_OUT_7;\n output D_COUT0;\n output D_COUT1;\n output D_COUT2;\n output D_COUT3;\n output D_COUT4;\n output D_COUT5;\n output D_COUT6;\n output D_COUT7;\n output D_COUT8;\n output D_COUT9;\n output D_COUT10;\n output D_COUT11;\n output D_COUT12;\n output D_COUT13;\n output D_COUT14;\n output D_COUT15;\n output D_COUT16;\n output D_COUT17;\n output D_COUT18;\n output D_COUT19;\n input D_REFCLKI;\n output D_FFS_PLOL;\nendmodule\n\n",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// **AUTOGENERATED FILE** **DO NOT EDIT**
|
|
2
|
-
// Generated by ../yosys-src/techlibs/quicklogic/qlf_k6n10f/generate_bram_types_sim.py at 2023-12-
|
|
2
|
+
// Generated by ../yosys-src/techlibs/quicklogic/qlf_k6n10f/generate_bram_types_sim.py at 2023-12-22 16:27:10.162860+00:00
|
|
3
3
|
`timescale 1ns /10ps
|
|
4
4
|
|
|
5
5
|
module TDP36K_BRAM_A_X1_B_X1_nonsplit (
|
package/gen/yosys.core.wasm
CHANGED
|
Binary file
|