Merge remote-tracking branch 'donn/pyosys_bugfixes' into merge_pybind11

This commit is contained in:
Mohamed Gaber 2025-10-26 02:39:43 +03:00
commit dec28f65ae
No known key found for this signature in database
127 changed files with 4674 additions and 7342 deletions

View File

@ -11,6 +11,10 @@ indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[*.rst]
indent_style = space
indent_size = 3
[*.yml]
indent_style = space
indent_size = 2

View File

@ -55,11 +55,6 @@ jobs:
submodules: true
persist-credentials: false
- uses: actions/setup-python@v5
- name: Get Boost Source
shell: bash
run: |
mkdir -p boost
curl -L https://github.com/boostorg/boost/releases/download/boost-1.86.0/boost-1.86.0-b2-nodocs.tar.gz | tar --strip-components=1 -xzC boost
- name: Get FFI
shell: bash
run: |
@ -103,21 +98,16 @@ jobs:
CIBW_BEFORE_ALL: bash ./.github/workflows/wheels/cibw_before_all.sh
CIBW_ENVIRONMENT: >
OPTFLAGS=-O3
CXXFLAGS=-I./boost/pfx/include
LINKFLAGS=-L./boost/pfx/lib
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a'
PATH="$PWD/bison/src:$PATH"
CIBW_ENVIRONMENT_MACOS: >
OPTFLAGS=-O3
CXXFLAGS=-I./boost/pfx/include
LINKFLAGS=-L./boost/pfx/lib
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
MACOSX_DEPLOYMENT_TARGET=11
makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang'
makeFlags='CONFIG=clang'
PATH="$PWD/bison/src:$PATH"
CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh
CIBW_TEST_COMMAND: python3 {project}/tests/arch/ecp5/add_sub.py
CIBW_TEST_COMMAND: python3 {project}/tests/pyosys/run_tests.py
- uses: actions/upload-artifact@v4
with:
name: python-wheels-${{ matrix.os.runner }}

View File

@ -1,8 +1,8 @@
set -e
set -x
# Don't use objects from previous compiles on Windows/macOS
make clean
# Don't use Python objects from previous compiles
make clean-py
# DEBUG: show python3 and python3-config outputs
if [ "$(uname)" != "Linux" ]; then
@ -11,24 +11,3 @@ if [ "$(uname)" != "Linux" ]; then
fi
python3 --version
python3-config --includes
# Build boost
cd ./boost
## Delete the artefacts from previous builds (if any)
rm -rf ./pfx
## Bootstrap bjam
./bootstrap.sh --prefix=./pfx
## Build Boost against current version of Python, only for
## static linkage (Boost is statically linked because system boost packages
## wildly vary in versions, including the libboost_python3 version)
./b2\
-j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu)\
--prefix=./pfx\
--with-filesystem\
--with-system\
--with-python\
cxxflags="$(python3-config --includes) -std=c++17 -fPIC"\
cflags="$(python3-config --includes) -fPIC"\
link=static\
variant=release\
install

1
.gitignore vendored
View File

@ -5,6 +5,7 @@
/Brewfile.lock.json
## build artifacts
/.git-abc-submodule-hash
# compiler intermediate files
*.o
*.d

View File

@ -2,9 +2,28 @@
List of major changes and improvements between releases
=======================================================
Yosys 0.57 .. Yosys 0.58-dev
Yosys 0.58 .. Yosys 0.59-dev
--------------------------
Yosys 0.57 .. Yosys 0.58
--------------------------
* Various
- Run ABC passes in parallel.
- Extending support for buffer normalization.
- Overhaul of logging APIs.
- read_blif: Represent sequential elements with gate cells.
- Support multiple lib files in abc9_exe.
* New commands and options
- Added "-wireshape" option to "show" command to allow
control the shape of wire nodes.
- Added "-relativeshare" option to "read_verilog", "synth"
and "techmap" pass for synthesis reproducibility testing.
- "write_rtlil" pass no longer sorts design, added "-sort"
option to match old behavior
- Added "-sva-continue-on-err" to "verific" pass to allow
processing designs that includes unsupported SVA.
Yosys 0.56 .. Yosys 0.57
--------------------------
* New commands and options

View File

@ -38,7 +38,8 @@ techlibs/gowin/ @pepijndevos
techlibs/gatemate/ @pu-cc
# pyosys
misc/*.py @btut
pyosys/* @donn
setup.py @donn
backends/firrtl @ucbjrl @azidar

View File

@ -112,7 +112,7 @@ all: top-all
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
VPATH := $(YOSYS_SRC)
CXXSTD ?= c++17
export CXXSTD ?= c++17
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include
LIBS := $(LIBS) -lstdc++ -lm
PLUGIN_LINKFLAGS :=
@ -148,10 +148,6 @@ LINKFLAGS += -rdynamic
ifneq ($(shell :; command -v brew),)
BREW_PREFIX := $(shell brew --prefix)/opt
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
ifeq ($(ENABLE_PYOSYS),1)
CXXFLAGS += -I$(BREW_PREFIX)/boost/include
LINKFLAGS += -L$(BREW_PREFIX)/boost/lib -L$(BREW_PREFIX)/boost-python3/lib
endif
CXXFLAGS += -I$(BREW_PREFIX)/readline/include -I$(BREW_PREFIX)/flex/include
LINKFLAGS += -L$(BREW_PREFIX)/readline/lib -L$(BREW_PREFIX)/flex/lib
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
@ -180,7 +176,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.57+260
YOSYS_VER := 0.58+80
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2)
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'.' -f3)
@ -203,7 +199,7 @@ endif
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 3aca860.. | wc -l`/;" Makefile
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 157aabb.. | wc -l`/;" Makefile
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
@ -364,37 +360,24 @@ ifeq ($(ENABLE_LIBYOSYS),1)
TARGETS += libyosys.so
endif
PY_WRAPPER_FILE = pyosys/wrappers
# running make clean on just those and then recompiling saves a lot of
# time when running cibuildwheel
PYTHON_OBJECTS = pyosys/wrappers.o kernel/drivers.o kernel/yosys.o passes/cmds/plugin.o
ifeq ($(ENABLE_PYOSYS),1)
# python-config --ldflags includes -l and -L, but LINKFLAGS is only -L
LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags))
LIBS += $(shell $(PYTHON_CONFIG) --libs)
EXE_LIBS += $(filter-out $(LIBS),$(shell $(PYTHON_CONFIG_FOR_EXE) --libs))
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
PYBIND11_INCLUDE ?= $(shell $(PYTHON_EXECUTABLE) -m pybind11 --includes)
CXXFLAGS += -I$(PYBIND11_INCLUDE) -DYOSYS_ENABLE_PYTHON
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DYOSYS_ENABLE_PYTHON
# Detect name of boost_python library. Some distros use boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
CHECK_BOOST_PYTHON = (echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(LINKFLAGS) $(EXE_LIBS) $(LIBS) -l$(1) - > /dev/null 2>&1 && echo "-l$(1)")
BOOST_PYTHON_LIB ?= $(shell \
$(call CHECK_BOOST_PYTHON,boost_python-py$(subst .,,$(PYTHON_VERSION))) || \
$(call CHECK_BOOST_PYTHON,boost_python-py$(PYTHON_MAJOR_VERSION)) || \
$(call CHECK_BOOST_PYTHON,boost_python$(subst .,,$(PYTHON_VERSION))) || \
$(call CHECK_BOOST_PYTHON,boost_python$(PYTHON_MAJOR_VERSION)) \
)
# Inside CentOS 7
ifeq (${PLATFORM},centos7)
BOOST_PYTHON_LIB = -L/opt/boost/lib -lboost_python38
CXXFLAGS += -I/opt/boost/include
endif
ifeq ($(BOOST_PYTHON_LIB),)
$(error BOOST_PYTHON_LIB could not be detected. Please define manually)
endif
LIBS += $(BOOST_PYTHON_LIB) -lboost_filesystem
PY_WRAPPER_FILE = kernel/python_wrappers
OBJS += $(PY_WRAPPER_FILE).o
PY_GEN_SCRIPT= py_wrap_generator
PY_WRAP_INCLUDES := $(shell $(PYTHON_EXECUTABLE) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
PY_GEN_SCRIPT = pyosys/generator.py
PY_WRAP_INCLUDES := $(shell $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) --print-includes)
endif # ENABLE_PYOSYS
ifeq ($(ENABLE_BACKTRACE),1)
@ -556,7 +539,7 @@ VERIFIC_COMPONENTS += synlib
CXXFLAGS += -DVERIFIC_LIBERTY_SUPPORT
endif
ifeq ($(ENABLE_VERIFIC_UPF),1)
VERIFIC_COMPONENTS += hdl_file_sort verilog_nl
VERIFIC_COMPONENTS += hdl_file_sort verilog_nl
VERIFIC_COMPONENTS += commands upf
CXXFLAGS += -DVERIFIC_UPF_SUPPORT
endif
@ -602,6 +585,13 @@ $(subst //,/,$(1)/$(notdir $(2))): $(2)
$$(Q) cp "$(YOSYS_SRC)"/$(2) $(subst //,/,$(1)/$(notdir $(2)))
endef
define add_share_file_and_rename
EXTRA_TARGETS += $(subst //,/,$(1)/$(3))
$(subst //,/,$(1)/$(3)): $(2)
$$(P) mkdir -p $(1)
$$(Q) cp "$(YOSYS_SRC)"/$(2) $(subst //,/,$(1)/$(3))
endef
define add_gen_share_file
EXTRA_TARGETS += $(subst //,/,$(1)/$(notdir $(2)))
$(subst //,/,$(1)/$(notdir $(2))): $(2)
@ -838,9 +828,9 @@ endif
$(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(CXX) $(CXXFLAGS) -x c++ -o $@ -E -P -
ifeq ($(ENABLE_PYOSYS),1)
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
$(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT) pyosys/wrappers_tpl.cc $(PY_WRAP_INCLUDES) pyosys/hashlib.h
$(Q) mkdir -p $(dir $@)
$(P) $(PYTHON_EXECUTABLE) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
$(P) $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) $(PY_WRAPPER_FILE).cc
endif
%.o: %.cpp
@ -908,7 +898,17 @@ check-git-abc:
exit 1; \
fi
abc/abc$(EXE) abc/libabc.a: | check-git-abc
.git-abc-submodule-hash: FORCE
@new=$$(cd abc 2>/dev/null && git rev-parse HEAD 2>/dev/null || echo none); \
old=$$(cat .git-abc-submodule-hash 2>/dev/null || echo none); \
if [ "$$new" != "$$old" ]; then \
echo "$$new" > .git-abc-submodule-hash; \
fi
abc/abc$(EXE) abc/libabc.a: .git-abc-submodule-hash | check-git-abc
@if [ "$$(cd abc 2>/dev/null && git rev-parse HEAD 2>/dev/null)" != "$$(cat ../.git-abc-submodule-hash 2>/dev/null || echo none)" ]; then \
rm -f abc/abc$(EXE); \
fi
$(P)
$(Q) mkdir -p abc && $(MAKE) -C $(PROGRAM_PREFIX)abc -f "$(realpath $(YOSYS_SRC)/abc/Makefile)" ABCSRC="$(realpath $(YOSYS_SRC)/abc/)" $(S) $(ABCMKARGS) $(if $(filter %.a,$@),PROG="abc",PROG="abc$(EXE)") MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " $(if $(filter %.a,$@),libabc.a)
@ -1088,12 +1088,12 @@ ifeq ($(ENABLE_LIBYOSYS),1)
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so; fi
ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
$(INSTALL_SUDO) cp pyosys/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/__init__.py
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
$(INSTALL_SUDO) cp -r share $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
ifeq ($(ENABLE_ABC),1)
$(INSTALL_SUDO) cp yosys-abc $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc
endif
$(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
endif
endif
ifeq ($(ENABLE_PLUGINS),1)
@ -1183,12 +1183,10 @@ DOC_TARGET ?= html
docs: docs/prep
$(Q) $(MAKE) -C docs $(DOC_TARGET)
clean:
clean: clean-py
rm -rf share
rm -rf kernel/*.pyh
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) $(PY_WRAP_INCLUDES) $(PY_WRAPPER_FILE).cc
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
rm -f kernel/version_*.o kernel/version_*.cc
rm -f kernel/python_wrappers.o
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
rm -rf tests/asicworld/*.out tests/asicworld/*.log
rm -rf tests/hana/*.out tests/hana/*.log
@ -1202,12 +1200,18 @@ clean:
rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS))
-$(MAKE) -C docs clean
rm -rf docs/util/__pycache__
rm -f libyosys.so
clean-py:
rm -f $(PY_WRAPPER_FILE).inc.cc $(PY_WRAPPER_FILE).cc
rm -f $(PYTHON_OBJECTS)
rm -f *.whl
rm -f libyosys.so
rm -rf kernel/*.pyh
clean-abc:
$(MAKE) -C abc DEP= clean
rm -f $(PROGRAM_PREFIX)yosys-abc$(EXE) $(PROGRAM_PREFIX)yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
rm -f $(PROGRAM_PREFIX)yosys-abc$(EXE) $(PROGRAM_PREFIX)yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a .git-abc-submodule-hash
mrproper: clean
git clean -xdf

View File

@ -98,6 +98,8 @@ struct BtorWorker
vector<ywmap_btor_sig> ywmap_states;
dict<SigBit, int> ywmap_clock_bits;
dict<SigBit, int> ywmap_clock_inputs;
vector<Cell *> ywmap_asserts;
vector<Cell *> ywmap_assumes;
PrettyJson ywmap_json;
@ -1280,6 +1282,8 @@ struct BtorWorker
btorf("%d or %d %d %d\n", nid_a_or_not_en, sid, nid_a, nid_not_en);
btorf("%d constraint %d\n", nid, nid_a_or_not_en);
if (ywmap_json.active()) ywmap_assumes.emplace_back(cell);
btorf_pop(log_id(cell));
}
@ -1304,6 +1308,8 @@ struct BtorWorker
} else {
int nid = next_nid++;
btorf("%d bad %d%s\n", nid, nid_en_and_not_a, getinfo(cell, true));
if (ywmap_json.active()) ywmap_asserts.emplace_back(cell);
}
}
@ -1461,6 +1467,7 @@ struct BtorWorker
log_assert(cursor == 0);
log_assert(GetSize(todo) == 1);
btorf("%d bad %d\n", nid, todo[cursor]);
// What do we do with ywmap_asserts when using single_bad?
}
}
@ -1526,6 +1533,18 @@ struct BtorWorker
emit_ywmap_btor_sig(entry);
ywmap_json.end_array();
ywmap_json.name("asserts");
ywmap_json.begin_array();
for (Cell *cell : ywmap_asserts)
ywmap_json.value(witness_path(cell));
ywmap_json.end_array();
ywmap_json.name("assumes");
ywmap_json.begin_array();
for (Cell *cell : ywmap_assumes)
ywmap_json.value(witness_path(cell));
ywmap_json.end_array();
ywmap_json.end_object();
}
}

1
docs/.gitignore vendored
View File

@ -6,3 +6,4 @@
/source/_images/**/*.svg
/source/_images/**/*.dot
/source/_images/code_examples
/venv

View File

@ -63,6 +63,10 @@ significant bit first. Bits may be any of:
- ``m``: A marked bit (internal use only)
- ``-``: A don't care value
When the bit representation has fewer bits than the width, it is padded to the width with
the most significant explicit bit, or ``0`` if the most significant explicit bit is ``1``,
or ``x`` if there are no explicit bits.
An *integer* is simply a signed integer value in decimal format. **Warning:**
Integer constants are limited to 32 bits. That is, they may only be in the range
:math:`[-2147483648, 2147483648)`. Integers outside this range will result in an
@ -133,6 +137,7 @@ wires, memories, cells, processes, and connections.
<module> ::= <attr-stmt>* <module-stmt> <module-body> <module-end-stmt>
<module-stmt> ::= module <id> <eol>
<module-body> ::= (<param-stmt>
| <conn-stmt>
| <wire>
| <memory>
| <cell>
@ -170,6 +175,11 @@ See :ref:`sec:rtlil_sigspec` for an overview of signal specifications.
| <sigspec> [ <integer> (:<integer>)? ]
| { <sigspec>* }
When a ``<wire-id>`` is specified, the wire must have been previously declared.
When a signal slice is specified, the left-hand integer must be greather than or
equal to the right-hand integer.
Connections
^^^^^^^^^^^
@ -268,7 +278,7 @@ may have zero or more attributes.
.. code:: BNF
<switch> ::= <switch-stmt> <case>* <switch-end-stmt>
<switch-stmt> := <attr-stmt>* switch <sigspec> <eol>
<switch-stmt> ::= <attr-stmt>* switch <sigspec> <eol>
<case> ::= <attr-stmt>* <case-stmt> <case-body>
<case-stmt> ::= case <compare>? <eol>
<compare> ::= <sigspec> (, <sigspec>)*
@ -295,3 +305,4 @@ be:
| sync always <eol>
<sync-type> ::= low | high | posedge | negedge | edge
<update-stmt> ::= update <dest-sigspec> <src-sigspec> <eol>
| <attr-stmt>* memwr <id> <sigspec> <sigspec> <sigspec> <constant> <eol>

View File

@ -0,0 +1,37 @@
from pyosys import libyosys as ys
class AllEnablePass(ys.Pass):
def __init__(self):
super().__init__(
"all_enable",
"makes all _DFF_P_ registers require an enable signal"
)
def execute(self, args, design):
ys.log_header(design, "Adding enable signals\n")
ys.log_push()
top_module = design.top_module()
if "\\enable" not in top_module.wires_:
enable_line = top_module.addWire("\\enable")
enable_line.port_input = True
top_module.fixup_ports()
for cell in top_module.cells_.values():
if cell.type != "$_DFF_P_":
continue
cell.type = "$_DFFE_PP_"
cell.setPort("\\E", ys.SigSpec(enable_line))
ys.log_pop()
p = AllEnablePass() # register the pass
# using the pass
design = ys.Design()
ys.run_pass("read_verilog tests/simple/fiedler-cooley.v", design)
ys.run_pass("hierarchy -check -auto-top", design)
ys.run_pass("synth", design)
ys.run_pass("all_enable", design)
ys.run_pass("write_verilog out.v", design)
ys.run_pass("synth_ice40 -json out.json", design)

View File

@ -0,0 +1,51 @@
from pyosys import libyosys as ys
# loading design
design = ys.Design()
ys.run_pass("read_verilog tests/simple/fiedler-cooley.v", design)
ys.run_pass("hierarchy -check -auto-top", design)
# top module inspection
top_module = design.top_module()
for id, wire in top_module.wires_.items():
if not wire.port_input and not wire.port_output:
continue
description = "input" if wire.port_input else "output"
description += " " + wire.name.str()
if wire.width != 1:
frm = wire.start_offset
to = wire.start_offset + wire.width
if wire.upto:
to, frm = frm, to
description += f" [{to}:{frm}]"
print(description)
# synth
ys.run_pass("synth", design)
# adding the enable line
enable_line = top_module.addWire("\\enable")
enable_line.port_input = True
top_module.fixup_ports()
# hooking the enable line to the internal dff cells
for cell in top_module.cells_.values():
if cell.type != "$_DFF_P_":
continue
cell.type = "$_DFFE_PP_"
cell.setPort("\\E", ys.SigSpec(enable_line))
# run check
top_module.check()
ys.run_pass("stat", design)
# write outputs
ys.run_pass("write_verilog out.v", design)
ys.run_pass("synth_ice40 -json out.json", design)

View File

@ -6,7 +6,7 @@ import os
project = 'YosysHQ Yosys'
author = 'YosysHQ GmbH'
copyright ='2025 YosysHQ GmbH'
yosys_ver = "0.57"
yosys_ver = "0.58"
# select HTML theme
html_theme = 'furo-ys'

View File

@ -17,3 +17,4 @@ ways Yosys can interact with designs for a deeper investigation.
more_scripting/index
bugpoint
verilog
pyosys

View File

@ -0,0 +1,208 @@
Scripting with Pyosys
=====================
Pyosys is a limited subset of the Yosys C++ API (aka "libyosys") made available
using the Python programming language.
Like ``.ys`` and ``.tcl`` scripts, Pyosys provides an interface to write Yosys
scripts in the Python programming language, giving you the benefits of
a type system, control flow, object-oriented programming, and more; especially
that the other options lack a type system and control flow/OOP in Tcl is
limited.
Though unlike these two, Pyosys goes a bit further, allowing you to use the
Yosys API to implement advanced functionality that would otherwise require
custom passes written in C++.
Getting Pyosys
--------------
Pyosys supports CPython 3.8 or higher. You can access Pyosys using one of two
methods:
1. Compiling Yosys with the Makefile flag ``ENABLE_PYOSYS=1``
This adds the flag ``-y`` to the Yosys binary, which allows you to execute
Python scripts using an interpreter embedded in Yosys itself:
``yosys -y ./my_pyosys_script.py``
2. Installing the Pyosys wheels
On macOS and GNU/Linux you can install pre-built wheels of Yosys using
``pip``:
``python3 -m pip install pyosys``
Which then allows you to run your scripts as follows:
``python3 ./my_pyosys_script.py``
Scripting and Database Inspection
---------------------------------
To start with, you have to import libyosys as follows:
.. code-block:: python
from pyosys import libyosys
As a reminder, Python allows you to alias imported modules and objects, so
this import may be preferable for terseness:
.. code-block:: python
from pyosys import libyosys as ys
Now, scripting is actually quite similar to ``.ys`` and ``.tcl`` script in that
you can provide mostly text commands. Albeit, you can construct your scripts
to use Python's amenities like conditional execution, loops, and functions:
.. code-block:: python
do_flatten = True
ys.run_pass("read_verilog tests/simple/fiedler-cooley.v")
ys.run_pass("hierarchy -check -auto-top")
if do_flatten:
ys.run_pass("flatten")
…but this does not strictly provide anything that Tcl scripts do not provide you
with. The real power of using Pyosys comes from the fact you can manually
instantiate, manage, and interact with the design database.
As an example, here is the same script with a manually instantiated design.
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: loading design
:end-before: top module inspection
:language: python
What's new here is that you can manually inspect the design's database. This
gives you access to a huge chunk of the design database API as declared in
the ``kernel/rtlil.h`` header.
For example, here's how to list the input and output ports of the top module
of your design:
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: top module inspection
:end-before: # synth
:language: python
.. tip::
C++ data structures in Yosys are bridged to Python such that they have a
pretty similar API to Python objects, for example:
- ``std::vector`` supports the same methods as
`iterables <https://docs.python.org/3/glossary.html#term-iterable>`_ in
Python.
- ``std::set`` and hashlib ``pool`` support the same methods as ``set``\s in
Python. While ``set`` is ordered, ``pool`` is not and modifications may
cause a complete reordering of the set.
- ``dict`` supports the same methods as ``dict``\s in Python, albeit it is
unordered, and modifications may cause a complete reordering of the
dictionary.
- ``idict`` uses a custom set of methods because it doesn't map very cleanly
to an existing Python data structure. See ``pyosys/hashlib.h`` for more
info.
For most operations, the Python equivalents are also supported as arguments
where they will automatically be cast to the right type, so you do not have
to manually instantiate the right underlying C++ object(s) yourself.
Modifying the Database
----------------------
.. warning::
Any modifications to the database may invalidate previous references held
by Python, just as if you were writing C++. Pyosys does not currently attempt
to keep deleted objects alive if a reference is held by Python.
You are not restricted to inspecting the database either: you have the ability
to modify it, and introduce new elements and/or changes to your design.
As a demonstrative example, let's assume we want to add an enable line to all
flip-flops in our fiedler-cooley design.
First of all, we will run :yoscrypt:`synth` to convert all of the logic to
Yosys's internal cell structure (see :ref:`sec:celllib_gates`):
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: # synth
:end-before: adding the enable line
:language: python
Next, we need to add the new port. The method for this is ``Module::addWire``\.
.. tip::
IdString is Yosys's internal representation of strings used as identifiers
within Verilog designs. They are efficient as only integers are stored and
passed around, but they can be translated to and from normal strings at will.
Pyosys will automatically cast Python strings to IdStrings for you, but the
rules around IdStrings apply, namely that *broadly*:
- Identifiers for internal cells must start with ``$``\.
- All other identifiers must start with ``\``\.
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: adding the enable line
:end-before: hooking the enable line
:language: python
Notice how we modified the wire then called a method to make Yosys re-process
the ports.
Next, we can iterate over all constituent cells, and if they are of the type
``$_DFF_P_``, we do two things:
1. Change their type to ``$_DFFE_PP_`` to enable hooking up an enable signal.
2. Hooking up the enable signal.
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: hooking the enable line
:end-before: run check
:language: python
To verify that you did everything correctly, it is prudent to call ``.check()``
on the module you're manipulating as follows after you're done with a set of
changes:
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: run check
:end-before: write output
:language: python
And then finally, write your outputs. Here, I choose an intermediate Verilog
file and :yoscrypt:`synth_ice40` to map it to the iCE40 architecture.
.. literalinclude:: /code_examples/pyosys/simple_database.py
:start-after: write output
:language: python
And voilà, you will note that in the intermediate output, all ``always @``
statements should have an ``if (enable)``\.
Encapsulating as Passes
-----------------------
Just like when writing C++, you can encapsulate routines in terms of "passes",
which adds your Pass to a global registry of commands accessible using
``run_pass``\.
.. literalinclude:: /code_examples/pyosys/pass.py
:language: python
In general, abstract classes and virtual methods are not really supported by
Pyosys due to their complexity, but there are two exceptions which are:
- ``Pass`` in ``kernel/register.h``
- ``Monitor`` in ``kernel/rtlil.h``

View File

@ -36,7 +36,7 @@ The main characteristics are:
all compilers, standard libraries and architectures.
In addition to ``dict<K, T>`` and ``pool<T>`` there is also an ``idict<K>`` that
creates a bijective map from ``K`` to the integers. For example:
creates a bijective map from ``K`` to incrementing integers. For example:
::

View File

@ -1,22 +1,25 @@
#!/usr/bin/python3
import libyosys as ys
from pyosys import libyosys as ys
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
__file_dir__ = Path(__file__).absolute().parent
class CellStatsPass(ys.Pass):
def __init__(self):
super().__init__("cell_stats", "Shows cell stats as plot")
def py_help(self):
def help(self):
ys.log("This pass uses the matplotlib library to display cell stats\n")
def py_execute(self, args, design):
def execute(self, args, design):
ys.log_header(design, "Plotting cell stats\n")
cell_stats = {}
for module in design.selected_whole_modules_warn():
for module in design.all_selected_whole_modules():
for cell in module.selected_cells():
if cell.type.str() in cell_stats:
cell_stats[cell.type.str()] += 1
@ -26,7 +29,14 @@ class CellStatsPass(ys.Pass):
plt.xticks(range(len(cell_stats)), list(cell_stats.keys()))
plt.show()
def py_clear_flags(self):
def clear_flags(self):
ys.log("Clear Flags - CellStatsPass\n")
p = CellStatsPass()
p = CellStatsPass() # register
if __name__ == "__main__":
design = ys.Design()
ys.run_pass(f"read_verilog {__file_dir__.parents[1] / 'tests' / 'simple' / 'fiedler-cooley.v'}", design)
ys.run_pass("prep", design)
ys.run_pass("opt -full", design)
ys.run_pass("cell_stats", design)

View File

@ -1,19 +1 @@
GENFILES += frontends/rtlil/rtlil_parser.tab.cc
GENFILES += frontends/rtlil/rtlil_parser.tab.hh
GENFILES += frontends/rtlil/rtlil_parser.output
GENFILES += frontends/rtlil/rtlil_lexer.cc
frontends/rtlil/rtlil_parser.tab.cc: frontends/rtlil/rtlil_parser.y
$(Q) mkdir -p $(dir $@)
$(P) $(BISON) -o $@ -d -r all -b frontends/rtlil/rtlil_parser $<
frontends/rtlil/rtlil_parser.tab.hh: frontends/rtlil/rtlil_parser.tab.cc
frontends/rtlil/rtlil_lexer.cc: frontends/rtlil/rtlil_lexer.l
$(Q) mkdir -p $(dir $@)
$(P) flex -o frontends/rtlil/rtlil_lexer.cc $<
OBJS += frontends/rtlil/rtlil_parser.tab.o frontends/rtlil/rtlil_lexer.o
OBJS += frontends/rtlil/rtlil_frontend.o

View File

@ -17,27 +17,766 @@
*
* ---
*
* A very simple and straightforward frontend for the RTLIL text
* representation.
* A handwritten recursive-descent parser for the RTLIL text representation.
*
*/
#include "rtlil_frontend.h"
#include "kernel/register.h"
#include "kernel/log.h"
void rtlil_frontend_yyerror(char const *s)
{
YOSYS_NAMESPACE_PREFIX log_error("Parser error in line %d: %s\n", rtlil_frontend_yyget_lineno(), s);
}
void rtlil_frontend_yywarning(char const *s)
{
YOSYS_NAMESPACE_PREFIX log_warning("In line %d: %s\n", rtlil_frontend_yyget_lineno(), s);
}
#include "kernel/utils.h"
#include <charconv>
#include <deque>
#include <optional>
YOSYS_NAMESPACE_BEGIN
struct RTLILFrontendWorker {
// Forbid constants of more than 1 Gb.
// This will help us not explode on malicious RTLIL.
static constexpr int MAX_CONST_WIDTH = 1024 * 1024 * 1024;
std::istream *f = nullptr;
RTLIL::Design *design;
bool flag_nooverwrite = false;
bool flag_overwrite = false;
bool flag_lib = false;
int line_num;
std::string line_buf;
// Substring of line_buf. Always newline-terminated, thus never empty.
std::string_view line;
RTLIL::Module *current_module;
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
std::vector<RTLIL::CaseRule*> case_stack;
template <typename... Args>
[[noreturn]]
void error(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_error("Parser error in line %d: %s\n", line_num, fmt.format(args...));
}
template <typename... Args>
void warning(FmtString<TypeIdentity<Args>...> fmt, const Args &... args)
{
log_warning("In line %d: %s\n", line_num, fmt.format(args...));
}
// May return an empty line if the stream is not good().
void advance_to_next_nonempty_line()
{
if (!f->good()) {
line = "\n";
return;
}
while (true) {
std::getline(*f, line_buf);
line_num++;
if (line_buf.empty() || line_buf[line_buf.size() - 1] != '\n')
line_buf += '\n';
line = line_buf;
consume_whitespace_and_comments();
if (line[0] != '\n' || !f->good())
break;
}
}
void consume_whitespace_and_comments()
{
while (true) {
switch (line[0]) {
case ' ':
case '\t':
line = line.substr(1);
break;
case '#':
line = "\n";
return;
default:
return;
}
}
}
bool try_parse_keyword(std::string_view keyword)
{
int keyword_size = keyword.size();
if (keyword != line.substr(0, keyword_size))
return false;
// This index is safe because `line` is always newline-terminated
// and `keyword` never contains a newline.
char ch = line[keyword_size];
if (ch >= 'a' && ch <= 'z')
return false;
line = line.substr(keyword_size);
consume_whitespace_and_comments();
return true;
}
std::string error_token()
{
std::string result;
for (char ch : line) {
if (ch == '\n' || ch == ' ' || ch == '\t')
break;
result += ch;
}
return result;
}
void expect_keyword(std::string_view keyword)
{
if (!try_parse_keyword(keyword))
error("Expected token `%s', got `%s'.", keyword, error_token());
}
bool try_parse_char(char ch)
{
if (line[0] != ch)
return false;
line = line.substr(1);
consume_whitespace_and_comments();
return true;
}
void expect_char(char ch)
{
if (!try_parse_char(ch))
error("Expected `%c', got `%s'.", ch, error_token());
}
bool try_parse_eol()
{
if (line[0] != '\n')
return false;
advance_to_next_nonempty_line();
return true;
}
void expect_eol()
{
if (!try_parse_eol())
error("Expected EOL, got `%s'.", error_token());
}
std::optional<RTLIL::IdString> try_parse_id()
{
char ch = line[0];
if (ch != '\\' && ch != '$')
return std::nullopt;
int idx = 1;
while (true) {
ch = line[idx];
if (ch <= ' ' && (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'))
break;
++idx;
}
IdString result(line.substr(0, idx));
line = line.substr(idx);
consume_whitespace_and_comments();
return result;
}
RTLIL::IdString parse_id()
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (!id.has_value())
error("Expected ID, got `%s'.", error_token());
return std::move(*id);
}
long long parse_integer()
{
long long result = parse_integer_alone();
consume_whitespace_and_comments();
return result;
}
long long parse_integer_alone()
{
int idx = 0;
if (line[idx] == '-')
++idx;
while (true) {
char ch = line[idx];
if (ch < '0' || ch > '9')
break;
++idx;
}
long long result;
if (std::from_chars(line.data(), line.data() + idx, result, 10).ec != std::errc{})
error("Invalid integer `%s'.", error_token());
line = line.substr(idx);
return result;
}
std::string parse_string()
{
if (line[0] != '\"')
error("Expected string, got `%s'.", error_token());
std::string str;
int idx = 1;
while (true) {
int start_idx = idx;
char ch;
while (true) {
ch = line[idx];
if (ch == '"' || ch == '\n' || ch == '\\' || ch == 0)
break;
++idx;
}
str.append(line.data() + start_idx, line.data() + idx);
++idx;
if (ch == '"')
break;
if (ch == 0)
error("Null byte in string literal: `%s'.", line);
if (ch == '\n')
error("Unterminated string literal: `%s'.", line);
ch = line[idx++];
if (ch == 'n') {
ch = '\n';
} else if (ch == 't') {
ch = '\t';
} else if (ch >= '0' && ch <= '7') {
int v = ch - '0';
char next_ch = line[idx + 1];
if (next_ch >= '0' && next_ch <= '7') {
++idx;
v = v*8 + (next_ch - '0');
next_ch = line[idx + 1];
if (next_ch >= '0' && next_ch <= '7') {
++idx;
v = v*8 + (next_ch - '0');
}
}
ch = v;
}
str += ch;
}
line = line.substr(idx);
consume_whitespace_and_comments();
return str;
}
RTLIL::Const parse_const()
{
if (line[0] == '"')
return RTLIL::Const(parse_string());
bool negative_value = line[0] == '-';
long long width = parse_integer_alone();
// Can't test value<0 here because we need to stop parsing after '-0'
if (negative_value || line[0] != '\'') {
if (width < INT_MIN || width > INT_MAX)
error("Integer %lld out of range before `%s'.", width, error_token());
consume_whitespace_and_comments();
return RTLIL::Const(width);
}
int idx = 1;
bool is_signed = line[1] == 's';
if (is_signed)
++idx;
std::vector<RTLIL::State> bits;
if (width > MAX_CONST_WIDTH)
error("Constant width %lld out of range before `%s`.", width, error_token());
bits.reserve(width);
while (true) {
RTLIL::State bit;
switch (line[idx]) {
case '0': bit = RTLIL::S0; break;
case '1': bit = RTLIL::S1; break;
case 'x': bit = RTLIL::Sx; break;
case 'z': bit = RTLIL::Sz; break;
case 'm': bit = RTLIL::Sm; break;
case '-': bit = RTLIL::Sa; break;
default: goto done;
}
bits.push_back(bit);
++idx;
}
done:
std::reverse(bits.begin(), bits.end());
if (GetSize(bits) > width)
bits.resize(width);
else if (GetSize(bits) < width) {
RTLIL::State extbit = RTLIL::Sx;
if (!bits.empty()) {
extbit = bits.back();
if (extbit == RTLIL::S1)
extbit = RTLIL::S0;
}
bits.resize(width, extbit);
}
RTLIL::Const val(std::move(bits));
if (is_signed)
val.flags |= RTLIL::CONST_FLAG_SIGNED;
line = line.substr(idx);
consume_whitespace_and_comments();
return val;
}
RTLIL::SigSpec parse_sigspec()
{
RTLIL::SigSpec sig;
if (try_parse_char('{')) {
std::vector<SigSpec> parts;
while (!try_parse_char('}'))
parts.push_back(parse_sigspec());
for (auto it = parts.rbegin(); it != parts.rend(); ++it)
sig.append(std::move(*it));
} else {
// We could add a special path for parsing IdStrings that must already exist,
// as here.
// We don't need to addref/release in this case.
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
RTLIL::Wire *wire = current_module->wire(*id);
if (wire == nullptr)
error("Wire `%s' not found.", *id);
sig = RTLIL::SigSpec(wire);
} else {
sig = RTLIL::SigSpec(parse_const());
}
}
while (try_parse_char('[')) {
int left = parse_integer();
if (left >= sig.size() || left < 0)
error("bit index %d out of range", left);
if (try_parse_char(':')) {
int right = parse_integer();
if (right < 0)
error("bit index %d out of range", right);
if (left < right)
error("invalid slice [%d:%d]", left, right);
sig = sig.extract(right, left-right+1);
} else {
sig = sig.extract(left);
}
expect_char(']');
}
return sig;
}
void parse_module()
{
RTLIL::IdString module_name = parse_id();
expect_eol();
bool delete_current_module = false;
if (design->has(module_name)) {
RTLIL::Module *existing_mod = design->module(module_name);
if (!flag_overwrite && (flag_lib || (attrbuf.count(ID::blackbox) && attrbuf.at(ID::blackbox).as_bool()))) {
log("Ignoring blackbox re-definition of module %s.\n", module_name);
delete_current_module = true;
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
error("RTLIL error: redefinition of module %s.", module_name);
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", module_name);
delete_current_module = true;
} else {
log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", module_name);
design->remove(existing_mod);
}
}
current_module = new RTLIL::Module;
current_module->name = std::move(module_name);
current_module->attributes = std::move(attrbuf);
if (!delete_current_module)
design->add(current_module);
while (true)
{
if (try_parse_keyword("attribute")) {
parse_attribute();
continue;
}
if (try_parse_keyword("parameter")) {
parse_parameter();
continue;
}
if (try_parse_keyword("connect")) {
parse_connect();
continue;
}
if (try_parse_keyword("wire")) {
parse_wire();
continue;
}
if (try_parse_keyword("cell")) {
parse_cell();
continue;
}
if (try_parse_keyword("memory")) {
parse_memory();
continue;
}
if (try_parse_keyword("process")) {
parse_process();
continue;
}
if (try_parse_keyword("end")) {
expect_eol();
break;
}
error("Unexpected token in module body: %s", error_token());
}
if (attrbuf.size() != 0)
error("dangling attribute");
current_module->fixup_ports();
if (delete_current_module)
delete current_module;
else if (flag_lib)
current_module->makeblackbox();
current_module = nullptr;
}
void parse_attribute()
{
RTLIL::IdString id = parse_id();
RTLIL::Const c = parse_const();
attrbuf.insert({std::move(id), std::move(c)});
expect_eol();
}
void parse_parameter()
{
RTLIL::IdString id = parse_id();
current_module->avail_parameters(id);
if (try_parse_eol())
return;
RTLIL::Const c = parse_const();
current_module->parameter_default_values.insert({std::move(id), std::move(c)});
expect_eol();
}
void parse_wire()
{
RTLIL::Wire *wire;
int width = 1;
int start_offset = 0;
int port_id = 0;
bool port_input = false;
bool port_output = false;
bool upto = false;
bool is_signed = false;
while (true)
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
if (current_module->wire(*id) != nullptr)
error("RTLIL error: redefinition of wire %s.", *id);
wire = current_module->addWire(std::move(*id));
break;
}
if (try_parse_keyword("width"))
width = parse_integer();
else if (try_parse_keyword("upto"))
upto = true;
else if (try_parse_keyword("signed"))
is_signed = true;
else if (try_parse_keyword("offset"))
start_offset = parse_integer();
else if (try_parse_keyword("input")) {
port_id = parse_integer();
port_input = true;
} else if (try_parse_keyword("output")) {
port_id = parse_integer();
port_output = true;
} else if (try_parse_keyword("inout")) {
port_id = parse_integer();
port_input = true;
port_output = true;
} else if (try_parse_eol())
error("Missing wire ID");
else
error("Unexpected wire option: %s", error_token());
}
wire->attributes = std::move(attrbuf);
wire->width = width;
wire->upto = upto;
wire->start_offset = start_offset;
wire->is_signed = is_signed;
wire->port_id = port_id;
wire->port_input = port_input;
wire->port_output = port_output;
expect_eol();
}
void parse_memory()
{
RTLIL::Memory *memory = new RTLIL::Memory;
memory->attributes = std::move(attrbuf);
int width = 1;
int start_offset = 0;
int size = 0;
while (true)
{
std::optional<RTLIL::IdString> id = try_parse_id();
if (id.has_value()) {
if (current_module->memories.count(*id) != 0)
error("RTLIL error: redefinition of memory %s.", *id);
memory->name = std::move(*id);
break;
}
if (try_parse_keyword("width"))
width = parse_integer();
else if (try_parse_keyword("size"))
size = parse_integer();
else if (try_parse_keyword("offset"))
start_offset = parse_integer();
else if (try_parse_eol())
error("Missing memory ID");
else
error("Unexpected memory option: %s", error_token());
}
memory->width = width;
memory->start_offset = start_offset;
memory->size = size;
current_module->memories.insert({memory->name, memory});
expect_eol();
}
void parse_cell()
{
RTLIL::IdString cell_type = parse_id();
RTLIL::IdString cell_name = parse_id();
expect_eol();
if (current_module->cell(cell_name) != nullptr)
error("RTLIL error: redefinition of cell %s.", cell_name);
RTLIL::Cell *cell = current_module->addCell(cell_name, cell_type);
cell->attributes = std::move(attrbuf);
while (true)
{
if (try_parse_keyword("parameter")) {
bool is_signed = false;
bool is_real = false;
if (try_parse_keyword("signed")) {
is_signed = true;
} else if (try_parse_keyword("real")) {
is_real = true;
}
RTLIL::IdString param_name = parse_id();
RTLIL::Const val = parse_const();
if (is_signed)
val.flags |= RTLIL::CONST_FLAG_SIGNED;
if (is_real)
val.flags |= RTLIL::CONST_FLAG_REAL;
cell->parameters.insert({std::move(param_name), std::move(val)});
expect_eol();
} else if (try_parse_keyword("connect")) {
RTLIL::IdString port_name = parse_id();
if (cell->hasPort(port_name))
error("RTLIL error: redefinition of cell port %s.", port_name);
cell->setPort(std::move(port_name), parse_sigspec());
expect_eol();
} else if (try_parse_keyword("end")) {
expect_eol();
break;
} else {
error("Unexpected token in cell body: %s", error_token());
}
}
}
void parse_connect()
{
if (attrbuf.size() != 0)
error("dangling attribute");
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
current_module->connect(std::move(s1), std::move(s2));
expect_eol();
}
void parse_case_body(RTLIL::CaseRule *current_case)
{
while (true)
{
if (try_parse_keyword("attribute"))
parse_attribute();
else if (try_parse_keyword("switch"))
parse_switch();
else if (try_parse_keyword("assign")) {
if (attrbuf.size() != 0)
error("dangling attribute");
// See https://github.com/YosysHQ/yosys/pull/4765 for discussion on this
// warning
if (!switch_stack.back()->empty())
warning("case rule assign statements after switch statements may cause unexpected behaviour. "
"The assign statement is reordered to come before all switch statements.");
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
current_case->actions.push_back(RTLIL::SigSig(std::move(s1), std::move(s2)));
expect_eol();
} else
return;
}
}
void parse_switch()
{
RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
rule->signal = parse_sigspec();
rule->attributes = std::move(attrbuf);
switch_stack.back()->push_back(rule);
expect_eol();
while (true) {
if (try_parse_keyword("attribute")) {
parse_attribute();
continue;
}
if (try_parse_keyword("end")) {
expect_eol();
break;
}
expect_keyword("case");
RTLIL::CaseRule *case_rule = new RTLIL::CaseRule;
case_rule->attributes = std::move(attrbuf);
rule->cases.push_back(case_rule);
switch_stack.push_back(&case_rule->switches);
case_stack.push_back(case_rule);
if (!try_parse_eol()) {
while (true) {
case_rule->compare.push_back(parse_sigspec());
if (try_parse_eol())
break;
expect_char(',');
}
}
parse_case_body(case_rule);
switch_stack.pop_back();
case_stack.pop_back();
}
}
void parse_process()
{
RTLIL::IdString proc_name = parse_id();
expect_eol();
if (current_module->processes.count(proc_name) != 0)
error("RTLIL error: redefinition of process %s.", proc_name);
RTLIL::Process *proc = current_module->addProcess(std::move(proc_name));
proc->attributes = std::move(attrbuf);
switch_stack.clear();
switch_stack.push_back(&proc->root_case.switches);
case_stack.clear();
case_stack.push_back(&proc->root_case);
parse_case_body(&proc->root_case);
while (try_parse_keyword("sync"))
{
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
if (try_parse_keyword("low")) rule->type = RTLIL::ST0;
else if (try_parse_keyword("high")) rule->type = RTLIL::ST1;
else if (try_parse_keyword("posedge")) rule->type = RTLIL::STp;
else if (try_parse_keyword("negedge")) rule->type = RTLIL::STn;
else if (try_parse_keyword("edge")) rule->type = RTLIL::STe;
else if (try_parse_keyword("always")) rule->type = RTLIL::STa;
else if (try_parse_keyword("global")) rule->type = RTLIL::STg;
else if (try_parse_keyword("init")) rule->type = RTLIL::STi;
else error("Unexpected sync type: %s", error_token());
if (rule->type != RTLIL::STa && rule->type != RTLIL::STg && rule->type != RTLIL::STi)
rule->signal = parse_sigspec();
proc->syncs.push_back(rule);
expect_eol();
bool attributes_in_update_list = false;
while (true)
{
if (try_parse_keyword("update")) {
RTLIL::SigSpec s1 = parse_sigspec();
RTLIL::SigSpec s2 = parse_sigspec();
rule->actions.push_back(RTLIL::SigSig(std::move(s1), std::move(s2)));
expect_eol();
continue;
}
if (try_parse_keyword("attribute")) {
attributes_in_update_list = true;
parse_attribute();
continue;
}
if (!try_parse_keyword("memwr"))
break;
RTLIL::MemWriteAction act;
act.attributes = std::move(attrbuf);
act.memid = parse_id();
act.address = parse_sigspec();
act.data = parse_sigspec();
act.enable = parse_sigspec();
act.priority_mask = parse_const();
rule->mem_write_actions.push_back(std::move(act));
expect_eol();
}
// The old parser allowed dangling attributes before a "sync" to carry through
// the "sync", so we will too, for now.
if (attributes_in_update_list && attrbuf.size() > 0)
error("dangling attribute");
}
expect_keyword("end");
expect_eol();
}
RTLILFrontendWorker(RTLIL::Design *design) : design(design) {}
void parse(std::istream *f)
{
this->f = f;
line_num = 0;
advance_to_next_nonempty_line();
while (f->good())
{
if (try_parse_keyword("attribute")) {
parse_attribute();
continue;
}
if (try_parse_keyword("module")) {
parse_module();
continue;
}
if (try_parse_keyword("autoidx")) {
autoidx = std::max<int>(autoidx, parse_integer());
expect_eol();
continue;
}
error("Unexpected token: %s", error_token());
}
if (attrbuf.size() != 0)
error("dangling attribute");
}
};
struct RTLILFrontend : public Frontend {
RTLILFrontend() : Frontend("rtlil", "read modules from RTLIL file") { }
void help() override
@ -63,9 +802,7 @@ struct RTLILFrontend : public Frontend {
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
RTLIL_FRONTEND::flag_nooverwrite = false;
RTLIL_FRONTEND::flag_overwrite = false;
RTLIL_FRONTEND::flag_lib = false;
RTLILFrontendWorker worker(design);
log_header(design, "Executing RTLIL frontend.\n");
@ -73,17 +810,17 @@ struct RTLILFrontend : public Frontend {
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-nooverwrite") {
RTLIL_FRONTEND::flag_nooverwrite = true;
RTLIL_FRONTEND::flag_overwrite = false;
worker.flag_nooverwrite = true;
worker.flag_overwrite = false;
continue;
}
if (arg == "-overwrite") {
RTLIL_FRONTEND::flag_nooverwrite = false;
RTLIL_FRONTEND::flag_overwrite = true;
worker.flag_nooverwrite = false;
worker.flag_overwrite = true;
continue;
}
if (arg == "-lib") {
RTLIL_FRONTEND::flag_lib = true;
worker.flag_lib = true;
continue;
}
break;
@ -92,14 +829,8 @@ struct RTLILFrontend : public Frontend {
log("Input filename: %s\n", filename);
RTLIL_FRONTEND::lexin = f;
RTLIL_FRONTEND::current_design = design;
rtlil_frontend_yydebug = false;
rtlil_frontend_yyrestart(NULL);
rtlil_frontend_yyparse();
rtlil_frontend_yylex_destroy();
worker.parse(f);
}
} RTLILFrontend;
YOSYS_NAMESPACE_END

View File

@ -1,52 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
* A very simple and straightforward frontend for the RTLIL text
* representation.
*
*/
#ifndef RTLIL_FRONTEND_H
#define RTLIL_FRONTEND_H
#include "kernel/yosys.h"
YOSYS_NAMESPACE_BEGIN
namespace RTLIL_FRONTEND {
extern std::istream *lexin;
extern RTLIL::Design *current_design;
extern bool flag_nooverwrite;
extern bool flag_overwrite;
extern bool flag_lib;
}
YOSYS_NAMESPACE_END
extern int rtlil_frontend_yydebug;
int rtlil_frontend_yylex(void);
void rtlil_frontend_yyerror(char const *s);
void rtlil_frontend_yywarning(char const *s);
void rtlil_frontend_yyrestart(FILE *f);
int rtlil_frontend_yyparse(void);
int rtlil_frontend_yylex_destroy(void);
int rtlil_frontend_yyget_lineno(void);
#endif

View File

@ -1,150 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
* A very simple and straightforward frontend for the RTLIL text
* representation.
*
*/
%{
#ifdef __clang__
// bison generates code using the 'register' storage class specifier
#pragma clang diagnostic ignored "-Wdeprecated-register"
#endif
#include <cstdlib>
#include "frontends/rtlil/rtlil_frontend.h"
#include "rtlil_parser.tab.hh"
USING_YOSYS_NAMESPACE
#define YY_INPUT(buf,result,max_size) \
result = readsome(*RTLIL_FRONTEND::lexin, buf, max_size)
%}
%option yylineno
%option noyywrap
%option nounput
%option prefix="rtlil_frontend_yy"
%x STRING
%%
"autoidx" { return TOK_AUTOIDX; }
"module" { return TOK_MODULE; }
"attribute" { return TOK_ATTRIBUTE; }
"parameter" { return TOK_PARAMETER; }
"signed" { return TOK_SIGNED; }
"real" { return TOK_REAL; }
"wire" { return TOK_WIRE; }
"memory" { return TOK_MEMORY; }
"width" { return TOK_WIDTH; }
"upto" { return TOK_UPTO; }
"offset" { return TOK_OFFSET; }
"size" { return TOK_SIZE; }
"input" { return TOK_INPUT; }
"output" { return TOK_OUTPUT; }
"inout" { return TOK_INOUT; }
"cell" { return TOK_CELL; }
"connect" { return TOK_CONNECT; }
"switch" { return TOK_SWITCH; }
"case" { return TOK_CASE; }
"assign" { return TOK_ASSIGN; }
"sync" { return TOK_SYNC; }
"low" { return TOK_LOW; }
"high" { return TOK_HIGH; }
"posedge" { return TOK_POSEDGE; }
"negedge" { return TOK_NEGEDGE; }
"edge" { return TOK_EDGE; }
"always" { return TOK_ALWAYS; }
"global" { return TOK_GLOBAL; }
"init" { return TOK_INIT; }
"update" { return TOK_UPDATE; }
"memwr" { return TOK_MEMWR; }
"process" { return TOK_PROCESS; }
"end" { return TOK_END; }
[a-z]+ { return TOK_INVALID; }
"\\"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
"$"[^ \t\r\n]+ { rtlil_frontend_yylval.string = strdup(yytext); return TOK_ID; }
[0-9]+'s?[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; }
-?[0-9]+ {
char *end = nullptr;
errno = 0;
long value = strtol(yytext, &end, 10);
log_assert(end == yytext + strlen(yytext));
if (errno == ERANGE)
return TOK_INVALID; // literal out of range of long
if (value < INT_MIN || value > INT_MAX)
return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms)
rtlil_frontend_yylval.integer = value;
return TOK_INT;
}
\" { BEGIN(STRING); }
<STRING>\\. { yymore(); }
<STRING>\" {
BEGIN(0);
char *yystr = strdup(yytext);
yystr[strlen(yytext) - 1] = 0;
int i = 0, j = 0;
while (yystr[i]) {
if (yystr[i] == '\\' && yystr[i + 1]) {
i++;
if (yystr[i] == 'n')
yystr[i] = '\n';
else if (yystr[i] == 't')
yystr[i] = '\t';
else if ('0' <= yystr[i] && yystr[i] <= '7') {
yystr[i] = yystr[i] - '0';
if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0';
i++;
}
if ('0' <= yystr[i + 1] && yystr[i + 1] <= '7') {
yystr[i + 1] = yystr[i] * 8 + yystr[i + 1] - '0';
i++;
}
}
}
yystr[j++] = yystr[i++];
}
yystr[j] = 0;
rtlil_frontend_yylval.string = yystr;
return TOK_STRING;
}
<STRING>. { yymore(); }
"#"[^\n]* /* ignore comments */
[ \t] /* ignore non-newline whitespaces */
[\r\n]+ { return TOK_EOL; }
. { return *yytext; }
%%
// this is a hack to avoid the 'yyinput defined but not used' error msgs
void *rtlil_frontend_avoid_input_warnings() {
return (void*)&yyinput;
}

View File

@ -1,525 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
* A very simple and straightforward frontend for the RTLIL text
* representation.
*
*/
%require "3.0"
%{
#include <list>
#include "frontends/rtlil/rtlil_frontend.h"
YOSYS_NAMESPACE_BEGIN
namespace RTLIL_FRONTEND {
std::istream *lexin;
RTLIL::Design *current_design;
RTLIL::Module *current_module;
RTLIL::Wire *current_wire;
RTLIL::Memory *current_memory;
RTLIL::Cell *current_cell;
RTLIL::Process *current_process;
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
std::vector<RTLIL::CaseRule*> case_stack;
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
bool flag_nooverwrite, flag_overwrite, flag_lib;
bool delete_current_module;
}
using namespace RTLIL_FRONTEND;
YOSYS_NAMESPACE_END
USING_YOSYS_NAMESPACE
%}
%define api.prefix {rtlil_frontend_yy}
/* The union is defined in the header, so we need to provide all the
* includes it requires
*/
%code requires {
#include <string>
#include <vector>
#include "frontends/rtlil/rtlil_frontend.h"
}
%union {
char *string;
int integer;
YOSYS_NAMESPACE_PREFIX RTLIL::Const *data;
YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec *sigspec;
std::vector<YOSYS_NAMESPACE_PREFIX RTLIL::SigSpec> *rsigspec;
}
%token <string> TOK_ID TOK_VALUE TOK_STRING
%token <integer> TOK_INT
%token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT
%token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC
%token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT
%token TOK_UPDATE TOK_MEMWR TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO
%type <rsigspec> sigspec_list_reversed
%type <sigspec> sigspec sigspec_list
%type <integer> sync_type
%type <data> constant
%expect 0
%debug
%%
input:
optional_eol {
attrbuf.clear();
} design {
if (attrbuf.size() != 0)
rtlil_frontend_yyerror("dangling attribute");
};
EOL:
optional_eol TOK_EOL;
optional_eol:
optional_eol TOK_EOL | /* empty */;
design:
design module |
design attr_stmt |
design autoidx_stmt |
/* empty */;
module:
TOK_MODULE TOK_ID EOL {
delete_current_module = false;
if (current_design->has($2)) {
RTLIL::Module *existing_mod = current_design->module($2);
if (!flag_overwrite && (flag_lib || (attrbuf.count(ID::blackbox) && attrbuf.at(ID::blackbox).as_bool()))) {
log("Ignoring blackbox re-definition of module %s.\n", $2);
delete_current_module = true;
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) {
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of module %s.", $2).c_str());
} else if (flag_nooverwrite) {
log("Ignoring re-definition of module %s.\n", $2);
delete_current_module = true;
} else {
log("Replacing existing%s module %s.\n", existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "", $2);
current_design->remove(existing_mod);
}
}
current_module = new RTLIL::Module;
current_module->name = $2;
current_module->attributes = attrbuf;
if (!delete_current_module)
current_design->add(current_module);
attrbuf.clear();
free($2);
} module_body TOK_END {
if (attrbuf.size() != 0)
rtlil_frontend_yyerror("dangling attribute");
current_module->fixup_ports();
if (delete_current_module)
delete current_module;
else if (flag_lib)
current_module->makeblackbox();
current_module = nullptr;
} EOL;
module_body:
module_body module_stmt |
/* empty */;
module_stmt:
param_stmt | param_defval_stmt | attr_stmt | wire_stmt | memory_stmt | cell_stmt | proc_stmt | conn_stmt;
param_stmt:
TOK_PARAMETER TOK_ID EOL {
current_module->avail_parameters($2);
free($2);
};
param_defval_stmt:
TOK_PARAMETER TOK_ID constant EOL {
current_module->avail_parameters($2);
current_module->parameter_default_values[$2] = *$3;
delete $3;
free($2);
};
attr_stmt:
TOK_ATTRIBUTE TOK_ID constant EOL {
attrbuf[$2] = *$3;
delete $3;
free($2);
};
autoidx_stmt:
TOK_AUTOIDX TOK_INT EOL {
autoidx = max(autoidx, $2);
};
wire_stmt:
TOK_WIRE {
current_wire = current_module->addWire("$__rtlil_frontend_tmp__");
current_wire->attributes = attrbuf;
attrbuf.clear();
} wire_options TOK_ID EOL {
if (current_module->wire($4) != nullptr)
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of wire %s.", $4).c_str());
current_module->rename(current_wire, $4);
free($4);
};
wire_options:
wire_options TOK_WIDTH TOK_INT {
current_wire->width = $3;
} |
wire_options TOK_WIDTH TOK_INVALID {
rtlil_frontend_yyerror("RTLIL error: invalid wire width");
} |
wire_options TOK_UPTO {
current_wire->upto = true;
} |
wire_options TOK_SIGNED {
current_wire->is_signed = true;
} |
wire_options TOK_OFFSET TOK_INT {
current_wire->start_offset = $3;
} |
wire_options TOK_INPUT TOK_INT {
current_wire->port_id = $3;
current_wire->port_input = true;
current_wire->port_output = false;
} |
wire_options TOK_OUTPUT TOK_INT {
current_wire->port_id = $3;
current_wire->port_input = false;
current_wire->port_output = true;
} |
wire_options TOK_INOUT TOK_INT {
current_wire->port_id = $3;
current_wire->port_input = true;
current_wire->port_output = true;
} |
/* empty */;
memory_stmt:
TOK_MEMORY {
current_memory = new RTLIL::Memory;
current_memory->attributes = attrbuf;
attrbuf.clear();
} memory_options TOK_ID EOL {
if (current_module->memories.count($4) != 0)
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of memory %s.", $4).c_str());
current_memory->name = $4;
current_module->memories[$4] = current_memory;
free($4);
};
memory_options:
memory_options TOK_WIDTH TOK_INT {
current_memory->width = $3;
} |
memory_options TOK_SIZE TOK_INT {
current_memory->size = $3;
} |
memory_options TOK_OFFSET TOK_INT {
current_memory->start_offset = $3;
} |
/* empty */;
cell_stmt:
TOK_CELL TOK_ID TOK_ID EOL {
if (current_module->cell($3) != nullptr)
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell %s.", $3).c_str());
current_cell = current_module->addCell($3, $2);
current_cell->attributes = attrbuf;
attrbuf.clear();
free($2);
free($3);
} cell_body TOK_END EOL;
cell_body:
cell_body TOK_PARAMETER TOK_ID constant EOL {
current_cell->parameters[$3] = *$4;
free($3);
delete $4;
} |
cell_body TOK_PARAMETER TOK_SIGNED TOK_ID constant EOL {
current_cell->parameters[$4] = *$5;
current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_SIGNED;
free($4);
delete $5;
} |
cell_body TOK_PARAMETER TOK_REAL TOK_ID constant EOL {
current_cell->parameters[$4] = *$5;
current_cell->parameters[$4].flags |= RTLIL::CONST_FLAG_REAL;
free($4);
delete $5;
} |
cell_body TOK_CONNECT TOK_ID sigspec EOL {
if (current_cell->hasPort($3))
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of cell port %s.", $3).c_str());
current_cell->setPort($3, *$4);
delete $4;
free($3);
} |
/* empty */;
proc_stmt:
TOK_PROCESS TOK_ID EOL {
if (current_module->processes.count($2) != 0)
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of process %s.", $2).c_str());
current_process = current_module->addProcess($2);
current_process->attributes = attrbuf;
switch_stack.clear();
switch_stack.push_back(&current_process->root_case.switches);
case_stack.clear();
case_stack.push_back(&current_process->root_case);
attrbuf.clear();
free($2);
} case_body sync_list TOK_END EOL;
switch_stmt:
TOK_SWITCH sigspec EOL {
RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
rule->signal = *$2;
rule->attributes = attrbuf;
switch_stack.back()->push_back(rule);
attrbuf.clear();
delete $2;
} attr_list switch_body TOK_END EOL;
attr_list:
/* empty */ |
attr_list attr_stmt;
switch_body:
switch_body TOK_CASE {
RTLIL::CaseRule *rule = new RTLIL::CaseRule;
rule->attributes = attrbuf;
switch_stack.back()->back()->cases.push_back(rule);
switch_stack.push_back(&rule->switches);
case_stack.push_back(rule);
attrbuf.clear();
} compare_list EOL case_body {
switch_stack.pop_back();
case_stack.pop_back();
} |
/* empty */;
compare_list:
sigspec {
case_stack.back()->compare.push_back(*$1);
delete $1;
} |
compare_list ',' sigspec {
case_stack.back()->compare.push_back(*$3);
delete $3;
} |
/* empty */;
case_body:
case_body attr_stmt |
case_body switch_stmt |
case_body assign_stmt |
/* empty */;
assign_stmt:
TOK_ASSIGN sigspec sigspec EOL {
if (attrbuf.size() != 0)
rtlil_frontend_yyerror("dangling attribute");
// See https://github.com/YosysHQ/yosys/pull/4765 for discussion on this
// warning
if (!switch_stack.back()->empty()) {
rtlil_frontend_yywarning(
"case rule assign statements after switch statements may cause unexpected behaviour. "
"The assign statement is reordered to come before all switch statements."
);
}
case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
delete $2;
delete $3;
};
sync_list:
sync_list TOK_SYNC sync_type sigspec EOL {
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
rule->type = RTLIL::SyncType($3);
rule->signal = *$4;
current_process->syncs.push_back(rule);
delete $4;
} update_list |
sync_list TOK_SYNC TOK_ALWAYS EOL {
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
rule->type = RTLIL::SyncType::STa;
rule->signal = RTLIL::SigSpec();
current_process->syncs.push_back(rule);
} update_list |
sync_list TOK_SYNC TOK_GLOBAL EOL {
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
rule->type = RTLIL::SyncType::STg;
rule->signal = RTLIL::SigSpec();
current_process->syncs.push_back(rule);
} update_list |
sync_list TOK_SYNC TOK_INIT EOL {
RTLIL::SyncRule *rule = new RTLIL::SyncRule;
rule->type = RTLIL::SyncType::STi;
rule->signal = RTLIL::SigSpec();
current_process->syncs.push_back(rule);
} update_list |
/* empty */;
sync_type:
TOK_LOW { $$ = RTLIL::ST0; } |
TOK_HIGH { $$ = RTLIL::ST1; } |
TOK_POSEDGE { $$ = RTLIL::STp; } |
TOK_NEGEDGE { $$ = RTLIL::STn; } |
TOK_EDGE { $$ = RTLIL::STe; };
update_list:
update_list TOK_UPDATE sigspec sigspec EOL {
current_process->syncs.back()->actions.push_back(RTLIL::SigSig(*$3, *$4));
delete $3;
delete $4;
} |
update_list attr_list TOK_MEMWR TOK_ID sigspec sigspec sigspec constant EOL {
RTLIL::MemWriteAction act;
act.attributes = attrbuf;
act.memid = $4;
act.address = *$5;
act.data = *$6;
act.enable = *$7;
act.priority_mask = *$8;
current_process->syncs.back()->mem_write_actions.push_back(std::move(act));
attrbuf.clear();
free($4);
delete $5;
delete $6;
delete $7;
delete $8;
} |
/* empty */;
constant:
TOK_VALUE {
char *ep;
int width = strtol($1, &ep, 10);
bool is_signed = false;
if (*ep == '\'') {
ep++;
}
if (*ep == 's') {
is_signed = true;
ep++;
}
std::list<RTLIL::State> bits;
while (*ep != 0) {
RTLIL::State bit = RTLIL::Sx;
switch (*ep) {
case '0': bit = RTLIL::S0; break;
case '1': bit = RTLIL::S1; break;
case 'x': bit = RTLIL::Sx; break;
case 'z': bit = RTLIL::Sz; break;
case '-': bit = RTLIL::Sa; break;
case 'm': bit = RTLIL::Sm; break;
}
bits.push_front(bit);
ep++;
}
if (bits.size() == 0)
bits.push_back(RTLIL::Sx);
while ((int)bits.size() < width) {
RTLIL::State bit = bits.back();
if (bit == RTLIL::S1)
bit = RTLIL::S0;
bits.push_back(bit);
}
while ((int)bits.size() > width)
bits.pop_back();
RTLIL::Const::Builder builder(bits.size());
for (RTLIL::State bit : bits)
builder.push_back(bit);
$$ = new RTLIL::Const(builder.build());
if (is_signed) {
$$->flags |= RTLIL::CONST_FLAG_SIGNED;
}
free($1);
} |
TOK_INT {
$$ = new RTLIL::Const($1);
} |
TOK_STRING {
$$ = new RTLIL::Const($1);
free($1);
};
sigspec:
constant {
$$ = new RTLIL::SigSpec(*$1);
delete $1;
} |
TOK_ID {
if (current_module->wire($1) == nullptr)
rtlil_frontend_yyerror(stringf("RTLIL error: wire %s not found", $1).c_str());
$$ = new RTLIL::SigSpec(current_module->wire($1));
free($1);
} |
sigspec '[' TOK_INT ']' {
if ($3 >= $1->size() || $3 < 0)
rtlil_frontend_yyerror("bit index out of range");
$$ = new RTLIL::SigSpec($1->extract($3));
delete $1;
} |
sigspec '[' TOK_INT ':' TOK_INT ']' {
if ($3 >= $1->size() || $3 < 0 || $3 < $5)
rtlil_frontend_yyerror("invalid slice");
$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1));
delete $1;
} |
'{' sigspec_list '}' {
$$ = $2;
};
sigspec_list_reversed:
sigspec_list_reversed sigspec {
$$->push_back(*$2);
delete $2;
} |
/* empty */ {
$$ = new std::vector<RTLIL::SigSpec>;
};
sigspec_list: sigspec_list_reversed {
$$ = new RTLIL::SigSpec;
for (auto it = $1->rbegin(); it != $1->rend(); it++)
$$->append(*it);
delete $1;
};
conn_stmt:
TOK_CONNECT sigspec sigspec EOL {
if (attrbuf.size() != 0)
rtlil_frontend_yyerror("dangling attribute");
current_module->connect(*$2, *$3);
delete $2;
delete $3;
};

View File

@ -135,13 +135,13 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil
if (log_verific_callback) {
string full_message = stringf("%s%s\n", message_prefix, message);
#ifdef VERIFIC_LINEFILE_INCLUDES_COLUMNS
log_verific_callback(int(msg_type), message_id, LineFile::GetFileName(linefile),
linefile ? linefile->GetLeftLine() : 0, linefile ? linefile->GetLeftCol() : 0,
#ifdef VERIFIC_LINEFILE_INCLUDES_COLUMNS
log_verific_callback(int(msg_type), message_id, LineFile::GetFileName(linefile),
linefile ? linefile->GetLeftLine() : 0, linefile ? linefile->GetLeftCol() : 0,
linefile ? linefile->GetRightLine() : 0, linefile ? linefile->GetRightCol() : 0, full_message.c_str());
#else
log_verific_callback(int(msg_type), message_id, LineFile::GetFileName(linefile),
linefile ? LineFile::GetLineNo(linefile) : 0, 0,
log_verific_callback(int(msg_type), message_id, LineFile::GetFileName(linefile),
linefile ? LineFile::GetLineNo(linefile) : 0, 0,
linefile ? LineFile::GetLineNo(linefile) : 0, 0, full_message.c_str());
#endif
} else {
@ -171,6 +171,25 @@ string get_full_netlist_name(Netlist *nl)
return nl->CellBaseName();
}
std::string format_src_location(DesignObj *obj)
{
if (obj == nullptr || !obj->Linefile())
return std::string();
#ifdef VERIFIC_LINEFILE_INCLUDES_COLUMNS
return stringf("%s:%d.%d-%d.%d", LineFile::GetFileName(obj->Linefile()), obj->Linefile()->GetLeftLine(), obj->Linefile()->GetLeftCol(), obj->Linefile()->GetRightLine(), obj->Linefile()->GetRightCol());
#else
return stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
#endif
}
std::string announce_src_location(DesignObj *obj)
{
std::string loc = format_src_location(obj);
if (loc.empty())
return std::string();
return loc + ": ";
}
#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
class YosysStreamCallBackHandler : public VerificStreamCallBackHandler
{
@ -313,7 +332,7 @@ static const RTLIL::Const extract_vhdl_const(const char *value, bool output_sig
bool isBinary = std::all_of(data.begin(), data.end(), [](char c) {return c=='1' || c=='0'; });
if (isBinary)
c = RTLIL::Const::from_string(data);
else
else
c = RTLIL::Const(data);
} else if (val.size()==3 && val[0]=='\'' && val.back()=='\'') {
c = RTLIL::Const::from_string(val.substr(1,val.size()-2));
@ -403,7 +422,7 @@ static const RTLIL::Const verific_const(const char* type_name, const char *value
// SystemVerilog
if (type_name && strcmp(type_name, "real")==0) {
return extract_real_value(val);
} else
} else
return extract_verilog_const(value, allow_string, output_signed);
}
@ -425,14 +444,8 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
MapIter mi;
Att *attr;
#ifdef VERIFIC_LINEFILE_INCLUDES_COLUMNS
if (obj->Linefile()) {
attributes[ID::src] = stringf("%s:%d.%d-%d.%d", LineFile::GetFileName(obj->Linefile()), obj->Linefile()->GetLeftLine(), obj->Linefile()->GetLeftCol(), obj->Linefile()->GetRightLine(), obj->Linefile()->GetRightCol());
}
#else
if (obj->Linefile())
attributes[ID::src] = stringf("%s:%d", LineFile::GetFileName(obj->Linefile()), LineFile::GetLineNo(obj->Linefile()));
#endif
attributes[ID::src] = format_src_location(obj);
FOREACH_ATTRIBUTE(obj, mi, attr) {
if (attr->Key()[0] == ' ' || attr->Value() == nullptr)
@ -518,7 +531,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
}
}
if (p == nullptr)
log_error("Expected TypeRange value '%s' to be of form \"<binary>\" or <binary>.\n", v);
log_error("%sExpected TypeRange value '%s' to be of form \"<binary>\" or <binary>.\n", announce_src_location(obj), v);
}
#endif
}
@ -1000,7 +1013,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
else if (net_cin == net_a_msb)
cell = module->addSshr(inst_name, IN1, IN2, OUT, true);
else
log_error("Can't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", inst->Name());
log_error("%sCan't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", announce_src_location(inst), inst->Name());
import_attributes(cell->attributes, inst);
return true;
}
@ -1054,7 +1067,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
else if (net_cin->IsPwr())
cell = module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);
else
log_error("Can't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", inst->Name());
log_error("%sCan't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", announce_src_location(inst), inst->Name());
import_attributes(cell->attributes, inst);
return true;
}
@ -1279,7 +1292,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
for (unsigned j = 0 ; j < selector->GetNumConditions(i) ; ++j) {
Array left_bound, right_bound ;
selector->GetCondition(i, j, &left_bound, &right_bound);
SigSpec sel_left = sig_select_values.extract(offset_select, select_width);
offset_select += select_width;
@ -1554,7 +1567,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
char *architecture_name = name_space.ReName(nl->Name()) ;
module->set_string_attribute(ID(architecture), (architecture_name) ? architecture_name : nl->Name());
}
#endif
#endif
const char *param_name ;
const char *param_value ;
MapIter mi;
@ -1686,7 +1699,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
bits_in_word = min<uint64_t>(bits_in_word, pr->GetInst()->Input2Size());
continue;
}
log_error("Verific RamNet %s is connected to unsupported instance type %s (%s).\n",
log_error("%sVerific RamNet %s is connected to unsupported instance type %s (%s).\n", announce_src_location(pr->GetInst()),
net->Name(), pr->GetInst()->View()->Owner()->Name(), pr->GetInst()->Name());
}
memory->width = bits_in_word;
@ -1709,7 +1722,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
if (*ascii_initdata == 0)
break;
if (*ascii_initdata == '0' || *ascii_initdata == '1') {
initval.bits()[bit_idx] = (*ascii_initdata == '0') ? State::S0 : State::S1;
initval.set(bit_idx, (*ascii_initdata == '0') ? State::S0 : State::S1);
initval_valid = true;
}
ascii_initdata++;
@ -1833,9 +1846,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
if (init_nets.count(net)) {
if (init_nets.at(net) == '0')
initval.bits().at(bitidx) = State::S0;
initval.set(bitidx, State::S0);
if (init_nets.at(net) == '1')
initval.bits().at(bitidx) = State::S1;
initval.set(bitidx, State::S1);
initval_valid = true;
init_nets.erase(net);
}
@ -1908,13 +1921,13 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
if (bit.wire->attributes.count(ID::init))
initval = bit.wire->attributes.at(ID::init);
while (GetSize(initval) < GetSize(bit.wire))
initval.bits().push_back(State::Sx);
if (GetSize(initval) < GetSize(bit.wire))
initval.resize(GetSize(bit.wire), State::Sx);
if (it.second == '0')
initval.bits().at(bit.offset) = State::S0;
initval.set(bit.offset, State::S0);
if (it.second == '1')
initval.bits().at(bit.offset) = State::S1;
initval.set(bit.offset, State::S1);
bit.wire->attributes[ID::init] = initval;
}
@ -1975,7 +1988,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
{
RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetInput()->Name()), nullptr);
if (!memory)
log_error("Memory net '%s' missing, possibly no driver, use verific -flatten.\n", inst->GetInput()->Name());
log_error("%sMemory net '%s' missing, possibly no driver, use verific -flatten.\n", announce_src_location(inst), inst->GetInput()->Name());
int numchunks = int(inst->OutputSize()) / memory->width;
int chunksbits = ceil_log2(numchunks);
@ -2006,7 +2019,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
{
RTLIL::Memory *memory = module->memories.at(RTLIL::escape_id(inst->GetOutput()->Name()), nullptr);
if (!memory)
log_error("Memory net '%s' missing, possibly no driver, use verific -flatten.\n", inst->GetInput()->Name());
log_error("%sMemory net '%s' missing, possibly no driver, use verific -flatten.\n", announce_src_location(inst), inst->GetInput()->Name());
int numchunks = int(inst->Input2Size()) / memory->width;
int chunksbits = ceil_log2(numchunks);
@ -2041,7 +2054,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
if (import_netlist_instance_cells(inst, inst_name))
continue;
if (inst->IsOperator() && !verific_sva_prims.count(inst->Type()))
log_warning("Unsupported Verific operator: %s (fallback to gate level implementation provided by verific)\n", inst->View()->Owner()->Name());
log_warning("%sUnsupported Verific operator: %s (fallback to gate level implementation provided by verific)\n", announce_src_location(inst), inst->View()->Owner()->Name());
} else {
if (import_netlist_instance_gates(inst, inst_name))
continue;
@ -2101,7 +2114,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
}
Const qx_init = Const(State::S1, width);
qx_init.bits().resize(2 * width, State::S0);
qx_init.resize(2 * width, State::S0);
clocking.addDff(new_verific_id(inst), sig_dx, sig_qx, qx_init);
module->addXnor(new_verific_id(inst), sig_dx, sig_qx, sig_ox);
@ -2227,10 +2240,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
if (inst->IsPrimitive())
{
if (!mode_keep)
log_error("Unsupported Verific primitive %s of type %s\n", inst->Name(), inst->View()->Owner()->Name());
log_error("%sUnsupported Verific primitive %s of type %s\n", announce_src_location(inst), inst->Name(), inst->View()->Owner()->Name());
if (!verific_sva_prims.count(inst->Type()))
log_warning("Unsupported Verific primitive %s of type %s\n", inst->Name(), inst->View()->Owner()->Name());
log_warning("%sUnsupported Verific primitive %s of type %s\n", announce_src_location(inst), inst->Name(), inst->View()->Owner()->Name());
}
import_verific_cells:
@ -2366,7 +2379,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
continue;
if (non_ff_bits.count(SigBit(wire, i)))
initval.bits()[i] = State::Sx;
initval.set(i, State::Sx);
}
if (wire->port_input) {
@ -2559,7 +2572,7 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
if (c.wire && c.wire->attributes.count(ID::init)) {
Const val = c.wire->attributes.at(ID::init);
for (int i = 0; i < GetSize(c); i++)
initval.bits()[offset+i] = val[c.offset+i];
initval.set(offset+i, val[c.offset+i]);
}
offset += GetSize(c);
}
@ -2630,7 +2643,7 @@ Cell *VerificClocking::addAldff(IdString name, RTLIL::SigSpec sig_aload, RTLIL::
if (c.wire && c.wire->attributes.count(ID::init)) {
Const val = c.wire->attributes.at(ID::init);
for (int i = 0; i < GetSize(c); i++)
initval.bits()[offset+i] = val[c.offset+i];
initval.set(offset+i, val[c.offset+i]);
}
offset += GetSize(c);
}
@ -2811,13 +2824,13 @@ void save_blackbox_msg_state()
void restore_blackbox_msg_state()
{
#ifdef VERIFIC_SYSTEMVERILOG_SUPPORT
Message::ClearMessageType("VERI-1063") ;
Message::ClearMessageType("VERI-1063") ;
if (Message::GetMessageType("VERI-1063")!=prev_1063)
Message::SetMessageType("VERI-1063", prev_1063);
#endif
#ifdef VERIFIC_VHDL_SUPPORT
Message::ClearMessageType("VHDL-1240") ;
Message::ClearMessageType("VHDL-1241") ;
Message::ClearMessageType("VHDL-1240") ;
Message::ClearMessageType("VHDL-1241") ;
if (Message::GetMessageType("VHDL-1240")!=prev_1240)
Message::SetMessageType("VHDL-1240", prev_1240);
if (Message::GetMessageType("VHDL-1241")!=prev_1241)
@ -3415,7 +3428,7 @@ struct VerificPass : public Pass {
log("\n");
#if defined(YOSYS_ENABLE_VERIFIC) and defined(YOSYSHQ_VERIFIC_EXTENSIONS)
VerificExtensions::Help();
#endif
#endif
log("Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n");
log("https://www.yosyshq.com/\n");
log("\n");
@ -3471,7 +3484,7 @@ struct VerificPass : public Pass {
VhdlPrimaryUnit *unit ;
if (!flag_lib) return;
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
if (vhdl_lib) {
if (vhdl_lib) {
FOREACH_VHDL_PRIMARY_UNIT(vhdl_lib, mi, unit) {
if (!unit) continue;
map.Insert(unit,unit);
@ -3503,7 +3516,7 @@ struct VerificPass : public Pass {
VeriModule *veri_module ;
if (!flag_lib) return;
VeriLibrary *veri_lib = veri_file::GetLibrary(work.c_str(), 1);
if (veri_lib) {
if (veri_lib) {
FOREACH_VERILOG_MODULE_IN_LIBRARY(veri_lib, mi, veri_module) {
if (!veri_module) continue;
map.Insert(veri_module,veri_module);
@ -4501,12 +4514,12 @@ struct VerificPass : public Pass {
}
}
#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
if (VerificExtensions::Execute(args, argidx, work,
if (VerificExtensions::Execute(args, argidx, work,
[this](const std::vector<std::string> &args, size_t argidx, std::string msg)
{ cmd_error(args, argidx, msg); } )) {
goto check_error;
}
#endif
#endif
cmd_error(args, argidx, "Missing or unsupported mode parameter.\n");

View File

@ -577,7 +577,7 @@ struct SvaFsm
if (delta_pos >= 0 && i_within_j && j_within_i) {
did_something = true;
values[i].bits()[delta_pos] = State::Sa;
values[i].set(delta_pos, State::Sa);
values[j] = values.back();
values.pop_back();
goto next_pair;

View File

@ -37,6 +37,12 @@
# include <tcl.h>
#endif
#ifdef YOSYS_ENABLE_PYTHON
# include <Python.h>
# include <pybind11/pybind11.h>
namespace py = pybind11;
#endif
#include <stdio.h>
#include <string.h>
#include <limits.h>
@ -91,9 +97,10 @@ int main(int argc, char **argv)
log_error_stderr = true;
yosys_banner();
yosys_setup();
#ifdef WITH_PYTHON
PyRun_SimpleString(("sys.path.append(\""+proc_self_dirname()+"\")").c_str());
PyRun_SimpleString(("sys.path.append(\""+proc_share_dirname()+"plugins\")").c_str());
#ifdef YOSYS_ENABLE_PYTHON
py::object sys = py::module_::import("sys");
sys.attr("path").attr("append")(proc_self_dirname());
sys.attr("path").attr("append")(proc_share_dirname());
#endif
if (argc == 2)
@ -226,10 +233,10 @@ int main(int argc, char **argv)
cxxopts::value<std::string>(),"<tcl_scriptfile>")
("C,tcl-interactive", "enters TCL interactive shell mode")
#endif // YOSYS_ENABLE_TCL
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
("y,py-scriptfile", "execute the Python <script>",
cxxopts::value<std::string>(), "<script>")
#endif // WITH_PYTHON
#endif // YOSYS_ENABLE_PYTHON
("p,commands", "execute <commands> (to chain commands, separate them with semicolon + whitespace: 'cmd1; cmd2')",
cxxopts::value<std::vector<std::string>>(), "<commands>")
("r,top", "elaborate the specified HDL <top> module",
@ -515,9 +522,10 @@ int main(int argc, char **argv)
#endif
yosys_setup();
#ifdef WITH_PYTHON
PyRun_SimpleString(("sys.path.append(\""+proc_self_dirname()+"\")").c_str());
PyRun_SimpleString(("sys.path.append(\""+proc_share_dirname()+"plugins\")").c_str());
#ifdef YOSYS_ENABLE_PYTHON
py::object sys = py::module_::import("sys");
sys.attr("path").attr("append")(proc_self_dirname());
sys.attr("path").attr("append")(proc_share_dirname());
#endif
log_error_atexit = yosys_atexit;
@ -566,22 +574,19 @@ int main(int argc, char **argv)
log_error("Can't execute TCL script: this version of yosys is not built with TCL support enabled.\n");
#endif
} else if (scriptfile_python) {
#ifdef WITH_PYTHON
PyObject *sys = PyImport_ImportModule("sys");
#ifdef YOSYS_ENABLE_PYTHON
py::list new_argv;
int py_argc = special_args.size() + 1;
PyObject *new_argv = PyList_New(py_argc);
PyList_SetItem(new_argv, 0, PyUnicode_FromString(scriptfile.c_str()));
new_argv.append(scriptfile);
for (int i = 1; i < py_argc; ++i)
PyList_SetItem(new_argv, i, PyUnicode_FromString(special_args[i - 1].c_str()));
new_argv.append(special_args[i - 1]);
PyObject *old_argv = PyObject_GetAttrString(sys, "argv");
PyObject_SetAttrString(sys, "argv", new_argv);
Py_DECREF(old_argv);
py::setattr(sys, "argv", new_argv);
PyObject *py_path = PyUnicode_FromString(scriptfile.c_str());
PyObject_SetAttrString(sys, "_yosys_script_path", py_path);
Py_DECREF(py_path);
PyRun_SimpleString("import os, sys; sys.path.insert(0, os.path.dirname(os.path.abspath(sys._yosys_script_path)))");
py::object Path = py::module_::import("pathlib").attr("Path");
py::object scriptfile_python_path = Path(scriptfile).attr("parent");
sys.attr("path").attr("insert")(0, py::str(scriptfile_python_path));
FILE *scriptfp = fopen(scriptfile.c_str(), "r");
if (scriptfp == nullptr) {

View File

@ -13,6 +13,7 @@
#define HASHLIB_H
#include <array>
#include <atomic>
#include <stdexcept>
#include <algorithm>
#include <set>
@ -1361,8 +1362,18 @@ public:
template<typename K, typename OPS>
class mfp
{
mutable idict<K, 0, OPS> database;
mutable std::vector<int> parents;
idict<K, 0, OPS> database;
class AtomicParent {
public:
explicit AtomicParent(int p) : parent(p) {}
AtomicParent(const AtomicParent &other) : parent(other.get()) {}
AtomicParent &operator=(const AtomicParent &other) { set(other.get()); return *this; }
int get() const { return parent.load(std::memory_order_relaxed); }
void set(int p) { parent.store(p, std::memory_order_relaxed); }
private:
std::atomic<int> parent;
};
std::vector<AtomicParent> parents;
public:
typedef typename idict<K, 0>::const_iterator const_iterator;
@ -1373,12 +1384,14 @@ public:
// Finds a given element's index. If it isn't in the data structure,
// it is added as its own set
int operator()(const K &key) const
int operator()(const K &key)
{
int i = database(key);
// If the lookup caused the database to grow,
// also add a corresponding entry in parents initialized to -1 (no parent)
parents.resize(database.size(), -1);
if (parents.size() < database.size()) {
parents.emplace_back(-1);
}
return i;
}
@ -1388,21 +1401,38 @@ public:
return database[index];
}
// Why this method is correct for concurent ifind() calls:
// Consider the mfp state after the last non-const method call before
// a particular call to ifind(i). In this state, i's parent chain leads
// to some root R. Let S be the set of integers s such that ifind(s) = R
// in this state. Let 'orig_parents' be the value of 'parents' in this state.
//
// Now consider the concurrent calls to ifind(s), s ∈ S, before the next non-const method
// call. Consider the atomic writes performed by various ifind() calls, in any causally
// consistent order. The first atomic write can only set parents[k] to R, because the
// atomic read of parents[p] in the first while loop can only observe the value
// 'orig_parents[p]'. Subsequent writes can also only set parents[k] to R, because the
// parents[p] reads either observe 'orig_parents[p]' or R (and observing R ends the first
// while loop immediately). Thus all parents[p] reads observe either 'orig_parents[p]'
// or R, so ifind() always returns R.
int ifind(int i) const
{
int p = i, k = i;
while (parents[p] != -1)
p = parents[p];
while (true) {
int pp = parents[p].get();
if (pp < 0)
break;
p = pp;
}
// p is now the representative of i
// Now we traverse from i up to the representative again
// and make p the parent of all the nodes along the way.
// This is a side effect and doesn't affect the return value.
// It speeds up future find operations
while (k != p) {
int next_k = parents[k];
parents[k] = p;
int next_k = parents[k].get();
const_cast<AtomicParent*>(&parents[k])->set(p);
k = next_k;
}
@ -1417,7 +1447,7 @@ public:
j = ifind(j);
if (i != j)
parents[i] = j;
parents[i].set(j);
}
void ipromote(int i)
@ -1425,15 +1455,15 @@ public:
int k = i;
while (k != -1) {
int next_k = parents[k];
parents[k] = i;
int next_k = parents[k].get();
parents[k].set(i);
k = next_k;
}
parents[i] = -1;
parents[i].set(-1);
}
int lookup(const K &a) const
int lookup(const K &a)
{
return ifind((*this)(a));
}

View File

@ -384,6 +384,13 @@ std::string escape_filename_spaces(const std::string& filename)
return out;
}
void append_globbed(std::vector<std::string>& paths, std::string pattern)
{
rewrite_filename(pattern);
std::vector<std::string> globbed = glob_filename(pattern);
copy(globbed.begin(), globbed.end(), back_inserter(paths));
}
void format_emit_unescaped(std::string &result, std::string_view fmt)
{
result.reserve(result.size() + fmt.size());

View File

@ -469,6 +469,7 @@ bool is_absolute_path(std::string filename);
void remove_directory(std::string dirname);
bool create_directory(const std::string& dirname);
std::string escape_filename_spaces(const std::string& filename);
void append_globbed(std::vector<std::string>& paths, std::string pattern);
YOSYS_NAMESPACE_END

View File

@ -266,10 +266,10 @@ std::string& Const::get_str() {
return *get_if_str();
}
RTLIL::Const::Const(const std::string &str)
RTLIL::Const::Const(std::string str)
{
flags = RTLIL::CONST_FLAG_STRING;
new ((void*)&str_) std::string(str);
new ((void*)&str_) std::string(std::move(str));
tag = backing_tag::string;
}
@ -1093,7 +1093,7 @@ RTLIL::Design::Design()
refcount_modules_ = 0;
push_full_selection();
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Design::get_all_designs()->insert(std::pair<unsigned int, RTLIL::Design*>(hashidx_, this));
#endif
}
@ -1104,12 +1104,12 @@ RTLIL::Design::~Design()
delete pr.second;
for (auto n : bindings_)
delete n;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Design::get_all_designs()->erase(hashidx_);
#endif
}
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Design*> all_designs;
std::map<unsigned int, RTLIL::Design*> *RTLIL::Design::get_all_designs(void)
{
@ -1446,7 +1446,7 @@ RTLIL::Module::Module()
refcount_wires_ = 0;
refcount_cells_ = 0;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Module::get_all_modules()->insert(std::pair<unsigned int, RTLIL::Module*>(hashidx_, this));
#endif
}
@ -1463,12 +1463,12 @@ RTLIL::Module::~Module()
delete pr.second;
for (auto binding : bindings_)
delete binding;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Module::get_all_modules()->erase(hashidx_);
#endif
}
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Module*> all_modules;
std::map<unsigned int, RTLIL::Module*> *RTLIL::Module::get_all_modules(void)
{
@ -3082,7 +3082,7 @@ void RTLIL::Module::fixup_ports()
RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, int width)
{
RTLIL::Wire *wire = new RTLIL::Wire;
wire->name = name;
wire->name = std::move(name);
wire->width = width;
add(wire);
return wire;
@ -3090,7 +3090,7 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, int width)
RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *other)
{
RTLIL::Wire *wire = addWire(name);
RTLIL::Wire *wire = addWire(std::move(name));
wire->width = other->width;
wire->start_offset = other->start_offset;
wire->port_id = other->port_id;
@ -3105,7 +3105,7 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *oth
RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type)
{
RTLIL::Cell *cell = new RTLIL::Cell;
cell->name = name;
cell->name = std::move(name);
cell->type = type;
add(cell);
return cell;
@ -3113,17 +3113,25 @@ RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, RTLIL::IdString type)
RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, const RTLIL::Cell *other)
{
RTLIL::Cell *cell = addCell(name, other->type);
RTLIL::Cell *cell = addCell(std::move(name), other->type);
cell->connections_ = other->connections_;
cell->parameters = other->parameters;
cell->attributes = other->attributes;
return cell;
}
RTLIL::Memory *RTLIL::Module::addMemory(RTLIL::IdString name)
{
RTLIL::Memory *mem = new RTLIL::Memory;
mem->name = std::move(name);
memories[mem->name] = mem;
return mem;
}
RTLIL::Memory *RTLIL::Module::addMemory(RTLIL::IdString name, const RTLIL::Memory *other)
{
RTLIL::Memory *mem = new RTLIL::Memory;
mem->name = name;
mem->name = std::move(name);
mem->width = other->width;
mem->start_offset = other->start_offset;
mem->size = other->size;
@ -3135,7 +3143,7 @@ RTLIL::Memory *RTLIL::Module::addMemory(RTLIL::IdString name, const RTLIL::Memor
RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name)
{
RTLIL::Process *proc = new RTLIL::Process;
proc->name = name;
proc->name = std::move(name);
add(proc);
return proc;
}
@ -3143,7 +3151,7 @@ RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name)
RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name, const RTLIL::Process *other)
{
RTLIL::Process *proc = other->clone();
proc->name = name;
proc->name = std::move(name);
add(proc);
return proc;
}
@ -4162,19 +4170,19 @@ RTLIL::Wire::Wire()
upto = false;
is_signed = false;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Wire::get_all_wires()->insert(std::pair<unsigned int, RTLIL::Wire*>(hashidx_, this));
#endif
}
RTLIL::Wire::~Wire()
{
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Wire::get_all_wires()->erase(hashidx_);
#endif
}
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Wire*> all_wires;
std::map<unsigned int, RTLIL::Wire*> *RTLIL::Wire::get_all_wires(void)
{
@ -4191,7 +4199,7 @@ RTLIL::Memory::Memory()
width = 1;
start_offset = 0;
size = 0;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Memory::get_all_memorys()->insert(std::pair<unsigned int, RTLIL::Memory*>(hashidx_, this));
#endif
}
@ -4212,19 +4220,19 @@ RTLIL::Cell::Cell() : module(nullptr)
// log("#memtrace# %p\n", this);
memhasher();
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Cell::get_all_cells()->insert(std::pair<unsigned int, RTLIL::Cell*>(hashidx_, this));
#endif
}
RTLIL::Cell::~Cell()
{
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Cell::get_all_cells()->erase(hashidx_);
#endif
}
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Cell*> all_cells;
std::map<unsigned int, RTLIL::Cell*> *RTLIL::Cell::get_all_cells(void)
{
@ -6026,7 +6034,7 @@ RTLIL::Process *RTLIL::Process::clone() const
return new_proc;
}
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
RTLIL::Memory::~Memory()
{
RTLIL::Memory::get_all_memorys()->erase(hashidx_);

View File

@ -209,10 +209,15 @@ struct RTLIL::IdString
}
static int get_reference(const char *p)
{
return get_reference(std::string_view(p));
}
static int get_reference(std::string_view p)
{
log_assert(destruct_guard_ok);
auto it = global_id_index_.find((char*)p);
auto it = global_id_index_.find(p);
if (it != global_id_index_.end()) {
#ifndef YOSYS_NO_IDS_REFCNT
global_refcount_storage_.at(it->second)++;
@ -226,14 +231,13 @@ struct RTLIL::IdString
ensure_prepopulated();
if (!p[0])
if (p.empty())
return 0;
log_assert(p[0] == '$' || p[0] == '\\');
log_assert(p[1] != 0);
for (const char *c = p; *c; c++)
if ((unsigned)*c <= (unsigned)' ')
log_error("Found control character or space (0x%02x) in string '%s' which is not allowed in RTLIL identifiers\n", *c, p);
for (char ch : p)
if ((unsigned)ch <= (unsigned)' ')
log_error("Found control character or space (0x%02x) in string '%s' which is not allowed in RTLIL identifiers\n", ch, std::string(p).c_str());
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) {
@ -245,8 +249,11 @@ struct RTLIL::IdString
int idx = global_free_idx_list_.back();
global_free_idx_list_.pop_back();
global_id_storage_.at(idx) = strdup(p);
global_id_index_[global_id_storage_.at(idx)] = idx;
char* buf = static_cast<char*>(malloc(p.size() + 1));
memcpy(buf, p.data(), p.size());
buf[p.size()] = 0;
global_id_storage_.at(idx) = buf;
global_id_index_.insert(it, {std::string_view(buf, p.size()), idx});
global_refcount_storage_.at(idx)++;
#else
int idx = global_id_storage_.size();
@ -255,7 +262,7 @@ struct RTLIL::IdString
#endif
if (yosys_xtrace) {
log("#X# New IdString '%s' with index %d.\n", p, idx);
log("#X# New IdString '%s' with index %d.\n", global_id_storage_.at(idx), idx);
log_backtrace("-X- ", yosys_xtrace-1);
}
@ -322,7 +329,8 @@ struct RTLIL::IdString
inline IdString(const char *str) : index_(get_reference(str)) { }
inline IdString(const IdString &str) : index_(get_reference(str.index_)) { }
inline IdString(IdString &&str) : index_(str.index_) { str.index_ = 0; }
inline IdString(const std::string &str) : index_(get_reference(str.c_str())) { }
inline IdString(const std::string &str) : index_(get_reference(std::string_view(str))) { }
inline IdString(std::string_view str) : index_(get_reference(str)) { }
inline IdString(StaticId id) : index_(static_cast<short>(id)) {}
inline ~IdString() { put_reference(index_); }
@ -331,6 +339,12 @@ struct RTLIL::IdString
index_ = get_reference(rhs.index_);
}
inline void operator=(IdString &&rhs) {
put_reference(index_);
index_ = rhs.index_;
rhs.index_ = 0;
}
inline void operator=(const char *rhs) {
IdString id(rhs);
*this = id;
@ -866,9 +880,9 @@ private:
public:
Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector<RTLIL::State>()) {}
Const(const std::string &str);
Const(long long int val); // default width is 32
Const(long long int val, int width);
Const(std::string str);
Const(long long val); // default width is 32
Const(long long val, int width);
Const(RTLIL::State bit, int width = 1);
Const(std::vector<RTLIL::State> bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::move(bits)) {}
Const(const std::vector<bool> &bits);
@ -1347,7 +1361,7 @@ public:
inline bool is_bit() const { return width_ == 1; }
bool known_driver() const;
bool is_mostly_const() const;
bool is_fully_const() const;
bool is_fully_zero() const;
@ -1693,7 +1707,7 @@ struct RTLIL::Design
// SILIMATE ADDED TO IMPROVE PYOSYS API
void run_pass(std::string command);
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Design*> *get_all_designs(void);
#endif
};
@ -1826,6 +1840,7 @@ public:
RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type);
RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other);
RTLIL::Memory *addMemory(RTLIL::IdString name);
RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other);
RTLIL::Process *addProcess(RTLIL::IdString name);
@ -2056,7 +2071,7 @@ public:
std::string rtlil_dump();
unsigned int rtlil_hash();
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Module*> *get_all_modules(void);
#endif
};
@ -2109,7 +2124,7 @@ public:
return zero_index + start_offset;
}
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void);
#endif
};
@ -2126,7 +2141,7 @@ struct RTLIL::Memory : public RTLIL::NamedObject
Memory();
int width, start_offset, size;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
~Memory();
static std::map<unsigned int, RTLIL::Memory*> *get_all_memorys(void);
#endif
@ -2184,7 +2199,7 @@ public:
template<typename T> void rewrite_sigspecs(T &functor);
template<typename T> void rewrite_sigspecs2(T &functor);
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
static std::map<unsigned int, RTLIL::Cell*> *get_all_cells(void);
#endif

View File

@ -39,6 +39,12 @@
# include <dlfcn.h>
#endif
#ifdef YOSYS_ENABLE_PYTHON
# include <Python.h>
# include <pybind11/pybind11.h>
namespace py = pybind11;
#endif
#if defined(_WIN32)
# include <windows.h>
# include <io.h>
@ -65,14 +71,9 @@
# include <sys/sysctl.h>
#endif
#ifdef WITH_PYTHON
#if PY_MAJOR_VERSION >= 3
# define INIT_MODULE PyInit_libyosys
extern "C" PyObject* INIT_MODULE();
#else
# define INIT_MODULE initlibyosys
extern "C" void INIT_MODULE();
#endif
#ifdef YOSYS_ENABLE_PYTHON
extern "C" PyObject* PyInit_libyosys();
extern "C" PyObject* PyInit_pyosys();
#include <signal.h>
#endif
@ -191,6 +192,25 @@ int run_command(const std::string &command, std::function<void(const std::string
bool already_setup = false;
bool already_shutdown = false;
#ifdef YOSYS_ENABLE_PYTHON
// Include pyosys as a package for some compatibility with wheels.
//
// This should not affect using wheels as the dylib has to actually be called
// pyosys.so for this function to be interacted with at all.
PYBIND11_MODULE(pyosys, m) {
m.add_object("__path__", py::list());
}
// Catch uses of 'import libyosys' which can import libyosys.so, causing a ton
// of symbol collisions and overall weird behavior.
//
// This should not affect using wheels as the dylib has to actually be called
// libyosys_dummy.so for this function to be interacted with at all.
PYBIND11_MODULE(libyosys_dummy, _) {
throw py::import_error("Change your import from 'import libyosys' to 'from pyosys import libyosys'.");
}
#endif
void yosys_setup()
{
if(already_setup)
@ -201,12 +221,16 @@ void yosys_setup()
IdString::ensure_prepopulated();
#ifdef WITH_PYTHON
// With Python 3.12, calling PyImport_AppendInittab on an already
#ifdef YOSYS_ENABLE_PYTHON
// Starting Python 3.12, calling PyImport_AppendInittab on an already
// initialized platform fails (such as when libyosys is imported
// from a Python interpreter)
if (!Py_IsInitialized()) {
PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
PyImport_AppendInittab((char*)"pyosys.libyosys", PyInit_libyosys);
// compatibility with wheels
PyImport_AppendInittab((char*)"pyosys", PyInit_pyosys);
// prevent catastrophes
PyImport_AppendInittab((char*)"libyosys", PyInit_libyosys_dummy);
Py_Initialize();
PyRun_SimpleString("import sys");
}
@ -263,13 +287,13 @@ void yosys_shutdown()
dlclose(it.second);
loaded_plugins.clear();
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
loaded_python_plugins.clear();
#endif
loaded_plugin_aliases.clear();
#endif
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
Py_Finalize();
#endif
}
@ -545,7 +569,7 @@ void init_share_dirname()
#else
void init_share_dirname()
{
# ifdef WITH_PYTHON
# ifdef YOSYS_ENABLE_PYTHON
PyObject *sys_obj = PyImport_ImportModule("sys");
if (PyObject_HasAttrString(sys_obj, "_pyosys_share_dirname")) {
@ -605,7 +629,7 @@ void init_abc_executable_name()
yosys_abc_executable = proc_self_dirname() + "..\\" + proc_program_prefix() + "yosys-abc";
# endif
# ifdef WITH_PYTHON
# ifdef YOSYS_ENABLE_PYTHON
PyObject *sys_obj = PyImport_ImportModule("sys");
if (PyObject_HasAttrString(sys_obj, "_pyosys_abc")) {

View File

@ -51,7 +51,7 @@ YOSYS_NAMESPACE_BEGIN
void yosys_setup();
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
bool yosys_already_setup();
#endif
@ -89,7 +89,7 @@ extern std::vector<RTLIL::Design*> pushed_designs;
// from passes/cmds/pluginc.cc
extern std::map<std::string, void*> loaded_plugins;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
extern std::map<std::string, void*> loaded_python_plugins;
#endif
extern std::map<std::string, std::string> loaded_plugin_aliases;

View File

@ -21,6 +21,7 @@
#define YOSYS_COMMON_H
#include <array>
#include <atomic>
#include <map>
#include <set>
#include <tuple>
@ -53,10 +54,6 @@
#include <sys/stat.h>
#include <errno.h>
#ifdef WITH_PYTHON
#include <Python.h>
#endif
#ifndef _YOSYS_
# error It looks like you are trying to build Yosys without the config defines set. \
When building Yosys with a custom make system, make sure you set all the \

File diff suppressed because it is too large Load Diff

View File

@ -57,3 +57,4 @@ OBJS += passes/cmds/abstract.o
OBJS += passes/cmds/test_select.o
OBJS += passes/cmds/timeest.o
OBJS += passes/cmds/linecoverage.o
OBJS += passes/cmds/sort.o

View File

@ -51,6 +51,9 @@ struct BoxDerivePass : Pass {
log(" replaces the internal Yosys naming scheme in which the names of derived\n");
log(" modules start with '$paramod$')\n");
log("\n");
log(" -apply_derived_type\n");
log(" use the derived modules\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *d) override
{
@ -59,11 +62,14 @@ struct BoxDerivePass : Pass {
size_t argidx;
IdString naming_attr;
IdString base_name;
bool apply_mode = false;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-naming_attr" && argidx + 1 < args.size())
naming_attr = RTLIL::escape_id(args[++argidx]);
else if (args[argidx] == "-base" && argidx + 1 < args.size())
base_name = RTLIL::escape_id(args[++argidx]);
else if (args[argidx] == "-apply_derived_type")
apply_mode = true;
else
break;
}
@ -90,24 +96,29 @@ struct BoxDerivePass : Pass {
auto index = std::make_pair(base->name, cell->parameters);
if (cell->parameters.empty() || done.count(index))
if (cell->parameters.empty())
continue;
IdString derived_type = base->derive(d, cell->parameters);
Module *derived = d->module(derived_type);
log_assert(derived && "Failed to derive module\n");
log_debug("derived %s\n", derived_type);
if (!done.count(index)) {
IdString derived_type = base->derive(d, cell->parameters);
Module *derived = d->module(derived_type);
log_assert(derived && "Failed to derive module\n");
log("derived %s\n", derived_type);
if (!naming_attr.empty() && derived->has_attribute(naming_attr)) {
IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr));
if (!new_name.isPublic())
log_error("Derived module %s cannot be renamed to private name %s.\n",
log_id(derived), log_id(new_name));
derived->attributes.erase(naming_attr);
d->rename(derived, new_name);
if (!naming_attr.empty() && derived->has_attribute(naming_attr)) {
IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr));
if (!new_name.isPublic())
log_error("Derived module %s cannot be renamed to private name %s.\n",
log_id(derived), log_id(new_name));
derived->attributes.erase(naming_attr);
d->rename(derived, new_name);
}
done[index] = derived;
}
done[index] = derived;
if (apply_mode)
cell->type = done[index]->name;
}
}
}

View File

@ -22,6 +22,27 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static void publish(RTLIL::IdString& id) {
if (id.begins_with("$")) {
log_debug("publishing %s\n", id.c_str());
id = "\\" + id.str();
log_debug("published %s\n", id.c_str());
}
}
static void publish_design(RTLIL::Design* design) {
auto saved_modules = design->modules_;
design->modules_.clear();
for (auto& [name, mod] : saved_modules) {
publish(mod->name);
design->modules_[mod->name] = mod;
for (auto* cell : mod->cells()) {
publish(cell->type);
}
}
}
struct ChtypePass : public Pass {
ChtypePass() : Pass("chtype", "change type of cells in the design") { }
void help() override
@ -38,12 +59,16 @@ struct ChtypePass : public Pass {
log(" -map <old_type> <new_type>\n");
log(" change cells types that match <old_type> to <new_type>\n");
log("\n");
log(" -publish_icells\n");
log(" change internal cells types to public types\n");
log("\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
IdString set_type;
dict<IdString, IdString> map_types;
bool publish_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@ -58,10 +83,17 @@ struct ChtypePass : public Pass {
map_types[old_type] = new_type;
continue;
}
if (args[argidx] == "-publish_icells") {
publish_mode = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if (publish_mode)
publish_design(design);
for (auto module : design->selected_modules())
{
for (auto cell : module->selected_cells())

View File

@ -22,23 +22,45 @@
#ifdef YOSYS_ENABLE_PLUGINS
# include <dlfcn.h>
# include <filesystem>
namespace fs = std::filesystem;
#endif
#ifdef WITH_PYTHON
# include <boost/algorithm/string/predicate.hpp>
#ifdef YOSYS_ENABLE_PYTHON
# include <Python.h>
# include <boost/filesystem.hpp>
# include <pybind11/pybind11.h>
namespace py = pybind11;
#endif
YOSYS_NAMESPACE_BEGIN
std::map<std::string, void*> loaded_plugins;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
std::map<std::string, void*> loaded_python_plugins;
#endif
std::map<std::string, std::string> loaded_plugin_aliases;
#ifdef YOSYS_ENABLE_PLUGINS
static constexpr const char *path_delimiters = fs::path::preferred_separator == '\\' ? ";" : ":" ;
inline const std::vector<fs::path> get_plugin_search_paths() {
std::vector<fs::path> result;
const char *yosys_plugin_path = std::getenv("YOSYS_PLUGIN_PATH");
if (yosys_plugin_path != nullptr && strlen(yosys_plugin_path)) {
// make mutable. std::string also manages allocation as a bonus
// guaranteed contiguous in c++>=11
std::string copy{yosys_plugin_path};
char *token = nullptr;
char *rest = &copy[0];
while ((token = strtok_r(rest, path_delimiters, &rest))) {
result.push_back(fs::path(token));
}
}
result.push_back(fs::path(proc_share_dirname()) / "plugins"); // lowest priority
return result;
}
void load_plugin(std::string filename, std::vector<std::string> aliases)
{
std::string orig_filename = filename;
@ -49,31 +71,31 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
filename = "./" + filename;
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
const bool is_loaded = loaded_plugins.count(orig_filename) && loaded_python_plugins.count(orig_filename);
#else
const bool is_loaded = loaded_plugins.count(orig_filename);
#endif
fs::path full_path = fs::absolute(filename);
if (!is_loaded) {
// Check if we're loading a python script
if(filename.find(".py") != std::string::npos)
{
#ifdef WITH_PYTHON
boost::filesystem::path full_path(filename);
std::string path(full_path.parent_path().c_str());
filename = full_path.filename().c_str();
filename = filename.substr(0,filename.size()-3);
PyRun_SimpleString(("sys.path.insert(0,\""+path+"\")").c_str());
PyErr_Print();
PyObject *module_p = PyImport_ImportModule(filename.c_str());
if(module_p == NULL)
{
PyErr_Print();
log_cmd_error("Can't load python module `%s'\n", full_path.filename());
if (full_path.extension() == ".py") {
#ifdef YOSYS_ENABLE_PYTHON
fs::path plugin_python_path = full_path.parent_path();
fs::path basename = full_path.stem();
py::object sys = py::module_::import("sys");
sys.attr("path").attr("insert")(0, py::str(plugin_python_path.c_str()));
try {
auto module_container = py::module_::import(basename.c_str());
loaded_python_plugins[orig_filename] = module_container.ptr();
} catch (py::error_already_set &e) {
log_cmd_error("Can't load python module `%s': %s\n", basename, e.what());
return;
}
loaded_python_plugins[orig_filename] = module_p;
Pass::init_register();
#else
log_error(
@ -83,23 +105,25 @@ void load_plugin(std::string filename, std::vector<std::string> aliases)
#endif
} else {
// Otherwise we assume it's a native plugin
void *hdl = dlopen(filename.c_str(), RTLD_LAZY|RTLD_LOCAL);
// We were unable to open the file, try to do so from the plugin directory
if (hdl == NULL && orig_filename.find('/') == std::string::npos) {
hdl = dlopen([orig_filename]() {
std::string new_path = proc_share_dirname() + "plugins/" + orig_filename;
// Check if we need to append .so
if (new_path.find(".so") == std::string::npos)
new_path.append(".so");
return new_path;
}().c_str(), RTLD_LAZY|RTLD_LOCAL);
// We were unable to open the file, try to do so from plugin search
// paths
if (hdl == nullptr && orig_filename.find('/') == std::string::npos) {
const std::vector<fs::path> search_paths = get_plugin_search_paths();
for (const auto &search_path: search_paths) {
fs::path potential_path = search_path / orig_filename;
if (potential_path.extension() != ".so") {
potential_path = search_path / (orig_filename + ".so");
}
hdl = dlopen(potential_path.string().c_str(), RTLD_LAZY | RTLD_LOCAL);
if (hdl != nullptr) {
break;
}
}
}
if (hdl == NULL)
if (hdl == nullptr)
log_cmd_error("Can't load module `%s': %s\n", filename, dlerror());
loaded_plugins[orig_filename] = hdl;
@ -116,7 +140,7 @@ void load_plugin(std::string, std::vector<std::string>)
log_error(
"\n This version of Yosys cannot load plugins at runtime.\n"
" Some plugins may have been included at build time.\n"
" Use option `-H' to see the available built-in and plugin commands.\n"
" Use `yosys -H' to see the available built-in and plugin commands.\n"
);
}
#endif
@ -177,7 +201,7 @@ struct PluginPass : public Pass {
if (list_mode)
{
log("\n");
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
if (loaded_plugins.empty() and loaded_python_plugins.empty())
#else
if (loaded_plugins.empty())
@ -189,7 +213,7 @@ struct PluginPass : public Pass {
for (auto &it : loaded_plugins)
log(" %s\n", it.first);
#ifdef WITH_PYTHON
#ifdef YOSYS_ENABLE_PYTHON
for (auto &it : loaded_python_plugins)
log(" %s\n", it.first);
#endif

View File

@ -125,7 +125,7 @@ struct PortarcsPass : Pass {
for (auto cell : m->cells())
// Ignore all bufnorm helper cells
if (!cell->type.in(ID($buf), ID($input_port), ID($connect))) {
if (!cell->type.in(ID($buf), ID($input_port), ID($connect), ID($tribuf))) {
auto tdata = tinfo.find(cell->type);
if (tdata == tinfo.end())
log_cmd_error("Missing timing data for module '%s'.\n", log_id(cell->type));

26
passes/cmds/sort.cc Normal file
View File

@ -0,0 +1,26 @@
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SortPass : Pass {
SortPass() : Pass("sort", "sort the design objects") {}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" sort\n");
log("\n");
log("Sorts the design objects.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *d) override
{
log_header(d, "Executing SORT pass.\n");
if (args.size() != 1)
log_cmd_error("This pass takes no arguments.\n");
d->sort();
}
} SortPass;
PRIVATE_NAMESPACE_END

View File

@ -1394,7 +1394,7 @@ struct SimWorker : SimShared
}
}
void run(Module *topmod, int numcycles)
void run(Module *topmod, int cycle_width, int numcycles)
{
log_assert(top == nullptr);
top = new SimInstance(this, scope, topmod);
@ -1420,20 +1420,20 @@ struct SimWorker : SimShared
for (int cycle = 0; cycle < numcycles; cycle++)
{
if (debug)
log("\n===== %d =====\n", 10*cycle + 5);
log("\n===== %d =====\n", int(cycle_width*cycle + cycle_width/2));
else if (verbose)
log("Simulating cycle %d.\n", (cycle*2)+1);
set_inports(clock, State::S0);
set_inports(clockn, State::S1);
update(true);
register_output_step(10*cycle + 5);
register_output_step(cycle_width*cycle + cycle_width/2);
if (cycle == 0)
top->set_initstate_outputs(State::S0);
if (debug)
log("\n===== %d =====\n", 10*cycle + 10);
log("\n===== %d =====\n", int(cycle_width*cycle + cycle_width));
else if (verbose)
log("Simulating cycle %d.\n", (cycle*2)+2);
@ -1446,10 +1446,10 @@ struct SimWorker : SimShared
}
update(true);
register_output_step(10*cycle + 10);
register_output_step(cycle_width*cycle + cycle_width);
}
register_output_step(10*numcycles + 2);
register_output_step(cycle_width*numcycles + 2);
write_output_files();
}
@ -1584,7 +1584,7 @@ struct SimWorker : SimShared
return atoi(name.substr(pos+1).c_str());
}
void run_cosim_aiger_witness(Module *topmod)
void run_cosim_aiger_witness(Module *topmod, int cycle_width)
{
log_assert(top == nullptr);
if (!multiclock && (clock.size()+clockn.size())==0)
@ -1693,18 +1693,18 @@ struct SimWorker : SimShared
set_inports(clockn, State::S1);
}
update(true);
register_output_step(10*cycle);
register_output_step(cycle_width*cycle);
if (!multiclock && cycle) {
set_inports(clock, State::S0);
set_inports(clockn, State::S1);
update(true);
register_output_step(10*cycle + 5);
register_output_step(cycle_width*cycle + cycle_width/2);
}
cycle++;
break;
}
}
register_output_step(10*cycle);
register_output_step(cycle_width*cycle);
write_output_files();
}
@ -1732,7 +1732,7 @@ struct SimWorker : SimShared
return name.substr(0, pos);
}
void run_cosim_btor2_witness(Module *topmod)
void run_cosim_btor2_witness(Module *topmod, int cycle_width)
{
log_assert(top == nullptr);
if (!multiclock && (clock.size()+clockn.size())==0)
@ -1770,12 +1770,12 @@ struct SimWorker : SimShared
set_inports(clock, State::S1);
set_inports(clockn, State::S0);
update(true);
register_output_step(10*cycle+0);
register_output_step(cycle_width*cycle + 0);
if (!multiclock) {
set_inports(clock, State::S0);
set_inports(clockn, State::S1);
update(true);
register_output_step(10*cycle+5);
register_output_step(cycle_width*cycle + cycle_width/2);
}
cycle++;
prev_cycle = curr_cycle;
@ -1834,7 +1834,7 @@ struct SimWorker : SimShared
break;
}
}
register_output_step(10*cycle);
register_output_step(cycle_width*cycle);
write_output_files();
}
@ -1985,7 +1985,7 @@ struct SimWorker : SimShared
}
}
void run_cosim_yw_witness(Module *topmod, int append)
void run_cosim_yw_witness(Module *topmod, int cycle_width, int append)
{
if (!clock.empty())
log_cmd_error("The -clock option is not required nor supported when reading a Yosys witness file.\n");
@ -2015,7 +2015,7 @@ struct SimWorker : SimShared
log("Simulating non-active clock edge.\n");
set_yw_clocks(yw, hierarchy, false);
update(false);
register_output_step(5);
register_output_step(cycle_width/2);
}
top->set_initstate_outputs(State::S0);
}
@ -2028,18 +2028,18 @@ struct SimWorker : SimShared
set_yw_state(yw, hierarchy, cycle);
set_yw_clocks(yw, hierarchy, true);
update(true);
register_output_step(10 * cycle);
register_output_step(cycle_width*cycle);
if (!yw.clocks.empty()) {
if (debug)
log("Simulating non-active clock edge.\n");
set_yw_clocks(yw, hierarchy, false);
update(false);
register_output_step(5 + 10 * cycle);
register_output_step(cycle_width*cycle + cycle_width/2);
}
}
register_output_step(10 * (GetSize(yw.steps) + append));
register_output_step(cycle_width * (GetSize(yw.steps) + append));
write_output_files();
}
@ -2858,6 +2858,9 @@ struct SimPass : public Pass {
log(" File formats supported: FST, VCD, AIW, WIT and .yw\n");
log(" VCD support requires vcd2fst external tool to be present\n");
log("\n");
log(" -width <integer>\n");
log(" cycle width in generated simulation output (must be divisible by 2).\n");
log("\n");
log(" -append <integer>\n");
log(" number of extra clock cycles to simulate for a Yosys witness input\n");
log("\n");
@ -2917,6 +2920,7 @@ struct SimPass : public Pass {
{
SimWorker worker;
int numcycles = 20;
int cycle_width = 10;
int append = 0;
bool start_set = false, stop_set = false, at_set = false;
@ -3009,6 +3013,12 @@ struct SimPass : public Pass {
append = atoi(args[++argidx].c_str());
continue;
}
if (args[argidx] == "-width" && argidx+1 < args.size()) {
cycle_width = atoi(args[++argidx].c_str());
if (cycle_width <= 0 || (cycle_width % 2))
log_cmd_error("Cycle width must be positive even number.\n");
continue;
}
if (args[argidx] == "-map" && argidx+1 < args.size()) {
std::string map_filename = args[++argidx];
rewrite_filename(map_filename);
@ -3104,7 +3114,7 @@ struct SimPass : public Pass {
}
if (worker.sim_filename.empty())
worker.run(top_mod, numcycles);
worker.run(top_mod, cycle_width, numcycles);
else {
std::string filename_trim = file_base_name(worker.sim_filename);
if (filename_trim.size() > 4 && ((filename_trim.compare(filename_trim.size()-4, std::string::npos, ".fst") == 0) ||
@ -3113,11 +3123,11 @@ struct SimPass : public Pass {
} else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".aiw") == 0) {
if (worker.map_filename.empty())
log_cmd_error("For AIGER witness file map parameter is mandatory.\n");
worker.run_cosim_aiger_witness(top_mod);
worker.run_cosim_aiger_witness(top_mod, cycle_width);
} else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".wit") == 0) {
worker.run_cosim_btor2_witness(top_mod);
worker.run_cosim_btor2_witness(top_mod, cycle_width);
} else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".yw") == 0) {
worker.run_cosim_yw_witness(top_mod, append);
worker.run_cosim_yw_witness(top_mod, cycle_width, append);
} else {
log_cmd_error("Unhandled extension for simulation input file `%s`.\n", worker.sim_filename);
}

View File

@ -38,8 +38,8 @@ struct Abc9Pass : public ScriptPass
Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
void on_register() override
{
RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -v; &mfs";
RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f; &ps; &if {C} {W} {D} {R} -a -v; &mfs";
RTLIL::constpad["abc9.script.default"] = "+&scorr; &sweep; &dc2; &dch -f -r; &ps; &if {C} {W} {D} {R} -v; &mfs";
RTLIL::constpad["abc9.script.default.area"] = "+&scorr; &sweep; &dc2; &dch -f -r; &ps; &if {C} {W} {D} {R} -a -v; &mfs";
RTLIL::constpad["abc9.script.default.fast"] = "+&if {C} {W} {D} {R} -v";
// Based on ABC's &flow
RTLIL::constpad["abc9.script.flow"] = "+&scorr; &sweep;" \

View File

@ -1605,6 +1605,7 @@ static void replace_zbufs(Design *design)
mod->bufNormalize();
}
design->bufNormalize(false);
}
@ -1624,7 +1625,6 @@ static void restore_zbufs(Design *design)
mod->addBuf(NEW_ID, Const(State::Sz, GetSize(sig_y)), sig_y);
mod->remove(cell);
}
mod->bufNormalize();
}
}

View File

@ -141,7 +141,11 @@ struct AbcNewPass : public ScriptPass {
selected_modules = order_modules(active_design,
active_design->selected_whole_modules_warn());
active_design->push_empty_selection();
} else {
}
run("abc9_ops -replace_zbufs");
if (help_mode) {
selected_modules = {nullptr};
run("foreach module in selection");
}
@ -169,13 +173,10 @@ struct AbcNewPass : public ScriptPass {
}
run(stringf(" abc9_ops -write_box %s/input.box", tmpdir));
run(" abc9_ops -replace_zbufs");
run(stringf(" write_xaiger2 -mapping_prep -map2 %s/input.map2 %s/input.xaig", tmpdir, tmpdir));
run(stringf(" abc9_exe %s -cwd %s -box %s/input.box", exe_options, tmpdir, tmpdir));
run(stringf(" read_xaiger2 -sc_mapping -module_name %s -map2 %s/input.map2 %s/output.aig",
modname.c_str(), tmpdir.c_str(), tmpdir.c_str()));
run(" abc9_ops -restore_zbufs");
if (!help_mode && mod->has_attribute(ID(abc9_script))) {
if (script_save.empty())
active_design->scratchpad_unset("abc9.script");
@ -196,6 +197,8 @@ struct AbcNewPass : public ScriptPass {
}
}
run("abc9_ops -restore_zbufs");
if (!help_mode) {
active_design->pop_selection();
}

View File

@ -40,34 +40,51 @@ struct AlumaccWorker
{
std::vector<RTLIL::Cell*> cells;
RTLIL::SigSpec a, b, c, y;
std::vector<tuple<bool, bool, bool, bool, RTLIL::SigSpec>> cmp;
std::vector<tuple<bool, bool, bool, bool, bool, RTLIL::SigSpec>> cmp;
bool is_signed, invert_b;
RTLIL::Cell *alu_cell;
RTLIL::SigSpec cached_lt, cached_gt, cached_eq, cached_ne;
RTLIL::SigSpec cached_lt, cached_slt, cached_gt, cached_sgt, cached_eq, cached_ne;
RTLIL::SigSpec cached_cf, cached_of, cached_sf;
RTLIL::SigSpec get_lt() {
if (GetSize(cached_lt) == 0) {
if (is_signed) {
RTLIL::SigSpec get_lt(bool is_signed) {
if (is_signed) {
if (GetSize(cached_slt) == 0) {
get_of();
get_sf();
cached_lt = alu_cell->module->Xor(NEW_ID, cached_of, cached_sf);
cached_slt = alu_cell->module->Xor(NEW_ID, cached_of, cached_sf);
}
else
return cached_slt;
} else {
if (GetSize(cached_lt) == 0) {
cached_lt = get_cf();
}
return cached_lt;
}
return cached_lt;
}
RTLIL::SigSpec get_gt() {
if (GetSize(cached_gt) == 0) {
get_lt();
get_eq();
SigSpec Or = alu_cell->module->Or(NEW_ID, cached_lt, cached_eq);
cached_gt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->get_src_attribute());
RTLIL::SigSpec get_gt(bool is_signed) {
if (is_signed) {
if (GetSize(cached_sgt) == 0) {
get_lt(is_signed);
get_eq();
SigSpec Or = alu_cell->module->Or(NEW_ID, cached_slt, cached_eq);
cached_sgt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->get_src_attribute());
}
return cached_sgt;
} else {
if (GetSize(cached_gt) == 0) {
get_lt(is_signed);
get_eq();
SigSpec Or = alu_cell->module->Or(NEW_ID, cached_lt, cached_eq);
cached_gt = alu_cell->module->Not(NEW_ID, Or, false, alu_cell->get_src_attribute());
}
return cached_gt;
}
return cached_gt;
}
RTLIL::SigSpec get_eq() {
@ -409,7 +426,7 @@ struct AlumaccWorker
alunode_t *n = nullptr;
for (auto node : sig_alu[RTLIL::SigSig(A, B)])
if (node->is_signed == is_signed && node->invert_b && node->c == State::S1) {
if (node->invert_b && node->c == State::S1) {
n = node;
break;
}
@ -439,7 +456,7 @@ struct AlumaccWorker
}
n->cells.push_back(cell);
n->cmp.push_back(std::make_tuple(cmp_less, !cmp_less, cmp_equal, false, Y));
n->cmp.push_back(std::make_tuple(cmp_less, !cmp_less, cmp_equal, false, is_signed, Y));
}
for (auto cell : eq_cells)
@ -454,7 +471,7 @@ struct AlumaccWorker
alunode_t *n = nullptr;
for (auto node : sig_alu[RTLIL::SigSig(A, B)])
if (node->is_signed == is_signed && node->invert_b && node->c == State::S1) {
if (node->invert_b && node->c == State::S1) {
n = node;
break;
}
@ -470,7 +487,7 @@ struct AlumaccWorker
if (n != nullptr) {
log(" creating $alu model for %s (%s): merged with %s.\n", log_id(cell), log_id(cell->type), log_id(n->cells.front()));
n->cells.push_back(cell);
n->cmp.push_back(std::make_tuple(false, false, cmp_equal, !cmp_equal, Y));
n->cmp.push_back(std::make_tuple(false, false, cmp_equal, !cmp_equal, false, Y));
}
}
}
@ -525,11 +542,12 @@ struct AlumaccWorker
bool cmp_gt = std::get<1>(it);
bool cmp_eq = std::get<2>(it);
bool cmp_ne = std::get<3>(it);
RTLIL::SigSpec cmp_y = std::get<4>(it);
bool is_signed = std::get<4>(it);
RTLIL::SigSpec cmp_y = std::get<5>(it);
RTLIL::SigSpec sig;
if (cmp_lt) sig.append(n->get_lt());
if (cmp_gt) sig.append(n->get_gt());
if (cmp_lt) sig.append(n->get_lt(is_signed));
if (cmp_gt) sig.append(n->get_gt(is_signed));
if (cmp_eq) sig.append(n->get_eq());
if (cmp_ne) sig.append(n->get_ne());

View File

@ -290,9 +290,7 @@ struct ClockgatePass : public Pass {
continue;
}
if (args[argidx] == "-liberty" && argidx+1 < args.size()) {
std::string liberty_file = args[++argidx];
rewrite_filename(liberty_file);
liberty_files.push_back(liberty_file);
append_globbed(liberty_files, args[++argidx]);
continue;
}
if (args[argidx] == "-dont_use" && argidx+1 < args.size()) {

View File

@ -609,9 +609,7 @@ struct DfflibmapPass : public Pass {
{
std::string arg = args[argidx];
if (arg == "-liberty" && argidx+1 < args.size()) {
std::string liberty_file = args[++argidx];
rewrite_filename(liberty_file);
liberty_files.push_back(liberty_file);
append_globbed(liberty_files, args[++argidx]);
continue;
}
if (arg == "-prepare") {

View File

@ -96,9 +96,7 @@
quiet = true;
continue;
}
std::string fname = args[argidx];
rewrite_filename(fname);
paths.push_back(fname);
append_globbed(paths, args[argidx]);
break;
}
int modes = enable + disable + purge + list + verbose + quiet;

2
pyosys/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
wrappers.cc
wrappers.inc.cc

831
pyosys/generator.py Normal file
View File

@ -0,0 +1,831 @@
#!/usr/bin/env python3
# yosys -- Yosys Open SYnthesis Suite
#
# Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# Written by Mohamed Gaber <me@donn.website>
#
# Inspired by py_wrap_generator.py by Benedikt Tutzer
"""
This generates:
- Wrapper calls for opaque container types
- Full wrappers for select classes and all enums, global functions and global
variables
Jump to "MARK: Inclusion and Exclusion" to control the above.
Please run ruff on this file in particular to make sure it parses with Python
<= 3.12. There is so much f-string use here that the outer quote thing
is a common problem. ``ruff check pyosys/generator.py`` suffices.
"""
import os
import io
import shutil
import argparse
from pathlib import Path
from sysconfig import get_paths
from dataclasses import dataclass, field
from typing import Any, Dict, FrozenSet, Iterable, Tuple, Union, Optional, List
import pybind11
from cxxheaderparser.simple import parse_file, ClassScope, NamespaceScope, EnumDecl
from cxxheaderparser.options import ParserOptions
from cxxheaderparser.preprocessor import make_gcc_preprocessor
from cxxheaderparser.types import (
PQName,
Type,
Pointer,
Reference,
MoveReference,
AnonymousName,
Method,
Function,
Field,
Variable,
Array,
FundamentalSpecifier,
FunctionType,
)
__file_dir__ = Path(__file__).absolute().parent
__yosys_root__ = __file_dir__.parent
@dataclass
class PyosysClass:
"""
Metadata about classes or structs intended to be wrapped using Pyosys.
:param name: The base name of the class (without extra qualifiers)
:param ref_only: Whether this class can be copied to Python, or only
referenced.
:param string_expr:
A C++ expression that will be used for the ``__str__`` method in Python.
The object will be available as a const reference with the identifier
`s`.
:param hash_expr:
A C++ expression that will be fed to ``run_hash`` to declare a
``__hash__`` method for Python.
The object will be vailable as a const reference with the identifier
`s`.
:param denylist: If specified, one or more methods can be excluded from
wrapping.
"""
name: str
ref_only: bool = False
# in the format s.(method or property) (or just s)
string_expr: Optional[str] = None
hash_expr: Optional[str] = None
denylist: FrozenSet[str] = frozenset({})
@dataclass
class PyosysHeader:
"""
:param name: The name of the header, i.e., its relative path to the Yosys root
:param classes: A list of ``PyosysClass`` classes to be wrapped
:param enums: A list of enums to be wrapped
"""
name: str
classes: List[PyosysClass] = field(default_factory=lambda: [])
def __post_init__(self):
self.classes_by_name = {}
if classes := self.classes:
for cls in classes:
self.classes_by_name[cls.name] = cls
# MARK: Inclusion and Exclusion
global_denylist = frozenset(
{
# deprecated
"builtin_ff_cell_types",
"logv_file_error",
# no implementation
"set_verific_logging",
# can't bridge to python cleanly
## std::regex
"log_warn_regexes",
"log_nowarn_regexes",
"log_werror_regexes",
## function pointers
"log_error_atexit",
"log_verific_callback",
}
)
pyosys_headers = [
# Headers for incomplete types
PyosysHeader("kernel/binding.h"),
PyosysHeader("libs/sha1/sha1.h"),
# Headers for globals
PyosysHeader("kernel/log.h"),
PyosysHeader("kernel/yosys.h"),
PyosysHeader("kernel/cost.h"),
# Headers with classes
PyosysHeader(
"kernel/celltypes.h",
[PyosysClass("CellType", hash_expr="s.type"), PyosysClass("CellTypes")],
),
PyosysHeader("kernel/consteval.h", [PyosysClass("ConstEval")]),
PyosysHeader(
"kernel/register.h",
[
# PyosysClass("Pass") # Virtual methods, manually bridged
],
),
PyosysHeader(
"kernel/rtlil.h",
[
PyosysClass(
"IdString",
string_expr="s.str()",
hash_expr="s.str()",
denylist=frozenset(
# shouldn't be messed with from python in general
{
"global_id_storage_",
"global_id_index_",
"global_refcount_storage_",
"global_free_idx_list_",
"last_created_idx_ptr_",
"last_created_idx_",
"builtin_ff_cell_types",
}
),
),
PyosysClass(
"Const",
string_expr="s.as_string()",
denylist=frozenset({"bits", "bitvectorize"}),
),
PyosysClass("AttrObject", denylist=frozenset({"get_blackbox_attribute"})),
PyosysClass("NamedObject"),
PyosysClass("Selection"),
# PyosysClass("Monitor"), # Virtual methods, manually bridged
PyosysClass("CaseRule"),
PyosysClass("SwitchRule"),
PyosysClass("SyncRule"),
PyosysClass(
"Process",
ref_only=True,
string_expr="s.name.c_str()",
hash_expr="s.name",
),
PyosysClass("SigChunk"),
PyosysClass("SigBit", hash_expr="s"),
PyosysClass("SigSpec", hash_expr="s"),
PyosysClass(
"Cell",
ref_only=True,
string_expr="s.name.c_str()",
hash_expr="s",
),
PyosysClass(
"Wire",
ref_only=True,
string_expr="s.name.c_str()",
hash_expr="s",
),
PyosysClass(
"Memory",
ref_only=True,
string_expr="s.name.c_str()",
hash_expr="s",
),
PyosysClass(
"Module",
ref_only=True,
string_expr="s.name.c_str()",
hash_expr="s",
denylist=frozenset({"Pow"}), # has no implementation
),
PyosysClass(
"Design",
string_expr="std::to_string(s.hashidx_)",
hash_expr="s",
denylist=frozenset({"selected_whole_modules"}), # deprecated
),
],
),
]
@dataclass(frozen=True) # hashable
class PyosysType:
"""
Bit of a hacky object all-around: this is more or less used to encapsulate
container types so they can be later made opaque using pybind.
"""
base: str
specialization: Tuple["PyosysType", ...]
const: bool = False
@classmethod
def from_type(Self, type_obj, drop_const=False) -> "PyosysType":
const = hasattr(type_obj, "const") and type_obj.const and not drop_const
if isinstance(type_obj, Pointer):
ptr_to = Self.from_type(type_obj.ptr_to)
return Self("ptr", (ptr_to,), const)
elif isinstance(type_obj, Reference):
ref_to = Self.from_type(type_obj.ref_to)
return Self("ref", (ref_to,), const)
elif isinstance(type_obj, FunctionType):
ret_type = Self.from_type(type_obj.return_type)
param_types = (Self.from_type(p.type) for p in type_obj.parameters)
return Self("fn", (ret_type, *param_types), False)
assert isinstance(
type_obj, Type
), f"unexpected c++ type object of type {type(type_obj)}"
last_segment = type_obj.typename.segments[-1]
base = last_segment.name
specialization = tuple()
if (
hasattr(last_segment, "specialization")
and last_segment.specialization is not None
):
for template_arg in last_segment.specialization.args:
specialization = (*specialization, Self.from_type(template_arg.arg))
return Self(base, specialization, const)
def generate_identifier(self):
title = self.base.title()
if len(self.specialization) == 0:
return title
if title == "Dict":
key, value = self.specialization
return f"{key.generate_identifier()}To{value.generate_identifier()}{title}"
elif title == "Fn":
identifier = self.specialization[0].generate_identifier()
if identifier == "Void":
identifier = ""
else:
identifier += "From"
identifier += "And".join(
p.generate_identifier() for p in self.specialization[1:]
)
return identifier
return (
"".join(spec.generate_identifier() for spec in self.specialization) + title
)
def generate_cpp_name(self):
const_prefix = "const " * self.const
if len(self.specialization) == 0:
return const_prefix + self.base
elif self.base == "ptr":
return const_prefix + f"{self.specialization[0].generate_cpp_name()} *"
elif self.base == "ref":
return const_prefix + f"{self.specialization[0].generate_cpp_name()} &"
elif self.base == "fn":
param_cpp_names = (s.generate_cpp_name() for s in self.specialization[1:])
return f"{self.specialization[0].generate_cpp_name()}({','.join(param_cpp_names)})"
else:
return (
const_prefix
+ f"{self.base}<{', '.join(spec.generate_cpp_name() for spec in self.specialization)}>"
)
class PyosysWrapperGenerator(object):
def __init__(
self,
from_headers: Iterable[PyosysHeader],
wrapper_stream: io.TextIOWrapper,
header_stream: io.TextIOWrapper,
):
self.headers = from_headers
self.f = wrapper_stream
self.f_inc = header_stream
self.found_containers: Dict[PyosysType, Any] = {}
self.class_registry: Dict[str, Tuple[ClassScope, PyosysClass]] = {}
# entry point
def generate(self):
tpl = __file_dir__ / "wrappers_tpl.cc"
preprocessor_opts = self.make_preprocessor_options()
with open(tpl, encoding="utf8") as f:
do_line_directive = True
for i, line in enumerate(f):
if do_line_directive:
self.f.write(f'#line {i + 1} "{tpl}"\n')
do_line_directive = False
if "<!-- generated includes -->" in line:
for header in self.headers:
self.f.write(f'#include "{header.name}"\n')
do_line_directive = True
elif "<!-- generated pymod-level code -->" in line:
for header in self.headers:
header_path = __yosys_root__ / header.name
parsed = parse_file(header_path, options=preprocessor_opts)
global_namespace = parsed.namespace
self.process_namespace(header, global_namespace)
else:
self.f.write(line)
for container, _ in self.found_containers.items():
identifier = container.generate_identifier()
print(
f"using {identifier} = {container.generate_cpp_name()};",
file=self.f_inc,
)
print(f"PYBIND11_MAKE_OPAQUE({identifier})", file=self.f_inc)
print(
f"static void bind_autogenerated_opaque_containers(py::module &m) {{",
file=self.f_inc,
)
for container, _ in self.found_containers.items():
identifier = container.generate_identifier()
cxx = container.generate_cpp_name()
tpl_args = [cxx]
for spec in container.specialization:
tpl_args.append(spec.generate_cpp_name())
print(
f'\tpy::hashlib::bind_{container.base}<{", ".join(tpl_args)}>(m, "{container.generate_identifier()}");',
file=self.f_inc,
)
print(
f"\tpy::implicitly_convertible<py::iterable, {identifier}>();",
file=self.f_inc,
)
print(f"}}", file=self.f_inc)
# helpers
def make_preprocessor_options(self):
py_include = get_paths()["include"]
preprocessor_bin = shutil.which("clang++") or "g++"
cxx_std = os.getenv("CXX_STD", "c++17")
return ParserOptions(
preprocessor=make_gcc_preprocessor(
defines=["_YOSYS_", "YOSYS_ENABLE_PYTHON"],
gcc_args=[preprocessor_bin, "-fsyntax-only", f"-std={cxx_std}"],
include_paths=[str(__yosys_root__), py_include, pybind11.get_include()],
),
)
@staticmethod
def find_containers(
containers: Iterable[str], type_info: Any
) -> Dict[PyosysType, Any]:
if isinstance(type_info, Pointer):
return PyosysWrapperGenerator.find_containers(containers, type_info.ptr_to)
if isinstance(type_info, MoveReference):
return PyosysWrapperGenerator.find_containers(
containers, type_info.moveref_to
)
if isinstance(type_info, Reference):
return PyosysWrapperGenerator.find_containers(containers, type_info.ref_to)
if not isinstance(type_info, Type):
return {}
segments = type_info.typename.segments
containers_found = {}
for segment in segments:
if isinstance(segment, FundamentalSpecifier):
continue
if segment.name in containers:
containers_found.update(
{PyosysType.from_type(type_info, drop_const=True): type_info}
)
if segment.specialization is not None:
for arg in segment.specialization.args:
sub_containers = PyosysWrapperGenerator.find_containers(
containers, arg.arg
)
containers_found.update(sub_containers)
return containers_found
@staticmethod
def find_anonymous_union(cls: ClassScope):
if cls.class_decl.typename.classkey != "union":
return None
for s in cls.class_decl.typename.segments:
if isinstance(s, AnonymousName):
return s
return None # named union
@staticmethod
def get_parameter_types(function: Function) -> str:
return ", ".join(p.type.format() for p in function.parameters)
def register_containers(self, target: Union[Function, Field, Variable]) -> bool:
supported = ("dict", "idict", "pool", "set", "vector")
found = False
if isinstance(target, Function):
return_type_containers = self.find_containers(supported, target.return_type)
found = found or len(return_type_containers)
self.found_containers.update(return_type_containers)
for parameter in target.parameters:
parameter_containers = self.find_containers(supported, parameter.type)
found = found or len(parameter_containers)
self.found_containers.update(parameter_containers)
else:
variable_containers = self.find_containers(supported, target.type)
found = found or len(variable_containers)
self.found_containers.update(variable_containers)
return found
# processors
def get_overload_cast(
self, function: Function, class_basename: Optional[str]
) -> str:
is_method = isinstance(function, Method)
function_return_type = function.return_type.format()
if class_basename == "Const" and function_return_type in {
"iterator",
"const_iterator",
}:
# HACK: qualify Const's iterators
function_return_type = f"{class_basename}::{function_return_type}"
pointer_kind = (
f"{class_basename}::*" if (is_method and not function.static) else "*"
)
retval = f"static_cast <"
retval += function_return_type
retval += f"({pointer_kind})"
retval += f"({self.get_parameter_types(function)})"
if is_method and function.const:
retval += " const"
retval += ">"
retval += "(&"
if is_method:
retval += f"{class_basename}::"
retval += function.name.segments[-1].format()
retval += ")"
return retval
def get_definition_args(
self,
function: Function,
class_basename: Optional[str],
python_name_override: Optional[str] = None,
) -> List[str]:
function_basename = function.name.segments[-1].format()
python_function_basename = python_name_override or keyword_aliases.get(
function_basename, function_basename
)
def_args = [f'"{python_function_basename}"']
def_args.append(self.get_overload_cast(function, class_basename))
for i, parameter in enumerate(function.parameters):
name = parameter.name or f"arg{i}"
parameter_arg = f'py::arg("{name}")'
if parameter.default is not None:
parameter_arg += f" = {parameter.default.format()}"
def_args.append(parameter_arg)
return def_args
def process_method(self, metadata: PyosysClass, function: Method):
if (
function.deleted
or function.template
or function.vararg
or function.access != "public"
or function.pure_virtual
or function.destructor
):
return
if any(isinstance(p.type, MoveReference) for p in function.parameters):
# skip move constructors
return
if len(function.name.segments) > 1:
# can't handle, skip
return
if function.constructor:
if (
not metadata.ref_only
): # ref-only classes should not be constructed from python
print(
f"\t\t\t.def(py::init<{self.get_parameter_types(function)}>())",
file=self.f,
)
return
python_name_override = None
if function.operator is not None:
if function.operator == "==":
python_name_override = "__eq__"
elif function.operator == "!=":
python_name_override = "__ne__"
elif function.operator == "<":
python_name_override = "__lt__"
else:
return
self.register_containers(function)
definition_fn = "def"
if function.static:
definition_fn = "def_static"
definition_args = self.get_definition_args(
function, metadata.name, python_name_override
)
print(
f"\t\t\t.{definition_fn}({', '.join(definition_args)})",
file=self.f,
)
def process_function(self, function: Function):
if function.deleted or function.template or function.vararg or function.static:
return
if function.operator is not None:
# Python doesn't do global operators
return
if function.name.segments[-1].format() in global_denylist:
return
self.register_containers(function)
print(
f"\t\t\tm.def({', '.join(self.get_definition_args(function, None))});",
file=self.f,
)
def process_field(self, metadata: PyosysClass, field: Field):
if field.access != "public":
return
if field.name is None:
# anonymous structs and unions
# unions handled in calling function
# ASSUMPTION: No anonymous structs in the yosys codebase
# (they're not in the C++ standard anyway)
return
unique_ptrs = self.find_containers(("unique_ptr",), field.type)
if len(unique_ptrs):
# TODO: figure out how to bridge unique pointers maybe does anyone
# care
return
has_containers = self.register_containers(field)
definition_fn = f"def_{'readonly' if field.type.const else 'readwrite'}"
if field.static:
definition_fn += "_static"
field_python_basename = keyword_aliases.get(field.name, field.name)
def_args = [
f'"{field_python_basename}"',
f"&{metadata.name}::{field.name}",
]
def_args.append("py::return_value_policy::copy")
print(
f"\t\t\t.{definition_fn}({', '.join(def_args)})",
file=self.f,
)
def process_variable(self, variable: Variable):
if isinstance(variable.type, Array):
return
variable_basename = variable.name.segments[-1].format()
if variable_basename in global_denylist:
return
self.register_containers(variable)
definition_fn = (
f"def_{'readonly' if variable.type.const else 'readwrite'}_static"
)
variable_python_basename = keyword_aliases.get(
variable_basename, variable_basename
)
variable_name = variable.name.format()
print(
f'\t\t\tglobal_variables.{definition_fn}("{variable_python_basename}", &{variable_name});',
file=self.f,
)
def process_class_members(
self,
metadata: PyosysClass,
base_metadata: PyosysClass,
cls: ClassScope,
basename: str,
):
for method in cls.methods:
if method.name.segments[-1].name in base_metadata.denylist:
continue
self.process_method(metadata, method)
visited_anonymous_unions = set()
for field_ in cls.fields:
if field_.name in base_metadata.denylist:
continue
self.process_field(metadata, field_)
# Handle anonymous unions
for subclass in cls.classes:
if subclass.class_decl.access != "public":
continue
if au := self.find_anonymous_union(subclass):
if au.id in visited_anonymous_unions:
continue
visited_anonymous_unions.add(au.id)
for subfield in subclass.fields:
self.process_field(metadata, subfield)
for base in cls.class_decl.bases:
if base.access != "public":
continue
name = base.typename.segments[-1].format()
if processed := self.class_registry.get(name):
base_scope, base_metadata = processed
self.process_class_members(
metadata, base_metadata, base_scope, basename
)
def process_class(
self,
metadata: PyosysClass,
cls: ClassScope,
namespace_components: Tuple[str, ...],
):
pqname: PQName = cls.class_decl.typename
full_path = list(namespace_components) + [
segment.format() for segment in pqname.segments
]
basename = full_path.pop()
self.class_registry[basename] = (cls, metadata)
declaration_namespace = "::".join(full_path)
tpl_args = [basename]
if metadata.ref_only:
tpl_args.append(f"std::unique_ptr<{basename}, py::nodelete>")
print(
f'\t\t{{using namespace {declaration_namespace}; py::class_<{", ".join(tpl_args)}>(m, "{basename}")',
file=self.f,
)
self.process_class_members(metadata, metadata, cls, basename)
if expr := metadata.string_expr:
print(
f'\t\t.def("__str__", [](const {basename} &s) {{ return {expr}; }})',
file=self.f,
)
print(
f'\t\t.def("__repr__", [](const {basename} &s) {{ std::stringstream ss; ss << "<{basename} " << {expr} << ">"; return ss.str(); }})',
file=self.f,
)
if expr := metadata.hash_expr:
print(
f'\t\t.def("__hash__", [](const {basename} &s) {{ return run_hash({expr}); }})',
file=self.f,
)
print(f"\t\t;}}", file=self.f)
def process_enum(
self,
enum: EnumDecl,
namespace_components: Tuple[str, ...],
):
pqname: PQName = enum.typename
full_path = list(namespace_components) + [
segment.format() for segment in pqname.segments
]
basename = full_path.pop()
declaration_namespace = "::".join(full_path)
print(
f'\t\t{{using namespace {declaration_namespace}; py::native_enum<{basename}>(m, "{basename}", "enum.Enum")',
file=self.f,
)
enum_class = enum.typename.classkey == "enum class"
for value in enum.values:
enum_class_qualifier = f"{basename}::" * enum_class
print(
f'\t\t\t.value("{value.name}", {enum_class_qualifier}{value.name})',
file=self.f,
)
print(f"\t\t\t.finalize();}}", file=self.f)
def process_namespace(
self,
header: PyosysHeader,
ns: NamespaceScope,
namespace_components: Tuple[str, ...] = (),
):
for name, subns in ns.namespaces.items():
self.process_namespace(header, subns, (*namespace_components, name))
if len(namespace_components) and (len(ns.functions) + len(ns.variables)):
# TODO: Not essential but maybe move namespace usage into
# process_function for consistency?
print(
f"\t\t{{ using namespace {'::'.join(namespace_components)};",
file=self.f,
)
for function in ns.functions:
self.process_function(function)
for variable in ns.variables:
self.process_variable(variable)
print(f"\t\t}}", file=self.f)
for enum in ns.enums:
self.process_enum(enum, namespace_components)
for cls in ns.classes:
pqname = cls.class_decl.typename
declared_name_str = pqname.segments[-1].format()
if cls_metadata := header.classes_by_name.get(declared_name_str):
self.process_class(cls_metadata, cls, namespace_components)
keyword_aliases = {
"False": "False_",
"None": "None_",
"True": "True_",
"and": "and_",
"as": "as_",
"assert": "assert_",
"break": "break_",
"class": "class_",
"continue": "continue_",
"def": "def_",
"del": "del_",
"elif": "elif_",
"else": "else_",
"except": "except_",
"for": "for_",
"from": "from_",
"global": "global_",
"if": "if_",
"import": "import_",
"in": "in_",
"is": "is_",
"lambda": "lambda_",
"nonlocal": "nonlocal_",
"not": "not_",
"or": "or_",
"pass": "pass_",
"raise": "raise_",
"return": "return_",
"try": "try_",
"while": "while_",
"with": "with_",
"yield": "yield_",
}
def print_includes():
for header in pyosys_headers:
print(header.name)
if __name__ == "__main__":
ap = argparse.ArgumentParser()
ap.add_argument("--debug", default=0, type=int)
group = ap.add_mutually_exclusive_group(required=True)
group.add_argument("--print-includes", action="store_true")
group.add_argument("output", nargs="?")
ns = ap.parse_args()
if ns.print_includes:
print_includes()
exit(0)
out_path = Path(ns.output)
out_inc = out_path.parent / (out_path.stem + ".inc.cc")
with open(out_path, "w", encoding="utf8") as f, open(
out_inc, "w", encoding="utf8"
) as inc_f:
generator = PyosysWrapperGenerator(
from_headers=pyosys_headers, wrapper_stream=f, header_stream=inc_f
)
generator.generate()

529
pyosys/hashlib.h Normal file
View File

@ -0,0 +1,529 @@
// -------------------------------------------------------
// Written by Mohamed Gaber in 2025 <me@donn.website>
// Based on kernel/hashlib.h by Claire Xenia Wolf <claire@yosyshq.com>
// -------------------------------------------------------
// This header is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <https://unlicense.org/>
// -------------------------------------------------------
//
// pybind11 bridging headers for hashlib template
//
// These are various binding functions that expose hashlib templates as opaque
// types (https://pybind11.readthedocs.io/en/latest/advanced/cast/stl.html#making-opaque-types).
//
// Opaque types cross language barries by reference, not value. This allows
// things like mutating containers that are class properties.
//
// All methods should be vaguely in the same order as the python reference
// https://docs.python.org/3.13/library/stdtypes.html
//
#include <optional> // optional maps cleanest to methods that accept None in Python
#include <pybind11/stl.h> // std::optional
#include <pybind11/pybind11.h> // base
#include <pybind11/operators.h> // easier operator binding
#include <pybind11/stl_bind.h> // vector
#include "kernel/hashlib.h"
namespace pybind11 {
namespace hashlib {
// "traits"
template <typename T> struct is_pointer: std::false_type {};
template <typename T> struct is_pointer<T*>: std::true_type {};
template <typename T> struct is_optional: std::false_type {};
template <typename T> struct is_optional< std::optional<T> >: std::true_type {};
bool is_mapping(object obj) {
object mapping = module_::import("collections.abc").attr("Mapping");
return isinstance(obj, mapping);
}
// Set Operations
bool is_subset(const iterable &lhs, const iterable &rhs, bool strict = false) {
for (auto &element: lhs) {
if (!rhs.contains(element)) {
return false;
}
}
if (strict) {
return len(rhs) > len(lhs);
}
return true;
}
template <typename C, typename T>
void unionize(C &lhs, const iterable &rhs) {
for (auto &element: rhs) {
lhs.insert(cast<T>(element));
}
}
template <typename C, typename T>
void difference(C &lhs, const iterable &rhs) {
for (auto &element: rhs) {
auto element_cxx = cast<T>(element);
if (lhs.count(element_cxx)) {
lhs.erase(element_cxx);
}
}
}
template <typename C, typename T>
void intersect(C &lhs, const iterable &rhs) {
// Doing it in-place is a lot slower
// TODO?: Leave modifying lhs to caller (saves a copy in some cases)
// but complicates chaining intersections.
C storage(lhs);
for (auto &element_cxx: lhs) {
if (!rhs.contains(cast(element_cxx))) {
storage.erase(element_cxx);
}
}
lhs = std::move(storage);
}
template <typename C, typename T>
void symmetric_difference(C &lhs, const iterable &rhs) {
C storage(lhs);
for (auto &element: rhs) {
auto element_cxx = cast<T>(element);
if (lhs.count(element_cxx)) {
storage.erase(element_cxx);
} else {
storage.insert(element_cxx);
}
}
for (auto &element_cxx: lhs) {
if (rhs.contains(cast(element_cxx))) {
storage.erase(element_cxx);
}
}
lhs = std::move(storage);
}
// shim
template <typename C, typename V>
void bind_vector(module &m, const char *name_cstr) {
pybind11::bind_vector<C>(m, name_cstr);
}
// also used for hashlib pool because the semantics are close enough
template <typename C, typename T>
void bind_set(module &m, const char *name_cstr) {
class_<C>(m, name_cstr)
.def(init<>())
.def(init<const C &>()) // copy constructor
.def(init([](const iterable &other){ // copy instructor from arbitrary iterables
auto s = new C();
unionize<C, T>(*s, other);
return s;
}))
.def("__len__", [](const C &s){ return (size_t)s.size(); })
.def("__contains__", [](const C &s, const T &v){ return s.count(v); })
.def("__delitem__", [](C &s, const T &v) {
auto n = s.erase(v);
if (n == 0) throw key_error(str(cast(v)));
})
.def("disjoint", [](const C &s, const iterable &other) {
for (const auto &element: other) {
if (s.count(cast<T>(element))) {
return false;
}
}
return true;
})
.def("issubset", [](const iterable &s, const iterable &other) {
return is_subset(s, other);
})
.def("__eq__", [](const iterable &s, const iterable &other) {
return is_subset(s, other) && len(s) == len(other);
})
.def("__le__", [](const iterable &s, const iterable &other) {
return is_subset(s, other);
})
.def("__lt__", [](const iterable &s, const iterable &other) {
return is_subset(s, other, true);
})
.def("issuperset", [](const iterable &s, const iterable &other) {
return is_subset(other, s);
})
.def("__ge__", [](const iterable &s, const iterable &other) {
return is_subset(other, s);
})
.def("__gt__", [](const iterable &s, const iterable &other) {
return is_subset(other, s, true);
})
.def("union", [](const C &s, const args &others) {
auto result = new C(s);
for (const auto &arg: others) {
auto arg_iterable = reinterpret_borrow<iterable>(arg);
unionize<C, T>(*result, arg_iterable);
}
return result;
})
.def("__or__", [](const C &s, const iterable &other) {
auto result = new C(s);
unionize<C, T>(*result, other);
return result;
})
.def("__ior__", [](C &s, const iterable &other) {
unionize<C, T>(s, other);
return s;
})
.def("intersection", [](const C &s, const args &others) {
auto result = new C(s);
for (const auto &arg: others) {
auto arg_iterable = reinterpret_borrow<iterable>(arg);
intersect<C, T>(*result, arg_iterable);
}
return result;
})
.def("__and__", [](const C &s, const iterable &other) {
auto result = new C(s);
intersect<C, T>(*result, other);
return result;
})
.def("__iand__", [](C &s, const iterable &other) {
intersect<C, T>(s, other);
return s;
})
.def("difference", [](const C &s, const args &others) {
auto result = new C(s);
for (const auto &arg: others) {
auto arg_iterable = reinterpret_borrow<iterable>(arg);
difference<C, T>(*result, arg_iterable);
}
return result;
})
.def("__sub__", [](const C &s, const iterable &other) {
auto result = new C(s);
difference<C, T>(*result, other);
return result;
})
.def("__isub__", [](C &s, const iterable &other) {
difference<C, T>(s, other);
return s;
})
.def("symmetric_difference", [](const C &s, const iterable &other) {
auto result = new C(s);
symmetric_difference<C, T>(*result, other);
return result;
})
.def("__xor__", [](const C &s, const iterable &other) {
auto result = new C(s);
symmetric_difference<C, T>(*result, other);
return result;
})
.def("__ixor__", [](C &s, const iterable &other) {
symmetric_difference<C, T>(s, other);
return s;
})
.def("copy", [](const C &s) {
return new C(s);
})
.def("update", [](C &s, iterable iterable) {
for (auto item: iterable) {
s.insert(item.cast<T>());
}
})
.def("add", [](C &s, const T &v){ s.insert(v); })
.def("remove", [](C &s, const T &v){
auto n = s.erase(v);
if (n == 0) throw key_error(str(cast(v)));
})
.def("discard", [](C &s, const T &v){ s.erase(v); })
.def("clear", [](C &s){ s.clear(); })
.def("pop", [](C &s){
if (s.size() == 0) {
throw key_error("empty pool");
}
auto result = *s.begin();
s.erase(result);
return result;
})
.def("__bool__", [](const C &s) { return s.size() != 0; })
.def("__iter__", [](const C &s){
return make_iterator(s.begin(), s.end());
}, keep_alive<0,1>())
.def("__eq__", [](const C &s, const C &other) { return s == other; })
.def("__eq__", [](const C &s, const iterable &other) {
C other_cast;
unionize<C, T>(other_cast, other);
return s == other_cast;
})
.def("__repr__", [name_cstr](const iterable &s){
// repr(set(s)) where s is iterable would be more terse/robust
// but are there concerns with copying?
str representation = str(name_cstr) + str("({");
str comma(", ");
for (const auto &element: s) {
representation += repr(element);
representation += comma; // python supports trailing commas
}
representation += str("})");
return representation;
});
}
// shim
template <typename C, typename T>
void bind_pool(module &m, const char *name_cstr) {
bind_set<C, T>(m, name_cstr);
}
template <typename C, typename K, typename V>
void update_dict(C &target, const iterable &iterable_or_mapping) {
if (is_mapping(iterable_or_mapping)) {
for (const auto &key: iterable_or_mapping) {
target[cast<K>(key)] = cast<V>(iterable_or_mapping[key]);
}
} else {
for (const auto &pair: iterable_or_mapping) {
if (len(pair) != 2) {
throw value_error(str("iterable element %s has more than two elements").format(str(pair)));
}
target[cast<K>(pair[cast(0)])] = cast<V>(pair[cast(1)]);
}
}
}
template <typename C, typename K, typename V>
void bind_dict(module &m, const char *name_cstr) {
auto cls = class_<C>(m, name_cstr)
.def(init<>())
.def(init<const C &>()) // copy constructor
.def(init([](const iterable &other){ // copy instructor from arbitrary iterables and mappings
auto s = new C();
update_dict<C, K, V>(*s, other);
return s;
}))
.def("__len__", [](const C &s){ return (size_t)s.size(); })
.def("__getitem__", [](const C &s, const K &k) { return s.at(k); })
.def("__setitem__", [](C &s, const K &k, const V &v) { s[k] = v; })
.def("__delitem__", [](C &s, const K &k) {
auto n = s.erase(k);
if (n == 0) throw key_error("remove: key not found");
})
.def("__contains__", [](const C &s, const K &k) { return s.count(k) != 0; })
.def("__iter__", [](const C &s){
return make_key_iterator(s.begin(), s.end());
}, keep_alive<0,1>())
.def("clear", [](C &s){ s.clear(); })
.def("copy", [](const C &s) {
return new C(s);
})
.def("get", [](const C &s, const K& k, std::optional<const V> &default_) {
if (default_.has_value()) {
return s.at(k, *default_);
} else {
return s.at(k);
}
}, arg("key"), arg("default") = std::nullopt)
.def("items", [](const C &s){
return make_iterator(s.begin(), s.end());
}, keep_alive<0,1>())
.def("keys", [](const C &s){
return make_key_iterator(s.begin(), s.end());
}, keep_alive<0,1>())
.def("pop", [](const C &s, const K& k, std::optional<const V> &default_) {
if (default_.has_value()) {
return s.at(k, *default_);
} else {
return s.at(k);
}
}, arg("key"), arg("default") = std::nullopt)
.def("popitem", [](C &s) {
auto it = s.begin();
if (it == s.end()) {
throw key_error("dict is empty");
}
auto copy = *it;
s.erase(it);
return copy;
})
.def("setdefault", [name_cstr](C &s, const K& k, std::optional<const V> &default_) {
auto it = s.find(k);
if (it != s.end()) {
return it->second;
}
if (default_.has_value()) {
s[k] = *default_;
return *default_;
}
// if pointer, nullptr can be our default
if constexpr (is_pointer<V>::value) {
s[k] = nullptr;
return (V)nullptr;
}
if constexpr (is_optional<V>::value) {
s[k] = std::nullopt;
return std::nullopt;
}
throw type_error(std::string("the value type of ") + name_cstr + " is not nullable");
}, arg("key"), arg("default") = std::nullopt)
.def("update", [](C &s, iterable iterable_or_mapping) {
update_dict<C, K, V>(s, iterable_or_mapping);
}, arg("iterable_or_mapping"))
.def("values", [](const C &s){
return make_value_iterator(s.begin(), s.end());
}, keep_alive<0,1>())
.def("__or__", [](const C &s, iterable iterable_or_mapping) {
auto result = new C(s);
update_dict<C, K, V>(*result, iterable_or_mapping);
return result;
})
.def("__ior__", [](C &s, iterable iterable_or_mapping) {
update_dict<C, K, V>(s, iterable_or_mapping);
return s;
})
.def("__bool__", [](const C &s) { return s.size() != 0; })
.def("__repr__", [name_cstr](const C &s) {
// repr(dict(s)) where s is iterable would be more terse/robust
// but are there concerns with copying?
str representation = str(name_cstr) + str("({");
str colon(": ");
str comma(", ");
for (const auto &item: s) {
representation += repr(cast(item.first));
representation += colon;
representation += repr(cast(item.second));
representation += comma; // python supports trailing commas
}
representation += str("})");
return representation;
});
// K is always comparable
// Python implements `is` as a fallback to check if it's the same object
if constexpr (detail::is_comparable<V>::value) {
cls.def("__eq__", [](const C &s, const C &other) { return s == other; });
cls.def("__eq__", [](const C &s, const iterable &other) {
C other_cast;
update_dict<C, K, V>(other_cast, other);
return s == other_cast;
});
}
// Inherit from collections.abc.Mapping so update operators (and a bunch
// of other things) work.
auto collections_abc = module_::import("collections.abc");
auto mapping = getattr(collections_abc, "Mapping");
auto current_bases = list(getattr(cls, "__bases__"));
current_bases.append(mapping);
setattr(cls, "__bases__", tuple(current_bases));
}
// idict is a special bijection and doesn't map cleanly to dict
//
// it's cleanest, despite the inconsistency with __getitem__, to just think of
// the hashable as key and the integer as value
template <typename C, typename K>
void bind_idict(module &m, const char *name_cstr) {
auto cls = class_<C>(m, name_cstr)
.def(init<>())
.def(init<const C &>()) // copy constructor
.def(init([](const iterable &other){ // copy instructor from arbitrary iterables
auto s = new C();
for (auto &e: other) {
(*s)(cast<K>(e));
}
return s;
}))
.def("__len__", [](const C &s){ return (size_t)s.size(); })
.def("__getitem__", [](const C &s, int v) { return s[v]; })
.def("__call__", [](C &s, const K &k) { return s(k); })
.def("__contains__", [](const C &s, const K &k) {
return s.count(k) != 0;
})
.def("__iter__", [](const C &s){
return make_iterator(s.begin(), s.end());
}, keep_alive<0,1>())
.def("clear", [](C &s) {
s.clear();
})
.def("copy", [](const C &s) {
return new C(s);
})
.def("get", [](const C &s, const K& k, std::optional<int> &default_) {
if (default_.has_value()) {
return s.at(k, *default_);
} else {
return s.at(k);
}
}, arg("key"), arg("default") = std::nullopt)
.def("keys", [](const C &s){
return make_iterator(s.begin(), s.end());
})
.def("values", [](args _){
throw type_error("idicts do not support iteration on the integers");
})
.def("items", [](args _){
throw type_error("idicts do not support pairwise iteration");
})
.def("update", [](C &s, iterable other) {
for (auto &e: other) {
s(cast<K>(e));
}
})
.def("__or__", [](const C &s, iterable other) {
auto result = new C(s);
for (auto &e: other) {
(*result)(cast<K>(e));
}
return result;
})
.def("__ior__", [](C &s, iterable other) {
for (auto &e: other) {
s(cast<K>(e));
}
return s;
})
.def("__bool__", [](const C &s) { return s.size() != 0; })
.def("__repr__", [name_cstr](const C &s){
// repr(dict(s)) where s is iterable would be more terse/robust
// but are there concerns with copying?
str representation = str(name_cstr) + str("() | {");
str comma(", ");
for (const auto &item: s) {
representation += repr(cast(item));
representation += comma; // python supports trailing commas
}
representation += str("}");
return representation;
});
for (const char *mutator: {"__setitem__", "__delitem__", "pop", "popitem", "setdefault"}) {
cls.def(mutator, [](args _) {
throw type_error("idicts do not support arbitrary element mutation");
});
}
}
}; // namespace hashlib
}; // namespace pybind11

263
pyosys/wrappers_tpl.cc Normal file
View File

@ -0,0 +1,263 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef YOSYS_ENABLE_PYTHON
// <!-- generated includes -->
#include <pybind11/pybind11.h>
#include <pybind11/native_enum.h>
#include <pybind11/functional.h>
// duplicates for LSPs
#include "kernel/register.h"
#include "kernel/yosys_common.h"
#include "pyosys/hashlib.h"
namespace py = pybind11;
USING_YOSYS_NAMESPACE
using std::set;
using std::function;
using std::ostream;
using namespace RTLIL;
#include "wrappers.inc.cc"
namespace pyosys {
struct Globals {};
// Trampolines for Classes with Python-Overridable Virtual Methods
// https://pybind11.readthedocs.io/en/stable/advanced/classes.html#overriding-virtual-functions-in-python
class PassTrampoline : public Pass {
public:
using Pass::Pass;
void help() override {
PYBIND11_OVERRIDE(void, Pass, help);
}
bool formatted_help() override {
PYBIND11_OVERRIDE(bool, Pass, formatted_help);
}
void clear_flags() override {
PYBIND11_OVERRIDE(void, Pass, clear_flags);
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
PYBIND11_OVERRIDE_PURE(
void,
Pass,
execute,
args,
design
);
}
void on_register() override {
PYBIND11_OVERRIDE(void, Pass, on_register);
}
void on_shutdown() override {
PYBIND11_OVERRIDE(void, Pass, on_shutdown);
}
bool replace_existing_pass() const override {
PYBIND11_OVERRIDE(
bool,
Pass,
replace_existing_pass
);
}
};
class MonitorTrampoline : public RTLIL::Monitor {
public:
using RTLIL::Monitor::Monitor;
void notify_module_add(RTLIL::Module *module) override {
PYBIND11_OVERRIDE(
void,
RTLIL::Monitor,
notify_module_add,
module
);
}
void notify_module_del(RTLIL::Module *module) override {
PYBIND11_OVERRIDE(
void,
RTLIL::Monitor,
notify_module_del,
module
);
}
void notify_connect(
RTLIL::Cell *cell,
const RTLIL::IdString &port,
const RTLIL::SigSpec &old_sig,
const RTLIL::SigSpec &sig
) override {
PYBIND11_OVERRIDE(
void,
RTLIL::Monitor,
notify_connect,
cell,
port,
old_sig,
sig
);
}
void notify_connect(
RTLIL::Module *module,
const RTLIL::SigSig &sigsig
) override {
PYBIND11_OVERRIDE(
void,
RTLIL::Monitor,
notify_connect,
module,
sigsig
);
}
void notify_connect(
RTLIL::Module *module,
const std::vector<RTLIL::SigSig> &sigsig_vec
) override {
PYBIND11_OVERRIDE(
void,
RTLIL::Monitor,
notify_connect,
module,
sigsig_vec
);
}
void notify_blackout(
RTLIL::Module *module
) override {
PYBIND11_OVERRIDE(
void,
RTLIL::Monitor,
notify_blackout,
module
);
}
};
PYBIND11_MODULE(libyosys, m) {
// this code is run on import
m.doc() = "python access to libyosys";
if (!yosys_already_setup()) {
log_streams.push_back(&std::cout);
log_error_stderr = true;
yosys_setup();
// Cleanup
m.add_object("_cleanup_handle", py::capsule([](){
yosys_shutdown();
}));
}
// Logging Methods
m.def("log_header", [](Design *d, std::string s) { log_formatted_header(d, "%s", s); });
m.def("log", [](std::string s) { log_formatted_string("%s", s); });
m.def("log_file_info", [](std::string_view file, int line, std::string s) { log_formatted_file_info(file, line, s); });
m.def("log_warning", [](std::string s) { log_formatted_warning("Warning: ", s); });
m.def("log_warning_noprefix", [](std::string s) { log_formatted_warning("", s); });
m.def("log_file_warning", [](std::string_view file, int line, std::string s) { log_formatted_file_warning(file, line, s); });
m.def("log_error", [](std::string s) { log_formatted_error(s); });
m.def("log_file_error", [](std::string_view file, int line, std::string s) { log_formatted_file_error(file, line, s); });
// Namespace to host global objects
auto global_variables = py::class_<Globals>(m, "Globals");
// Trampoline Classes
py::class_<Pass, pyosys::PassTrampoline, std::unique_ptr<Pass, py::nodelete>>(m, "Pass")
.def(py::init([](std::string name, std::string short_help) {
auto created = new pyosys::PassTrampoline(name, short_help);
Pass::init_register();
return created;
}), py::arg("name"), py::arg("short_help"))
.def("help", &Pass::help)
.def("formatted_help", &Pass::formatted_help)
.def("execute", &Pass::execute)
.def("clear_flags", &Pass::clear_flags)
.def("on_register", &Pass::on_register)
.def("on_shutdown", &Pass::on_shutdown)
.def("replace_existing_pass", &Pass::replace_existing_pass)
.def("experimental", &Pass::experimental)
.def("internal", &Pass::internal)
.def("pre_execute", &Pass::pre_execute)
.def("post_execute", &Pass::post_execute)
.def("cmd_log_args", &Pass::cmd_log_args)
.def("cmd_error", &Pass::cmd_error)
.def("extra_args", &Pass::extra_args)
.def("call", py::overload_cast<RTLIL::Design *,std::string>(&Pass::call))
.def("call", py::overload_cast<RTLIL::Design *,std::vector<std::string>>(&Pass::call))
;
py::class_<RTLIL::Monitor, pyosys::MonitorTrampoline>(m, "Monitor")
.def(py::init([]() {
return new pyosys::MonitorTrampoline();
}))
.def("notify_module_add", &RTLIL::Monitor::notify_module_add)
.def("notify_module_del", &RTLIL::Monitor::notify_module_del)
.def(
"notify_connect",
py::overload_cast<
RTLIL::Cell *,
const RTLIL::IdString &,
const RTLIL::SigSpec &,
const RTLIL::SigSpec &
>(&RTLIL::Monitor::notify_connect)
)
.def(
"notify_connect",
py::overload_cast<
RTLIL::Module *,
const RTLIL::SigSig &
>(&RTLIL::Monitor::notify_connect)
)
.def(
"notify_connect",
py::overload_cast<
RTLIL::Module *,
const std::vector<RTLIL::SigSig> &
>(&RTLIL::Monitor::notify_connect)
)
.def("notify_blackout", &RTLIL::Monitor::notify_blackout)
;
// Bind Opaque Containers
bind_autogenerated_opaque_containers(m);
// <!-- generated pymod-level code -->
py::implicitly_convertible<std::string, RTLIL::IdString>();
py::implicitly_convertible<const char *, RTLIL::IdString>();
};
};
#endif // YOSYS_ENABLE_PYTHON

11
pyproject.toml Normal file
View File

@ -0,0 +1,11 @@
[build-system]
requires = [
"setuptools>=42",
"pybind11>=3,<4",
"cxxheaderparser",
]
build-backend = "setuptools.build_meta"
[tool.ruff]
target-version = "py38"
lint.ignore = ["F541"]

View File

@ -16,19 +16,19 @@ import os
import re
import shlex
import shutil
from pathlib import Path
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
__dir__ = os.path.dirname(os.path.abspath(__file__))
import pybind11
from pybind11.setup_helpers import build_ext
yosys_version_rx = re.compile(r"PREQORSOR_VERSION\s*:=\s*([\w\-\+\.]+)")
__yosys_root__ = Path(__file__).parent
try:
version = yosys_version_rx.search(
open(os.path.join(__dir__, "../../Makefile"), encoding="utf8").read()
)[1]
except TypeError:
version = open(os.path.join(__dir__, "../../tmpl/version.txt"), encoding="utf8").read().strip()
yosys_version_rx = re.compile(r"YOSYS_VER\s*:=\s*([\w\-\+\.]+)")
with open(__yosys_root__ / "Makefile", encoding="utf8") as f:
# Extract and convert + to patch version
version = yosys_version_rx.search(f.read())[1].replace("+", ".")
class libyosys_so_ext(Extension):
def __init__(
@ -38,7 +38,13 @@ class libyosys_so_ext(Extension):
"libyosys.so",
[],
)
# when iterating locally, you probably want to set this variable
# to avoid mass rebuilds bec of pybind11's include path changing
pybind_include = os.getenv("_FORCE_PYBIND_INCLUDE", pybind11.get_include())
self.args = [
f"PYBIND11_INCLUDE={pybind_include}",
"ENABLE_PYOSYS=1",
# Would need to be installed separately by the user
"ENABLE_TCL=0",
@ -73,24 +79,25 @@ class libyosys_so_ext(Extension):
*self.args,
]
)
build_path = os.path.dirname(os.path.dirname(bext.get_ext_fullpath(self.name)))
pyosys_path = os.path.join(build_path, "pyosys")
ext_fullpath = Path(bext.get_ext_fullpath(self.name))
build_path = ext_fullpath.parents[1]
pyosys_path = build_path / "pyosys"
os.makedirs(pyosys_path, exist_ok=True)
# libyosys.so
target = os.path.join(pyosys_path, os.path.basename(self.name))
target = pyosys_path / self.name
shutil.copy(self.name, target)
# strip prevents proper debug symbols for libpyosys.so
# bext.spawn(["strip", "-S", target])
# yosys-abc
yosys_abc_target = os.path.join(pyosys_path, "yosys-abc")
yosys_abc_target = pyosys_path / "yosys-abc"
shutil.copy("yosys-abc", yosys_abc_target)
bext.spawn(["strip", "-S", yosys_abc_target])
bext.spawn(["strip", "-S", str(yosys_abc_target)])
# share directory
share_target = os.path.join(pyosys_path, "share")
share_target = pyosys_path / "share"
try:
shutil.rmtree(share_target)
except FileNotFoundError:
@ -106,14 +113,16 @@ class custom_build_ext(build_ext):
return ext.custom_build(self)
with open(__yosys_root__ / "README.md", encoding="utf8") as f:
long_description = f.read()
setup(
name="pyosys",
packages=["pyosys"],
version=version,
version=os.getenv("_PYOSYS_OVERRIDE_VER", version),
description="Python access to libyosys",
long_description=open(os.path.join(__dir__, "README.md")).read(),
long_description=long_description,
long_description_content_type="text/markdown",
install_requires=["wheel", "setuptools"],
license="MIT",
classifiers=[
"Programming Language :: Python :: 3",
@ -121,7 +130,6 @@ setup(
"Operating System :: POSIX :: Linux",
"Operating System :: MacOS :: MacOS X",
],
package_dir={"pyosys": "misc"},
python_requires=">=3.8",
ext_modules=[libyosys_so_ext()],
cmdclass={

View File

@ -1,15 +0,0 @@
OBJS += techlibs/ecp5/synth_ecp5.o
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_ff.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_io.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams.txt))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams.txt))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dsp_map.v))

View File

@ -1,90 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
(* techmap_celltype = "$alu" *)
module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
(* force_downto *)
input [A_WIDTH-1:0] A;
(* force_downto *)
input [B_WIDTH-1:0] B;
(* force_downto *)
output [Y_WIDTH-1:0] X, Y;
input CI, BI;
(* force_downto *)
output [Y_WIDTH-1:0] CO;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
(* force_downto *)
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
function integer round_up2;
input integer N;
begin
round_up2 = ((N + 1) / 2) * 2;
end
endfunction
localparam Y_WIDTH2 = round_up2(Y_WIDTH);
(* force_downto *)
wire [Y_WIDTH2-1:0] AA = A_buf;
(* force_downto *)
wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
(* force_downto *)
wire [Y_WIDTH2-1:0] BX = B_buf;
(* force_downto *)
wire [Y_WIDTH2-1:0] C = {CO, CI};
(* force_downto *)
wire [Y_WIDTH2-1:0] FCO, Y1;
genvar i;
generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
CCU2C #(
.INIT0(16'b1001011010101010),
.INIT1(16'b1001011010101010),
.INJECT1_0("NO"),
.INJECT1_1("NO")
) ccu2c_i (
.CIN(C[i]),
.A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),
.A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),
.S0(Y[i]), .S1(Y1[i]),
.COUT(FCO[i])
);
assign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));
if (i+1 < Y_WIDTH) begin
assign CO[i+1] = FCO[i];
assign Y[i+1] = Y1[i];
end
end endgenerate
assign X = AA ^ BB;
endmodule

View File

@ -1,52 +0,0 @@
ram block $__ECP5_DP16KD_ {
abits 14;
widths 1 2 4 9 18 per_port;
byte 9;
cost 128;
init no_undef;
port srsw "A" "B" {
clock anyedge;
clken;
wrbe_separate;
portoption "WRITEMODE" "NORMAL" {
rdwr no_change;
}
portoption "WRITEMODE" "WRITETHROUGH" {
rdwr new;
}
portoption "WRITEMODE" "READBEFOREWRITE" {
rdwr old;
}
option "RESETMODE" "SYNC" {
rdsrst zero ungated block_wr;
}
option "RESETMODE" "ASYNC" {
rdarst zero;
}
rdinit zero;
}
}
ram block $__ECP5_PDPW16KD_ {
abits 14;
widths 1 2 4 9 18 36 per_port;
byte 9;
cost 128;
init no_undef;
port sr "R" {
clock anyedge;
clken;
option "RESETMODE" "SYNC" {
rdsrst zero ungated;
}
option "RESETMODE" "ASYNC" {
rdarst zero;
}
rdinit zero;
}
port sw "W" {
width 36;
clock anyedge;
clken;
}
}

View File

@ -1,489 +0,0 @@
module $__ECP5_DP16KD_ (...);
parameter INIT = 0;
parameter OPTION_RESETMODE = "SYNC";
parameter PORT_A_WIDTH = 18;
parameter PORT_A_WR_BE_WIDTH = 2;
parameter PORT_A_CLK_POL = 1;
parameter PORT_A_OPTION_WRITEMODE = "NORMAL";
input PORT_A_CLK;
input PORT_A_CLK_EN;
input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
parameter PORT_B_WIDTH = 18;
parameter PORT_B_WR_BE_WIDTH = 2;
parameter PORT_B_CLK_POL = 1;
parameter PORT_B_OPTION_WRITEMODE = "NORMAL";
input PORT_B_CLK;
input PORT_B_CLK_EN;
input PORT_B_WR_EN;
input PORT_B_RD_SRST;
input PORT_B_RD_ARST;
input [13:0] PORT_B_ADDR;
input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;
input [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;
output [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;
function [319:0] init_slice;
input integer idx;
integer i, j;
init_slice = 0;
for (i = 0; i < 16; i = i + 1) begin
init_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];
end
endfunction
wire [17:0] DOA;
wire [17:0] DOB;
wire [17:0] DIA = PORT_A_WR_DATA;
wire [17:0] DIB = PORT_B_WR_DATA;
assign PORT_A_RD_DATA = DOA;
assign PORT_B_RD_DATA = DOB;
DP16KD #(
.INITVAL_00(init_slice('h00)),
.INITVAL_01(init_slice('h01)),
.INITVAL_02(init_slice('h02)),
.INITVAL_03(init_slice('h03)),
.INITVAL_04(init_slice('h04)),
.INITVAL_05(init_slice('h05)),
.INITVAL_06(init_slice('h06)),
.INITVAL_07(init_slice('h07)),
.INITVAL_08(init_slice('h08)),
.INITVAL_09(init_slice('h09)),
.INITVAL_0A(init_slice('h0a)),
.INITVAL_0B(init_slice('h0b)),
.INITVAL_0C(init_slice('h0c)),
.INITVAL_0D(init_slice('h0d)),
.INITVAL_0E(init_slice('h0e)),
.INITVAL_0F(init_slice('h0f)),
.INITVAL_10(init_slice('h10)),
.INITVAL_11(init_slice('h11)),
.INITVAL_12(init_slice('h12)),
.INITVAL_13(init_slice('h13)),
.INITVAL_14(init_slice('h14)),
.INITVAL_15(init_slice('h15)),
.INITVAL_16(init_slice('h16)),
.INITVAL_17(init_slice('h17)),
.INITVAL_18(init_slice('h18)),
.INITVAL_19(init_slice('h19)),
.INITVAL_1A(init_slice('h1a)),
.INITVAL_1B(init_slice('h1b)),
.INITVAL_1C(init_slice('h1c)),
.INITVAL_1D(init_slice('h1d)),
.INITVAL_1E(init_slice('h1e)),
.INITVAL_1F(init_slice('h1f)),
.INITVAL_20(init_slice('h20)),
.INITVAL_21(init_slice('h21)),
.INITVAL_22(init_slice('h22)),
.INITVAL_23(init_slice('h23)),
.INITVAL_24(init_slice('h24)),
.INITVAL_25(init_slice('h25)),
.INITVAL_26(init_slice('h26)),
.INITVAL_27(init_slice('h27)),
.INITVAL_28(init_slice('h28)),
.INITVAL_29(init_slice('h29)),
.INITVAL_2A(init_slice('h2a)),
.INITVAL_2B(init_slice('h2b)),
.INITVAL_2C(init_slice('h2c)),
.INITVAL_2D(init_slice('h2d)),
.INITVAL_2E(init_slice('h2e)),
.INITVAL_2F(init_slice('h2f)),
.INITVAL_30(init_slice('h30)),
.INITVAL_31(init_slice('h31)),
.INITVAL_32(init_slice('h32)),
.INITVAL_33(init_slice('h33)),
.INITVAL_34(init_slice('h34)),
.INITVAL_35(init_slice('h35)),
.INITVAL_36(init_slice('h36)),
.INITVAL_37(init_slice('h37)),
.INITVAL_38(init_slice('h38)),
.INITVAL_39(init_slice('h39)),
.INITVAL_3A(init_slice('h3a)),
.INITVAL_3B(init_slice('h3b)),
.INITVAL_3C(init_slice('h3c)),
.INITVAL_3D(init_slice('h3d)),
.INITVAL_3E(init_slice('h3e)),
.INITVAL_3F(init_slice('h3f)),
.DATA_WIDTH_A(PORT_A_WIDTH),
.DATA_WIDTH_B(PORT_B_WIDTH),
.REGMODE_A("NOREG"),
.REGMODE_B("NOREG"),
.RESETMODE(OPTION_RESETMODE),
.ASYNC_RESET_RELEASE(OPTION_RESETMODE),
.CSDECODE_A("0b000"),
.CSDECODE_B("0b000"),
.CLKAMUX(PORT_A_CLK_POL ? "CLKA" : "INV"),
.CLKBMUX(PORT_B_CLK_POL ? "CLKB" : "INV"),
.WRITEMODE_A(PORT_A_OPTION_WRITEMODE),
.WRITEMODE_B(PORT_B_OPTION_WRITEMODE),
.GSR("AUTO")
) _TECHMAP_REPLACE_ (
.CLKA(PORT_A_CLK),
.WEA(PORT_A_WIDTH == 18 ? PORT_A_WR_EN : (PORT_A_WR_EN | PORT_A_WR_BE[0])),
.CEA(PORT_A_CLK_EN),
.OCEA(1'b1),
.RSTA(OPTION_RESETMODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST),
.CSA0(1'b0),
.CSA1(1'b0),
.CSA2(1'b0),
.ADA0(PORT_A_WIDTH == 18 ? PORT_A_WR_BE[0] : PORT_A_ADDR[0]),
.ADA1(PORT_A_WIDTH == 18 ? PORT_A_WR_BE[1] : PORT_A_ADDR[1]),
.ADA2(PORT_A_ADDR[2]),
.ADA3(PORT_A_ADDR[3]),
.ADA4(PORT_A_ADDR[4]),
.ADA5(PORT_A_ADDR[5]),
.ADA6(PORT_A_ADDR[6]),
.ADA7(PORT_A_ADDR[7]),
.ADA8(PORT_A_ADDR[8]),
.ADA9(PORT_A_ADDR[9]),
.ADA10(PORT_A_ADDR[10]),
.ADA11(PORT_A_ADDR[11]),
.ADA12(PORT_A_ADDR[12]),
.ADA13(PORT_A_ADDR[13]),
.DIA0(DIA[0]),
.DIA1(DIA[1]),
.DIA2(DIA[2]),
.DIA3(DIA[3]),
.DIA4(DIA[4]),
.DIA5(DIA[5]),
.DIA6(DIA[6]),
.DIA7(DIA[7]),
.DIA8(DIA[8]),
.DIA9(DIA[9]),
.DIA10(DIA[10]),
.DIA11(DIA[11]),
.DIA12(DIA[12]),
.DIA13(DIA[13]),
.DIA14(DIA[14]),
.DIA15(DIA[15]),
.DIA16(DIA[16]),
.DIA17(DIA[17]),
.DOA0(DOA[0]),
.DOA1(DOA[1]),
.DOA2(DOA[2]),
.DOA3(DOA[3]),
.DOA4(DOA[4]),
.DOA5(DOA[5]),
.DOA6(DOA[6]),
.DOA7(DOA[7]),
.DOA8(DOA[8]),
.DOA9(DOA[9]),
.DOA10(DOA[10]),
.DOA11(DOA[11]),
.DOA12(DOA[12]),
.DOA13(DOA[13]),
.DOA14(DOA[14]),
.DOA15(DOA[15]),
.DOA16(DOA[16]),
.DOA17(DOA[17]),
.CLKB(PORT_B_CLK),
.WEB(PORT_B_WIDTH == 18 ? PORT_B_WR_EN : (PORT_B_WR_EN | PORT_B_WR_BE[0])),
.CEB(PORT_B_CLK_EN),
.OCEB(1'b1),
.RSTB(OPTION_RESETMODE == "SYNC" ? PORT_B_RD_SRST : PORT_B_RD_ARST),
.CSB0(1'b0),
.CSB1(1'b0),
.CSB2(1'b0),
.ADB0(PORT_B_WIDTH == 18 ? PORT_B_WR_BE[0] : PORT_B_ADDR[0]),
.ADB1(PORT_B_WIDTH == 18 ? PORT_B_WR_BE[1] : PORT_B_ADDR[1]),
.ADB2(PORT_B_ADDR[2]),
.ADB3(PORT_B_ADDR[3]),
.ADB4(PORT_B_ADDR[4]),
.ADB5(PORT_B_ADDR[5]),
.ADB6(PORT_B_ADDR[6]),
.ADB7(PORT_B_ADDR[7]),
.ADB8(PORT_B_ADDR[8]),
.ADB9(PORT_B_ADDR[9]),
.ADB10(PORT_B_ADDR[10]),
.ADB11(PORT_B_ADDR[11]),
.ADB12(PORT_B_ADDR[12]),
.ADB13(PORT_B_ADDR[13]),
.DIB0(DIB[0]),
.DIB1(DIB[1]),
.DIB2(DIB[2]),
.DIB3(DIB[3]),
.DIB4(DIB[4]),
.DIB5(DIB[5]),
.DIB6(DIB[6]),
.DIB7(DIB[7]),
.DIB8(DIB[8]),
.DIB9(DIB[9]),
.DIB10(DIB[10]),
.DIB11(DIB[11]),
.DIB12(DIB[12]),
.DIB13(DIB[13]),
.DIB14(DIB[14]),
.DIB15(DIB[15]),
.DIB16(DIB[16]),
.DIB17(DIB[17]),
.DOB0(DOB[0]),
.DOB1(DOB[1]),
.DOB2(DOB[2]),
.DOB3(DOB[3]),
.DOB4(DOB[4]),
.DOB5(DOB[5]),
.DOB6(DOB[6]),
.DOB7(DOB[7]),
.DOB8(DOB[8]),
.DOB9(DOB[9]),
.DOB10(DOB[10]),
.DOB11(DOB[11]),
.DOB12(DOB[12]),
.DOB13(DOB[13]),
.DOB14(DOB[14]),
.DOB15(DOB[15]),
.DOB16(DOB[16]),
.DOB17(DOB[17]),
);
endmodule
module $__ECP5_PDPW16KD_ (...);
parameter INIT = 0;
parameter OPTION_RESETMODE = "SYNC";
parameter PORT_R_WIDTH = 36;
parameter PORT_R_CLK_POL = 1;
input PORT_R_CLK;
input PORT_R_CLK_EN;
input PORT_R_RD_SRST;
input PORT_R_RD_ARST;
input [13:0] PORT_R_ADDR;
output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;
parameter PORT_W_WIDTH = 36;
parameter PORT_W_WR_EN_WIDTH = 4;
parameter PORT_W_CLK_POL = 1;
input PORT_W_CLK;
input PORT_W_CLK_EN;
input [13:0] PORT_W_ADDR;
input [PORT_W_WR_EN_WIDTH-1:0] PORT_W_WR_EN;
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
function [319:0] init_slice;
input integer idx;
integer i, j;
init_slice = 0;
for (i = 0; i < 16; i = i + 1) begin
init_slice[i*20+:18] = INIT[(idx * 16 + i) * 18+:18];
end
endfunction
wire [35:0] DI = PORT_W_WR_DATA;
wire [35:0] DO;
assign PORT_R_RD_DATA = PORT_R_WIDTH == 36 ? DO : DO[35:18];
DP16KD #(
.INITVAL_00(init_slice('h00)),
.INITVAL_01(init_slice('h01)),
.INITVAL_02(init_slice('h02)),
.INITVAL_03(init_slice('h03)),
.INITVAL_04(init_slice('h04)),
.INITVAL_05(init_slice('h05)),
.INITVAL_06(init_slice('h06)),
.INITVAL_07(init_slice('h07)),
.INITVAL_08(init_slice('h08)),
.INITVAL_09(init_slice('h09)),
.INITVAL_0A(init_slice('h0a)),
.INITVAL_0B(init_slice('h0b)),
.INITVAL_0C(init_slice('h0c)),
.INITVAL_0D(init_slice('h0d)),
.INITVAL_0E(init_slice('h0e)),
.INITVAL_0F(init_slice('h0f)),
.INITVAL_10(init_slice('h10)),
.INITVAL_11(init_slice('h11)),
.INITVAL_12(init_slice('h12)),
.INITVAL_13(init_slice('h13)),
.INITVAL_14(init_slice('h14)),
.INITVAL_15(init_slice('h15)),
.INITVAL_16(init_slice('h16)),
.INITVAL_17(init_slice('h17)),
.INITVAL_18(init_slice('h18)),
.INITVAL_19(init_slice('h19)),
.INITVAL_1A(init_slice('h1a)),
.INITVAL_1B(init_slice('h1b)),
.INITVAL_1C(init_slice('h1c)),
.INITVAL_1D(init_slice('h1d)),
.INITVAL_1E(init_slice('h1e)),
.INITVAL_1F(init_slice('h1f)),
.INITVAL_20(init_slice('h20)),
.INITVAL_21(init_slice('h21)),
.INITVAL_22(init_slice('h22)),
.INITVAL_23(init_slice('h23)),
.INITVAL_24(init_slice('h24)),
.INITVAL_25(init_slice('h25)),
.INITVAL_26(init_slice('h26)),
.INITVAL_27(init_slice('h27)),
.INITVAL_28(init_slice('h28)),
.INITVAL_29(init_slice('h29)),
.INITVAL_2A(init_slice('h2a)),
.INITVAL_2B(init_slice('h2b)),
.INITVAL_2C(init_slice('h2c)),
.INITVAL_2D(init_slice('h2d)),
.INITVAL_2E(init_slice('h2e)),
.INITVAL_2F(init_slice('h2f)),
.INITVAL_30(init_slice('h30)),
.INITVAL_31(init_slice('h31)),
.INITVAL_32(init_slice('h32)),
.INITVAL_33(init_slice('h33)),
.INITVAL_34(init_slice('h34)),
.INITVAL_35(init_slice('h35)),
.INITVAL_36(init_slice('h36)),
.INITVAL_37(init_slice('h37)),
.INITVAL_38(init_slice('h38)),
.INITVAL_39(init_slice('h39)),
.INITVAL_3A(init_slice('h3a)),
.INITVAL_3B(init_slice('h3b)),
.INITVAL_3C(init_slice('h3c)),
.INITVAL_3D(init_slice('h3d)),
.INITVAL_3E(init_slice('h3e)),
.INITVAL_3F(init_slice('h3f)),
.DATA_WIDTH_A(PORT_W_WIDTH),
.DATA_WIDTH_B(PORT_R_WIDTH),
.REGMODE_A("NOREG"),
.REGMODE_B("NOREG"),
.RESETMODE(OPTION_RESETMODE),
.ASYNC_RESET_RELEASE(OPTION_RESETMODE),
.CSDECODE_A("0b000"),
.CSDECODE_B("0b000"),
.CLKAMUX(PORT_W_CLK_POL ? "CLKA" : "INV"),
.CLKBMUX(PORT_R_CLK_POL ? "CLKB" : "INV"),
.GSR("AUTO")
) _TECHMAP_REPLACE_ (
.CLKA(PORT_W_CLK),
.WEA(PORT_W_WIDTH >= 18 ? 1'b1 : PORT_W_WR_EN[0]),
.CEA(PORT_W_CLK_EN),
.OCEA(1'b0),
.RSTA(1'b0),
.CSA0(1'b0),
.CSA1(1'b0),
.CSA2(1'b0),
.ADA0(PORT_W_WIDTH >= 18 ? PORT_W_WR_EN[0] : PORT_W_ADDR[0]),
.ADA1(PORT_W_WIDTH >= 18 ? PORT_W_WR_EN[1] : PORT_W_ADDR[1]),
.ADA2(PORT_W_WIDTH >= 36 ? PORT_W_WR_EN[2] : PORT_W_ADDR[2]),
.ADA3(PORT_W_WIDTH >= 36 ? PORT_W_WR_EN[3] : PORT_W_ADDR[3]),
.ADA4(PORT_W_ADDR[4]),
.ADA5(PORT_W_ADDR[5]),
.ADA6(PORT_W_ADDR[6]),
.ADA7(PORT_W_ADDR[7]),
.ADA8(PORT_W_ADDR[8]),
.ADA9(PORT_W_ADDR[9]),
.ADA10(PORT_W_ADDR[10]),
.ADA11(PORT_W_ADDR[11]),
.ADA12(PORT_W_ADDR[12]),
.ADA13(PORT_W_ADDR[13]),
.DIA0(DI[0]),
.DIA1(DI[1]),
.DIA2(DI[2]),
.DIA3(DI[3]),
.DIA4(DI[4]),
.DIA5(DI[5]),
.DIA6(DI[6]),
.DIA7(DI[7]),
.DIA8(DI[8]),
.DIA9(DI[9]),
.DIA10(DI[10]),
.DIA11(DI[11]),
.DIA12(DI[12]),
.DIA13(DI[13]),
.DIA14(DI[14]),
.DIA15(DI[15]),
.DIA16(DI[16]),
.DIA17(DI[17]),
.DIB0(DI[18]),
.DIB1(DI[19]),
.DIB2(DI[20]),
.DIB3(DI[21]),
.DIB4(DI[22]),
.DIB5(DI[23]),
.DIB6(DI[24]),
.DIB7(DI[25]),
.DIB8(DI[26]),
.DIB9(DI[27]),
.DIB10(DI[28]),
.DIB11(DI[29]),
.DIB12(DI[30]),
.DIB13(DI[31]),
.DIB14(DI[32]),
.DIB15(DI[33]),
.DIB16(DI[34]),
.DIB17(DI[35]),
.CLKB(PORT_R_CLK),
.WEB(1'b0),
.CEB(PORT_R_CLK_EN),
.OCEB(1'b1),
.RSTB(OPTION_RESETMODE == "SYNC" ? PORT_R_RD_SRST : PORT_R_RD_ARST),
.CSB0(1'b0),
.CSB1(1'b0),
.CSB2(1'b0),
.ADB0(PORT_R_ADDR[0]),
.ADB1(PORT_R_ADDR[1]),
.ADB2(PORT_R_ADDR[2]),
.ADB3(PORT_R_ADDR[3]),
.ADB4(PORT_R_ADDR[4]),
.ADB5(PORT_R_ADDR[5]),
.ADB6(PORT_R_ADDR[6]),
.ADB7(PORT_R_ADDR[7]),
.ADB8(PORT_R_ADDR[8]),
.ADB9(PORT_R_ADDR[9]),
.ADB10(PORT_R_ADDR[10]),
.ADB11(PORT_R_ADDR[11]),
.ADB12(PORT_R_ADDR[12]),
.ADB13(PORT_R_ADDR[13]),
.DOA0(DO[0]),
.DOA1(DO[1]),
.DOA2(DO[2]),
.DOA3(DO[3]),
.DOA4(DO[4]),
.DOA5(DO[5]),
.DOA6(DO[6]),
.DOA7(DO[7]),
.DOA8(DO[8]),
.DOA9(DO[9]),
.DOA10(DO[10]),
.DOA11(DO[11]),
.DOA12(DO[12]),
.DOA13(DO[13]),
.DOA14(DO[14]),
.DOA15(DO[15]),
.DOA16(DO[16]),
.DOA17(DO[17]),
.DOB0(DO[18]),
.DOB1(DO[19]),
.DOB2(DO[20]),
.DOB3(DO[21]),
.DOB4(DO[22]),
.DOB5(DO[23]),
.DOB6(DO[24]),
.DOB7(DO[25]),
.DOB8(DO[26]),
.DOB9(DO[27]),
.DOB10(DO[28]),
.DOB11(DO[29]),
.DOB12(DO[30]),
.DOB13(DO[31]),
.DOB14(DO[32]),
.DOB15(DO[33]),
.DOB16(DO[34]),
.DOB17(DO[35]),
);
endmodule

View File

@ -1,850 +0,0 @@
// ECP5 Blackbox cells
// FIXME: Create sim models
(* blackbox *)
module MULT18X18D(
input A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17,
input B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16, B17,
input C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17,
input SIGNEDA, SIGNEDB, SOURCEA, SOURCEB,
input CLK0, CLK1, CLK2, CLK3,
input CE0, CE1, CE2, CE3,
input RST0, RST1, RST2, RST3,
input SRIA0, SRIA1, SRIA2, SRIA3, SRIA4, SRIA5, SRIA6, SRIA7, SRIA8, SRIA9, SRIA10, SRIA11, SRIA12, SRIA13, SRIA14, SRIA15, SRIA16, SRIA17,
input SRIB0, SRIB1, SRIB2, SRIB3, SRIB4, SRIB5, SRIB6, SRIB7, SRIB8, SRIB9, SRIB10, SRIB11, SRIB12, SRIB13, SRIB14, SRIB15, SRIB16, SRIB17,
output SROA0, SROA1, SROA2, SROA3, SROA4, SROA5, SROA6, SROA7, SROA8, SROA9, SROA10, SROA11, SROA12, SROA13, SROA14, SROA15, SROA16, SROA17,
output SROB0, SROB1, SROB2, SROB3, SROB4, SROB5, SROB6, SROB7, SROB8, SROB9, SROB10, SROB11, SROB12, SROB13, SROB14, SROB15, SROB16, SROB17,
output ROA0, ROA1, ROA2, ROA3, ROA4, ROA5, ROA6, ROA7, ROA8, ROA9, ROA10, ROA11, ROA12, ROA13, ROA14, ROA15, ROA16, ROA17,
output ROB0, ROB1, ROB2, ROB3, ROB4, ROB5, ROB6, ROB7, ROB8, ROB9, ROB10, ROB11, ROB12, ROB13, ROB14, ROB15, ROB16, ROB17,
output ROC0, ROC1, ROC2, ROC3, ROC4, ROC5, ROC6, ROC7, ROC8, ROC9, ROC10, ROC11, ROC12, ROC13, ROC14, ROC15, ROC16, ROC17,
output P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35,
output SIGNEDP
);
parameter REG_INPUTA_CLK = "NONE";
parameter REG_INPUTA_CE = "CE0";
parameter REG_INPUTA_RST = "RST0";
parameter REG_INPUTB_CLK = "NONE";
parameter REG_INPUTB_CE = "CE0";
parameter REG_INPUTB_RST = "RST0";
parameter REG_INPUTC_CLK = "NONE";
parameter REG_INPUTC_CE = "CE0";
parameter REG_INPUTC_RST = "RST0";
parameter REG_PIPELINE_CLK = "NONE";
parameter REG_PIPELINE_CE = "CE0";
parameter REG_PIPELINE_RST = "RST0";
parameter REG_OUTPUT_CLK = "NONE";
parameter REG_OUTPUT_CE = "CE0";
parameter REG_OUTPUT_RST = "RST0";
parameter [127:0] CLK0_DIV = "ENABLED";
parameter [127:0] CLK1_DIV = "ENABLED";
parameter [127:0] CLK2_DIV = "ENABLED";
parameter [127:0] CLK3_DIV = "ENABLED";
parameter HIGHSPEED_CLK = "NONE";
parameter [127:0] GSR = "ENABLED";
parameter CAS_MATCH_REG = "FALSE";
parameter [127:0] SOURCEB_MODE = "B_SHIFT";
parameter [127:0] MULT_BYPASS = "DISABLED";
parameter [127:0] RESETMODE = "SYNC";
endmodule
(* blackbox *)
module ALU54B(
input CLK0, CLK1, CLK2, CLK3,
input CE0, CE1, CE2, CE3,
input RST0, RST1, RST2, RST3,
input SIGNEDIA, SIGNEDIB, SIGNEDCIN,
input A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35,
input B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19, B20, B21, B22, B23, B24, B25, B26, B27, B28, B29, B30, B31, B32, B33, B34, B35,
input C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C14, C15, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26, C27, C28, C29, C30, C31, C32, C33, C34, C35, C36, C37, C38, C39, C40, C41, C42, C43, C44, C45, C46, C47, C48, C49, C50, C51, C52, C53,
input CFB0, CFB1, CFB2, CFB3, CFB4, CFB5, CFB6, CFB7, CFB8, CFB9, CFB10, CFB11, CFB12, CFB13, CFB14, CFB15, CFB16, CFB17, CFB18, CFB19, CFB20, CFB21, CFB22, CFB23, CFB24, CFB25, CFB26, CFB27, CFB28, CFB29, CFB30, CFB31, CFB32, CFB33, CFB34, CFB35, CFB36, CFB37, CFB38, CFB39, CFB40, CFB41, CFB42, CFB43, CFB44, CFB45, CFB46, CFB47, CFB48, CFB49, CFB50, CFB51, CFB52, CFB53,
input MA0, MA1, MA2, MA3, MA4, MA5, MA6, MA7, MA8, MA9, MA10, MA11, MA12, MA13, MA14, MA15, MA16, MA17, MA18, MA19, MA20, MA21, MA22, MA23, MA24, MA25, MA26, MA27, MA28, MA29, MA30, MA31, MA32, MA33, MA34, MA35,
input MB0, MB1, MB2, MB3, MB4, MB5, MB6, MB7, MB8, MB9, MB10, MB11, MB12, MB13, MB14, MB15, MB16, MB17, MB18, MB19, MB20, MB21, MB22, MB23, MB24, MB25, MB26, MB27, MB28, MB29, MB30, MB31, MB32, MB33, MB34, MB35,
input CIN0, CIN1, CIN2, CIN3, CIN4, CIN5, CIN6, CIN7, CIN8, CIN9, CIN10, CIN11, CIN12, CIN13, CIN14, CIN15, CIN16, CIN17, CIN18, CIN19, CIN20, CIN21, CIN22, CIN23, CIN24, CIN25, CIN26, CIN27, CIN28, CIN29, CIN30, CIN31, CIN32, CIN33, CIN34, CIN35, CIN36, CIN37, CIN38, CIN39, CIN40, CIN41, CIN42, CIN43, CIN44, CIN45, CIN46, CIN47, CIN48, CIN49, CIN50, CIN51, CIN52, CIN53,
input OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7, OP8, OP9, OP10,
output R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53,
output CO0, CO1, CO2, CO3, CO4, CO5, CO6, CO7, CO8, CO9, CO10, CO11, CO12, CO13, CO14, CO15, CO16, CO17, CO18, CO19, CO20, CO21, CO22, CO23, CO24, CO25, CO26, CO27, CO28, CO29, CO30, CO31, CO32, CO33, CO34, CO35, CO36, CO37, CO38, CO39, CO40, CO41, CO42, CO43, CO44, CO45, CO46, CO47, CO48, CO49, CO50, CO51, CO52, CO53,
output EQZ, EQZM, EQOM, EQPAT, EQPATB,
output OVER, UNDER, OVERUNDER,
output SIGNEDR
);
parameter REG_INPUTC0_CLK = "NONE";
parameter REG_INPUTC0_CE = "CE0";
parameter REG_INPUTC0_RST = "RST0";
parameter REG_INPUTC1_CLK = "NONE";
parameter REG_INPUTC1_CE = "CE0";
parameter REG_INPUTC1_RST = "RST0";
parameter REG_OPCODEOP0_0_CLK = "NONE";
parameter REG_OPCODEOP0_0_CE = "CE0";
parameter REG_OPCODEOP0_0_RST = "RST0";
parameter REG_OPCODEOP1_0_CLK = "NONE";
parameter REG_OPCODEOP0_1_CLK = "NONE";
parameter REG_OPCODEOP0_1_CE = "CE0";
parameter REG_OPCODEOP0_1_RST = "RST0";
parameter REG_OPCODEOP1_1_CLK = "NONE";
parameter REG_OPCODEIN_0_CLK = "NONE";
parameter REG_OPCODEIN_0_CE = "CE0";
parameter REG_OPCODEIN_0_RST = "RST0";
parameter REG_OPCODEIN_1_CLK = "NONE";
parameter REG_OPCODEIN_1_CE = "CE0";
parameter REG_OPCODEIN_1_RST = "RST0";
parameter REG_OUTPUT0_CLK = "NONE";
parameter REG_OUTPUT0_CE = "CE0";
parameter REG_OUTPUT0_RST = "RST0";
parameter REG_OUTPUT1_CLK = "NONE";
parameter REG_OUTPUT1_CE = "CE0";
parameter REG_OUTPUT1_RST = "RST0";
parameter REG_FLAG_CLK = "NONE";
parameter REG_FLAG_CE = "CE0";
parameter REG_FLAG_RST = "RST0";
parameter REG_INPUTCFB_CLK = "NONE";
parameter REG_INPUTCFB_CE = "CE0";
parameter REG_INPUTCFB_RST = "RST0";
parameter [127:0] MCPAT_SOURCE = "STATIC";
parameter [127:0] MASKPAT_SOURCE = "STATIC";
parameter MASK01 = "0x00000000000000";
parameter [127:0] CLK0_DIV = "ENABLED";
parameter [127:0] CLK1_DIV = "ENABLED";
parameter [127:0] CLK2_DIV = "ENABLED";
parameter [127:0] CLK3_DIV = "ENABLED";
parameter MCPAT = "0x00000000000000";
parameter MASKPAT = "0x00000000000000";
parameter RNDPAT = "0x00000000000000";
parameter [127:0] GSR = "ENABLED";
parameter [127:0] RESETMODE = "SYNC";
parameter MULT9_MODE = "DISABLED";
parameter FORCE_ZERO_BARREL_SHIFT = "DISABLED";
parameter LEGACY = "DISABLED";
endmodule
(* blackbox *)
module EHXPLLL (
input CLKI, CLKFB,
input PHASESEL1, PHASESEL0, PHASEDIR, PHASESTEP, PHASELOADREG,
input STDBY, PLLWAKESYNC,
input RST, ENCLKOP, ENCLKOS, ENCLKOS2, ENCLKOS3,
output CLKOP, CLKOS, CLKOS2, CLKOS3,
output LOCK, INTLOCK,
output REFCLK, CLKINTFB
);
parameter CLKI_DIV = 1;
parameter CLKFB_DIV = 1;
parameter CLKOP_DIV = 8;
parameter CLKOS_DIV = 8;
parameter CLKOS2_DIV = 8;
parameter CLKOS3_DIV = 8;
parameter CLKOP_ENABLE = "ENABLED";
parameter CLKOS_ENABLE = "DISABLED";
parameter CLKOS2_ENABLE = "DISABLED";
parameter CLKOS3_ENABLE = "DISABLED";
parameter CLKOP_CPHASE = 0;
parameter CLKOS_CPHASE = 0;
parameter CLKOS2_CPHASE = 0;
parameter CLKOS3_CPHASE = 0;
parameter CLKOP_FPHASE = 0;
parameter CLKOS_FPHASE = 0;
parameter CLKOS2_FPHASE = 0;
parameter CLKOS3_FPHASE = 0;
parameter FEEDBK_PATH = "CLKOP";
parameter CLKOP_TRIM_POL = "RISING";
parameter CLKOP_TRIM_DELAY = 0;
parameter CLKOS_TRIM_POL = "RISING";
parameter CLKOS_TRIM_DELAY = 0;
parameter OUTDIVIDER_MUXA = "DIVA";
parameter OUTDIVIDER_MUXB = "DIVB";
parameter OUTDIVIDER_MUXC = "DIVC";
parameter OUTDIVIDER_MUXD = "DIVD";
parameter PLL_LOCK_MODE = 0;
parameter PLL_LOCK_DELAY = 200;
parameter STDBY_ENABLE = "DISABLED";
parameter REFIN_RESET = "DISABLED";
parameter SYNC_ENABLE = "DISABLED";
parameter INT_LOCK_STICKY = "ENABLED";
parameter DPHASE_SOURCE = "DISABLED";
parameter PLLRST_ENA = "DISABLED";
parameter INTFB_WAKE = "DISABLED";
endmodule
(* blackbox *)
module DTR(
input STARTPULSE,
output DTROUT7, DTROUT6, DTROUT5, DTROUT4, DTROUT3, DTROUT2, DTROUT1, DTROUT0
);
endmodule
(* blackbox *)
module OSCG(
output OSC
);
parameter DIV = 128;
endmodule
(* blackbox *) (* keep *)
module USRMCLK(
input USRMCLKI, USRMCLKTS,
output USRMCLKO
);
endmodule
(* blackbox *) (* keep *)
module JTAGG(
(* iopad_external_pin *)
input TCK,
(* iopad_external_pin *)
input TMS,
(* iopad_external_pin *)
input TDI,
input JTDO2, JTDO1,
(* iopad_external_pin *)
output TDO,
output JTDI, JTCK, JRTI2, JRTI1,
output JSHIFT, JUPDATE, JRSTN, JCE2, JCE1
);
parameter ER1 = "ENABLED";
parameter ER2 = "ENABLED";
endmodule
(* blackbox *)
module DELAYF(
input A, LOADN, MOVE, DIRECTION,
output Z, CFLAG
);
parameter DEL_MODE = "USER_DEFINED";
parameter DEL_VALUE = 0;
endmodule
(* blackbox *)
module DELAYG(
input A,
output Z
);
parameter DEL_MODE = "USER_DEFINED";
parameter DEL_VALUE = 0;
endmodule
(* blackbox *)
module IDDRX1F(
input D, SCLK, RST,
output Q0, Q1
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module IDDRX2F(
input D, SCLK, ECLK, RST, ALIGNWD,
output Q0, Q1, Q2, Q3
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module IDDR71B(
input D, SCLK, ECLK, RST, ALIGNWD,
output Q0, Q1, Q2, Q3, Q4, Q5, Q6
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module IDDRX2DQA(
input D, DQSR90, ECLK, SCLK, RST,
input RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
output Q0, Q1, Q2, Q3, QWL
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX1F(
input SCLK, RST, D0, D1,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX2F(
input SCLK, ECLK, RST, D0, D1, D2, D3,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDR71B(
input SCLK, ECLK, RST, D0, D1, D2, D3, D4, D5, D6,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module OSHX2A(
input D0, D1, RST, ECLK, SCLK,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX2DQA(
input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW270,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module ODDRX2DQSB(
input D0, D1, D2, D3, RST, ECLK, SCLK, DQSW,
output Q
);
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module TSHX2DQA(
input T0, T1, SCLK, ECLK, DQSW270, RST,
output Q
);
parameter GSR = "ENABLED";
parameter REGSET = "SET";
endmodule
(* blackbox *)
module TSHX2DQSA(
input T0, T1, SCLK, ECLK, DQSW, RST,
output Q
);
parameter GSR = "ENABLED";
parameter REGSET = "SET";
endmodule
(* blackbox *)
module DQSBUFM(
input DQSI, READ1, READ0, READCLKSEL2, READCLKSEL1, READCLKSEL0, DDRDEL,
input ECLK, SCLK,
input DYNDELAY7, DYNDELAY6, DYNDELAY5, DYNDELAY4,
input DYNDELAY3, DYNDELAY2, DYNDELAY1, DYNDELAY0,
input RST, RDLOADN, RDMOVE, RDDIRECTION, WRLOADN, WRMOVE, WRDIRECTION, PAUSE,
output DQSR90, DQSW, DQSW270,
output RDPNTR2, RDPNTR1, RDPNTR0, WRPNTR2, WRPNTR1, WRPNTR0,
output DATAVALID, BURSTDET, RDCFLAG, WRCFLAG
);
parameter DQS_LI_DEL_ADJ = "FACTORYONLY";
parameter DQS_LI_DEL_VAL = 0;
parameter DQS_LO_DEL_ADJ = "FACTORYONLY";
parameter DQS_LO_DEL_VAL = 0;
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module DDRDLLA(
input CLK, RST, UDDCNTLN, FREEZE,
output LOCK, DDRDEL, DCNTL7, DCNTL6, DCNTL5, DCNTL4, DCNTL3, DCNTL2, DCNTL1, DCNTL0
);
parameter FORCE_MAX_DELAY = "NO";
parameter GSR = "ENABLED";
endmodule
(* blackbox *)
module DLLDELD(
input A, DDRDEL, LOADN, MOVE, DIRECTION,
output Z, CFLAG
);
parameter DEL_ADJ = "PLUS";
parameter DEL_VAL = 0;
endmodule
(* blackbox *)
module CLKDIVF(
input CLKI, RST, ALIGNWD,
output CDIVX
);
parameter GSR = "DISABLED";
parameter DIV = "2.0";
endmodule
(* blackbox *)
module ECLKSYNCB(
input ECLKI, STOP,
output ECLKO
);
endmodule
(* blackbox *)
module ECLKBRIDGECS(
input CLK0, CLK1, SEL,
output ECSOUT
);
endmodule
(* blackbox *)
module DCCA(
input CLKI, CE,
output CLKO
);
endmodule
(* blackbox *)
module DCSC(
input CLK1, CLK0,
input SEL1, SEL0,
input MODESEL,
output DCSOUT
);
parameter DCSMODE = "POS";
endmodule
(* blackbox *) (* keep *)
module DCUA(
(* iopad_external_pin *)
input CH0_HDINP,
(* iopad_external_pin *)
input CH1_HDINP,
(* iopad_external_pin *)
input CH0_HDINN,
(* iopad_external_pin *)
input CH1_HDINN,
input D_TXBIT_CLKP_FROM_ND, D_TXBIT_CLKN_FROM_ND, D_SYNC_ND, D_TXPLL_LOL_FROM_ND,
input CH0_RX_REFCLK, CH1_RX_REFCLK, CH0_FF_RXI_CLK, CH1_FF_RXI_CLK, CH0_FF_TXI_CLK, CH1_FF_TXI_CLK, CH0_FF_EBRD_CLK, CH1_FF_EBRD_CLK,
input CH0_FF_TX_D_0, CH1_FF_TX_D_0, CH0_FF_TX_D_1, CH1_FF_TX_D_1, CH0_FF_TX_D_2, CH1_FF_TX_D_2, CH0_FF_TX_D_3, CH1_FF_TX_D_3,
input CH0_FF_TX_D_4, CH1_FF_TX_D_4, CH0_FF_TX_D_5, CH1_FF_TX_D_5, CH0_FF_TX_D_6, CH1_FF_TX_D_6, CH0_FF_TX_D_7, CH1_FF_TX_D_7,
input CH0_FF_TX_D_8, CH1_FF_TX_D_8, CH0_FF_TX_D_9, CH1_FF_TX_D_9, CH0_FF_TX_D_10, CH1_FF_TX_D_10, CH0_FF_TX_D_11, CH1_FF_TX_D_11,
input CH0_FF_TX_D_12, CH1_FF_TX_D_12, CH0_FF_TX_D_13, CH1_FF_TX_D_13, CH0_FF_TX_D_14, CH1_FF_TX_D_14, CH0_FF_TX_D_15, CH1_FF_TX_D_15,
input CH0_FF_TX_D_16, CH1_FF_TX_D_16, CH0_FF_TX_D_17, CH1_FF_TX_D_17, CH0_FF_TX_D_18, CH1_FF_TX_D_18, CH0_FF_TX_D_19, CH1_FF_TX_D_19,
input CH0_FF_TX_D_20, CH1_FF_TX_D_20, CH0_FF_TX_D_21, CH1_FF_TX_D_21, CH0_FF_TX_D_22, CH1_FF_TX_D_22, CH0_FF_TX_D_23, CH1_FF_TX_D_23,
input CH0_FFC_EI_EN, CH1_FFC_EI_EN, CH0_FFC_PCIE_DET_EN, CH1_FFC_PCIE_DET_EN, CH0_FFC_PCIE_CT, CH1_FFC_PCIE_CT, CH0_FFC_SB_INV_RX, CH1_FFC_SB_INV_RX,
input CH0_FFC_ENABLE_CGALIGN, CH1_FFC_ENABLE_CGALIGN, CH0_FFC_SIGNAL_DETECT, CH1_FFC_SIGNAL_DETECT, CH0_FFC_FB_LOOPBACK, CH1_FFC_FB_LOOPBACK, CH0_FFC_SB_PFIFO_LP, CH1_FFC_SB_PFIFO_LP,
input CH0_FFC_PFIFO_CLR, CH1_FFC_PFIFO_CLR, CH0_FFC_RATE_MODE_RX, CH1_FFC_RATE_MODE_RX, CH0_FFC_RATE_MODE_TX, CH1_FFC_RATE_MODE_TX, CH0_FFC_DIV11_MODE_RX, CH1_FFC_DIV11_MODE_RX, CH0_FFC_RX_GEAR_MODE, CH1_FFC_RX_GEAR_MODE, CH0_FFC_TX_GEAR_MODE, CH1_FFC_TX_GEAR_MODE,
input CH0_FFC_DIV11_MODE_TX, CH1_FFC_DIV11_MODE_TX, CH0_FFC_LDR_CORE2TX_EN, CH1_FFC_LDR_CORE2TX_EN, CH0_FFC_LANE_TX_RST, CH1_FFC_LANE_TX_RST, CH0_FFC_LANE_RX_RST, CH1_FFC_LANE_RX_RST,
input CH0_FFC_RRST, CH1_FFC_RRST, CH0_FFC_TXPWDNB, CH1_FFC_TXPWDNB, CH0_FFC_RXPWDNB, CH1_FFC_RXPWDNB, CH0_LDR_CORE2TX, CH1_LDR_CORE2TX,
input D_SCIWDATA0, D_SCIWDATA1, D_SCIWDATA2, D_SCIWDATA3, D_SCIWDATA4, D_SCIWDATA5, D_SCIWDATA6, D_SCIWDATA7,
input D_SCIADDR0, D_SCIADDR1, D_SCIADDR2, D_SCIADDR3, D_SCIADDR4, D_SCIADDR5, D_SCIENAUX, D_SCISELAUX,
input CH0_SCIEN, CH1_SCIEN, CH0_SCISEL, CH1_SCISEL, D_SCIRD, D_SCIWSTN, D_CYAWSTN, D_FFC_SYNC_TOGGLE,
input D_FFC_DUAL_RST, D_FFC_MACRO_RST, D_FFC_MACROPDB, D_FFC_TRST, CH0_FFC_CDR_EN_BITSLIP, CH1_FFC_CDR_EN_BITSLIP, D_SCAN_ENABLE, D_SCAN_IN_0,
input D_SCAN_IN_1, D_SCAN_IN_2, D_SCAN_IN_3, D_SCAN_IN_4, D_SCAN_IN_5, D_SCAN_IN_6, D_SCAN_IN_7, D_SCAN_MODE,
input D_SCAN_RESET, D_CIN0, D_CIN1, D_CIN2, D_CIN3, D_CIN4, D_CIN5, D_CIN6,D_CIN7, D_CIN8, D_CIN9, D_CIN10, D_CIN11,
output CH0_HDOUTP, CH1_HDOUTP, CH0_HDOUTN, CH1_HDOUTN, D_TXBIT_CLKP_TO_ND, D_TXBIT_CLKN_TO_ND, D_SYNC_PULSE2ND, D_TXPLL_LOL_TO_ND,
output CH0_FF_RX_F_CLK, CH1_FF_RX_F_CLK, CH0_FF_RX_H_CLK, CH1_FF_RX_H_CLK, CH0_FF_TX_F_CLK, CH1_FF_TX_F_CLK, CH0_FF_TX_H_CLK, CH1_FF_TX_H_CLK,
output CH0_FF_RX_PCLK, CH1_FF_RX_PCLK, CH0_FF_TX_PCLK, CH1_FF_TX_PCLK, CH0_FF_RX_D_0, CH1_FF_RX_D_0, CH0_FF_RX_D_1, CH1_FF_RX_D_1,
output CH0_FF_RX_D_2, CH1_FF_RX_D_2, CH0_FF_RX_D_3, CH1_FF_RX_D_3, CH0_FF_RX_D_4, CH1_FF_RX_D_4, CH0_FF_RX_D_5, CH1_FF_RX_D_5,
output CH0_FF_RX_D_6, CH1_FF_RX_D_6, CH0_FF_RX_D_7, CH1_FF_RX_D_7, CH0_FF_RX_D_8, CH1_FF_RX_D_8, CH0_FF_RX_D_9, CH1_FF_RX_D_9,
output CH0_FF_RX_D_10, CH1_FF_RX_D_10, CH0_FF_RX_D_11, CH1_FF_RX_D_11, CH0_FF_RX_D_12, CH1_FF_RX_D_12, CH0_FF_RX_D_13, CH1_FF_RX_D_13,
output CH0_FF_RX_D_14, CH1_FF_RX_D_14, CH0_FF_RX_D_15, CH1_FF_RX_D_15, CH0_FF_RX_D_16, CH1_FF_RX_D_16, CH0_FF_RX_D_17, CH1_FF_RX_D_17,
output CH0_FF_RX_D_18, CH1_FF_RX_D_18, CH0_FF_RX_D_19, CH1_FF_RX_D_19, CH0_FF_RX_D_20, CH1_FF_RX_D_20, CH0_FF_RX_D_21, CH1_FF_RX_D_21,
output CH0_FF_RX_D_22, CH1_FF_RX_D_22, CH0_FF_RX_D_23, CH1_FF_RX_D_23, CH0_FFS_PCIE_DONE, CH1_FFS_PCIE_DONE, CH0_FFS_PCIE_CON, CH1_FFS_PCIE_CON,
output CH0_FFS_RLOS, CH1_FFS_RLOS, CH0_FFS_LS_SYNC_STATUS, CH1_FFS_LS_SYNC_STATUS, CH0_FFS_CC_UNDERRUN, CH1_FFS_CC_UNDERRUN, CH0_FFS_CC_OVERRUN, CH1_FFS_CC_OVERRUN,
output CH0_FFS_RXFBFIFO_ERROR, CH1_FFS_RXFBFIFO_ERROR, CH0_FFS_TXFBFIFO_ERROR, CH1_FFS_TXFBFIFO_ERROR, CH0_FFS_RLOL, CH1_FFS_RLOL, CH0_FFS_SKP_ADDED, CH1_FFS_SKP_ADDED,
output CH0_FFS_SKP_DELETED, CH1_FFS_SKP_DELETED, CH0_LDR_RX2CORE, CH1_LDR_RX2CORE, D_SCIRDATA0, D_SCIRDATA1, D_SCIRDATA2, D_SCIRDATA3,
output D_SCIRDATA4, D_SCIRDATA5, D_SCIRDATA6, D_SCIRDATA7, D_SCIINT, D_SCAN_OUT_0, D_SCAN_OUT_1, D_SCAN_OUT_2, D_SCAN_OUT_3, D_SCAN_OUT_4, D_SCAN_OUT_5, D_SCAN_OUT_6, D_SCAN_OUT_7,
output D_COUT0, D_COUT1, D_COUT2, D_COUT3, D_COUT4, D_COUT5, D_COUT6, D_COUT7, D_COUT8, D_COUT9, D_COUT10, D_COUT11, D_COUT12, D_COUT13, D_COUT14, D_COUT15, D_COUT16, D_COUT17, D_COUT18, D_COUT19,
input D_REFCLKI,
output D_FFS_PLOL
);
parameter CH0_AUTO_CALIB_EN = "0b0";
parameter CH0_AUTO_FACQ_EN = "0b0";
parameter CH0_BAND_THRESHOLD = "0b000000";
parameter CH0_CALIB_CK_MODE = "0b0";
parameter CH0_CC_MATCH_1 = "0b0000000000";
parameter CH0_CC_MATCH_2 = "0b0000000000";
parameter CH0_CC_MATCH_3 = "0b0000000000";
parameter CH0_CC_MATCH_4 = "0b0000000000";
parameter CH0_CDR_CNT4SEL = "0b00";
parameter CH0_CDR_CNT8SEL = "0b00";
parameter CH0_CTC_BYPASS = "0b0";
parameter CH0_DCOATDCFG = "0b00";
parameter CH0_DCOATDDLY = "0b00";
parameter CH0_DCOBYPSATD = "0b0";
parameter CH0_DCOCALDIV = "0b000";
parameter CH0_DCOCTLGI = "0b000";
parameter CH0_DCODISBDAVOID = "0b0";
parameter CH0_DCOFLTDAC = "0b00";
parameter CH0_DCOFTNRG = "0b000";
parameter CH0_DCOIOSTUNE = "0b000";
parameter CH0_DCOITUNE = "0b00";
parameter CH0_DCOITUNE4LSB = "0b000";
parameter CH0_DCOIUPDNX2 = "0b0";
parameter CH0_DCONUOFLSB = "0b000";
parameter CH0_DCOSCALEI = "0b00";
parameter CH0_DCOSTARTVAL = "0b000";
parameter CH0_DCOSTEP = "0b00";
parameter CH0_DEC_BYPASS = "0b0";
parameter CH0_ENABLE_CG_ALIGN = "0b0";
parameter CH0_ENC_BYPASS = "0b0";
parameter CH0_FF_RX_F_CLK_DIS = "0b0";
parameter CH0_FF_RX_H_CLK_EN = "0b0";
parameter CH0_FF_TX_F_CLK_DIS = "0b0";
parameter CH0_FF_TX_H_CLK_EN = "0b0";
parameter CH0_GE_AN_ENABLE = "0b0";
parameter CH0_INVERT_RX = "0b0";
parameter CH0_INVERT_TX = "0b0";
parameter CH0_LDR_CORE2TX_SEL = "0b0";
parameter CH0_LDR_RX2CORE_SEL = "0b0";
parameter CH0_LEQ_OFFSET_SEL = "0b0";
parameter CH0_LEQ_OFFSET_TRIM = "0b000";
parameter CH0_LSM_DISABLE = "0b0";
parameter CH0_MATCH_2_ENABLE = "0b0";
parameter CH0_MATCH_4_ENABLE = "0b0";
parameter CH0_MIN_IPG_CNT = "0b00";
parameter CH0_PCIE_EI_EN = "0b0";
parameter CH0_PCIE_MODE = "0b0";
parameter CH0_PCS_DET_TIME_SEL = "0b00";
parameter CH0_PDEN_SEL = "0b0";
parameter CH0_PRBS_ENABLE = "0b0";
parameter CH0_PRBS_LOCK = "0b0";
parameter CH0_PRBS_SELECTION = "0b0";
parameter CH0_RATE_MODE_RX = "0b0";
parameter CH0_RATE_MODE_TX = "0b0";
parameter CH0_RCV_DCC_EN = "0b0";
parameter CH0_REG_BAND_OFFSET = "0b0000";
parameter CH0_REG_BAND_SEL = "0b000000";
parameter CH0_REG_IDAC_EN = "0b0";
parameter CH0_REG_IDAC_SEL = "0b0000000000";
parameter CH0_REQ_EN = "0b0";
parameter CH0_REQ_LVL_SET = "0b00";
parameter CH0_RIO_MODE = "0b0";
parameter CH0_RLOS_SEL = "0b0";
parameter CH0_RPWDNB = "0b0";
parameter CH0_RTERM_RX = "0b00000";
parameter CH0_RTERM_TX = "0b00000";
parameter CH0_RXIN_CM = "0b00";
parameter CH0_RXTERM_CM = "0b00";
parameter CH0_RX_DCO_CK_DIV = "0b000";
parameter CH0_RX_DIV11_SEL = "0b0";
parameter CH0_RX_GEAR_BYPASS = "0b0";
parameter CH0_RX_GEAR_MODE = "0b0";
parameter CH0_RX_LOS_CEQ = "0b00";
parameter CH0_RX_LOS_EN = "0b0";
parameter CH0_RX_LOS_HYST_EN = "0b0";
parameter CH0_RX_LOS_LVL = "0b000";
parameter CH0_RX_RATE_SEL = "0b0000";
parameter CH0_RX_SB_BYPASS = "0b0";
parameter CH0_SB_BYPASS = "0b0";
parameter CH0_SEL_SD_RX_CLK = "0b0";
parameter CH0_TDRV_DAT_SEL = "0b00";
parameter CH0_TDRV_POST_EN = "0b0";
parameter CH0_TDRV_PRE_EN = "0b0";
parameter CH0_TDRV_SLICE0_CUR = "0b000";
parameter CH0_TDRV_SLICE0_SEL = "0b00";
parameter CH0_TDRV_SLICE1_CUR = "0b000";
parameter CH0_TDRV_SLICE1_SEL = "0b00";
parameter CH0_TDRV_SLICE2_CUR = "0b00";
parameter CH0_TDRV_SLICE2_SEL = "0b00";
parameter CH0_TDRV_SLICE3_CUR = "0b00";
parameter CH0_TDRV_SLICE3_SEL = "0b00";
parameter CH0_TDRV_SLICE4_CUR = "0b00";
parameter CH0_TDRV_SLICE4_SEL = "0b00";
parameter CH0_TDRV_SLICE5_CUR = "0b00";
parameter CH0_TDRV_SLICE5_SEL = "0b00";
parameter CH0_TPWDNB = "0b0";
parameter CH0_TX_CM_SEL = "0b00";
parameter CH0_TX_DIV11_SEL = "0b0";
parameter CH0_TX_GEAR_BYPASS = "0b0";
parameter CH0_TX_GEAR_MODE = "0b0";
parameter CH0_TX_POST_SIGN = "0b0";
parameter CH0_TX_PRE_SIGN = "0b0";
parameter CH0_UC_MODE = "0b0";
parameter CH0_UDF_COMMA_A = "0b0000000000";
parameter CH0_UDF_COMMA_B = "0b0000000000";
parameter CH0_UDF_COMMA_MASK = "0b0000000000";
parameter CH0_WA_BYPASS = "0b0";
parameter CH0_WA_MODE = "0b0";
parameter CH1_AUTO_CALIB_EN = "0b0";
parameter CH1_AUTO_FACQ_EN = "0b0";
parameter CH1_BAND_THRESHOLD = "0b000000";
parameter CH1_CALIB_CK_MODE = "0b0";
parameter CH1_CC_MATCH_1 = "0b0000000000";
parameter CH1_CC_MATCH_2 = "0b0000000000";
parameter CH1_CC_MATCH_3 = "0b0000000000";
parameter CH1_CC_MATCH_4 = "0b0000000000";
parameter CH1_CDR_CNT4SEL = "0b00";
parameter CH1_CDR_CNT8SEL = "0b00";
parameter CH1_CTC_BYPASS = "0b0";
parameter CH1_DCOATDCFG = "0b00";
parameter CH1_DCOATDDLY = "0b00";
parameter CH1_DCOBYPSATD = "0b0";
parameter CH1_DCOCALDIV = "0b000";
parameter CH1_DCOCTLGI = "0b000";
parameter CH1_DCODISBDAVOID = "0b0";
parameter CH1_DCOFLTDAC = "0b00";
parameter CH1_DCOFTNRG = "0b000";
parameter CH1_DCOIOSTUNE = "0b000";
parameter CH1_DCOITUNE = "0b00";
parameter CH1_DCOITUNE4LSB = "0b000";
parameter CH1_DCOIUPDNX2 = "0b0";
parameter CH1_DCONUOFLSB = "0b000";
parameter CH1_DCOSCALEI = "0b00";
parameter CH1_DCOSTARTVAL = "0b000";
parameter CH1_DCOSTEP = "0b00";
parameter CH1_DEC_BYPASS = "0b0";
parameter CH1_ENABLE_CG_ALIGN = "0b0";
parameter CH1_ENC_BYPASS = "0b0";
parameter CH1_FF_RX_F_CLK_DIS = "0b0";
parameter CH1_FF_RX_H_CLK_EN = "0b0";
parameter CH1_FF_TX_F_CLK_DIS = "0b0";
parameter CH1_FF_TX_H_CLK_EN = "0b0";
parameter CH1_GE_AN_ENABLE = "0b0";
parameter CH1_INVERT_RX = "0b0";
parameter CH1_INVERT_TX = "0b0";
parameter CH1_LDR_CORE2TX_SEL = "0b0";
parameter CH1_LDR_RX2CORE_SEL = "0b0";
parameter CH1_LEQ_OFFSET_SEL = "0b0";
parameter CH1_LEQ_OFFSET_TRIM = "0b000";
parameter CH1_LSM_DISABLE = "0b0";
parameter CH1_MATCH_2_ENABLE = "0b0";
parameter CH1_MATCH_4_ENABLE = "0b0";
parameter CH1_MIN_IPG_CNT = "0b00";
parameter CH1_PCIE_EI_EN = "0b0";
parameter CH1_PCIE_MODE = "0b0";
parameter CH1_PCS_DET_TIME_SEL = "0b00";
parameter CH1_PDEN_SEL = "0b0";
parameter CH1_PRBS_ENABLE = "0b0";
parameter CH1_PRBS_LOCK = "0b0";
parameter CH1_PRBS_SELECTION = "0b0";
parameter CH1_RATE_MODE_RX = "0b0";
parameter CH1_RATE_MODE_TX = "0b0";
parameter CH1_RCV_DCC_EN = "0b0";
parameter CH1_REG_BAND_OFFSET = "0b0000";
parameter CH1_REG_BAND_SEL = "0b000000";
parameter CH1_REG_IDAC_EN = "0b0";
parameter CH1_REG_IDAC_SEL = "0b0000000000";
parameter CH1_REQ_EN = "0b0";
parameter CH1_REQ_LVL_SET = "0b00";
parameter CH1_RIO_MODE = "0b0";
parameter CH1_RLOS_SEL = "0b0";
parameter CH1_RPWDNB = "0b0";
parameter CH1_RTERM_RX = "0b00000";
parameter CH1_RTERM_TX = "0b00000";
parameter CH1_RXIN_CM = "0b00";
parameter CH1_RXTERM_CM = "0b00";
parameter CH1_RX_DCO_CK_DIV = "0b000";
parameter CH1_RX_DIV11_SEL = "0b0";
parameter CH1_RX_GEAR_BYPASS = "0b0";
parameter CH1_RX_GEAR_MODE = "0b0";
parameter CH1_RX_LOS_CEQ = "0b00";
parameter CH1_RX_LOS_EN = "0b0";
parameter CH1_RX_LOS_HYST_EN = "0b0";
parameter CH1_RX_LOS_LVL = "0b000";
parameter CH1_RX_RATE_SEL = "0b0000";
parameter CH1_RX_SB_BYPASS = "0b0";
parameter CH1_SB_BYPASS = "0b0";
parameter CH1_SEL_SD_RX_CLK = "0b0";
parameter CH1_TDRV_DAT_SEL = "0b00";
parameter CH1_TDRV_POST_EN = "0b0";
parameter CH1_TDRV_PRE_EN = "0b0";
parameter CH1_TDRV_SLICE0_CUR = "0b000";
parameter CH1_TDRV_SLICE0_SEL = "0b00";
parameter CH1_TDRV_SLICE1_CUR = "0b000";
parameter CH1_TDRV_SLICE1_SEL = "0b00";
parameter CH1_TDRV_SLICE2_CUR = "0b00";
parameter CH1_TDRV_SLICE2_SEL = "0b00";
parameter CH1_TDRV_SLICE3_CUR = "0b00";
parameter CH1_TDRV_SLICE3_SEL = "0b00";
parameter CH1_TDRV_SLICE4_CUR = "0b00";
parameter CH1_TDRV_SLICE4_SEL = "0b00";
parameter CH1_TDRV_SLICE5_CUR = "0b00";
parameter CH1_TDRV_SLICE5_SEL = "0b00";
parameter CH1_TPWDNB = "0b0";
parameter CH1_TX_CM_SEL = "0b00";
parameter CH1_TX_DIV11_SEL = "0b0";
parameter CH1_TX_GEAR_BYPASS = "0b0";
parameter CH1_TX_GEAR_MODE = "0b0";
parameter CH1_TX_POST_SIGN = "0b0";
parameter CH1_TX_PRE_SIGN = "0b0";
parameter CH1_UC_MODE = "0b0";
parameter CH1_UDF_COMMA_A = "0b0000000000";
parameter CH1_UDF_COMMA_B = "0b0000000000";
parameter CH1_UDF_COMMA_MASK = "0b0000000000";
parameter CH1_WA_BYPASS = "0b0";
parameter CH1_WA_MODE = "0b0";
parameter D_BITCLK_FROM_ND_EN = "0b0";
parameter D_BITCLK_LOCAL_EN = "0b0";
parameter D_BITCLK_ND_EN = "0b0";
parameter D_BUS8BIT_SEL = "0b0";
parameter D_CDR_LOL_SET = "0b00";
parameter D_CMUSETBIASI = "0b00";
parameter D_CMUSETI4CPP = "0b0000";
parameter D_CMUSETI4CPZ = "0b0000";
parameter D_CMUSETI4VCO = "0b00";
parameter D_CMUSETICP4P = "0b00";
parameter D_CMUSETICP4Z = "0b000";
parameter D_CMUSETINITVCT = "0b00";
parameter D_CMUSETISCL4VCO = "0b000";
parameter D_CMUSETP1GM = "0b000";
parameter D_CMUSETP2AGM = "0b000";
parameter D_CMUSETZGM = "0b000";
parameter D_DCO_CALIB_TIME_SEL = "0b00";
parameter D_HIGH_MARK = "0b0000";
parameter D_IB_PWDNB = "0b0";
parameter D_ISETLOS = "0b00000000";
parameter D_LOW_MARK = "0b0000";
parameter D_MACROPDB = "0b0";
parameter D_PD_ISET = "0b00";
parameter D_PLL_LOL_SET = "0b00";
parameter D_REFCK_MODE = "0b000";
parameter D_REQ_ISET = "0b000";
parameter D_RG_EN = "0b0";
parameter D_RG_SET = "0b00";
parameter D_SETICONST_AUX = "0b00";
parameter D_SETICONST_CH = "0b00";
parameter D_SETIRPOLY_AUX = "0b00";
parameter D_SETIRPOLY_CH = "0b00";
parameter D_SETPLLRC = "0b000000";
parameter D_SYNC_LOCAL_EN = "0b0";
parameter D_SYNC_ND_EN = "0b0";
parameter D_TXPLL_PWDNB = "0b0";
parameter D_TX_VCO_CK_DIV = "0b000";
parameter D_XGE_MODE = "0b0";
// These parameters don't do anything but are
// needed for compatibility with Diamond
parameter D_TX_MAX_RATE = "2.5";
parameter D_RX_MAX_RATE = "2.5";
parameter CH0_TXAMPLITUDE = "0d1300";
parameter CH1_TXAMPLITUDE = "0d1300";
parameter CH0_PROTOCOL = "8B10B";
parameter CH1_PROTOCOL = "8B10B";
parameter CH0_CDR_MAX_RATE = "2.5";
parameter CH1_CDR_MAX_RATE = "2.5";
parameter CH0_TXDEPRE = "DISABLED";
parameter CH1_TXDEPRE = "DISABLED";
parameter CH0_TXDEPOST = "DISABLED";
parameter CH1_TXDEPOST = "DISABLED";
endmodule
(* blackbox *)
module EXTREFB (
(* iopad_external_pin *)
input REFCLKP,
(* iopad_external_pin *)
input REFCLKN,
output REFCLKO
);
parameter REFCK_PWDNB = "0b0";
parameter REFCK_RTERM = "0b0";
parameter REFCK_DCBIAS_EN = "0b0";
endmodule
(* blackbox *)
module PCSCLKDIV (
input CLKI, RST, SEL2, SEL1, SEL0,
output CDIV1, CDIVX
);
parameter GSR = "DISABLED";
endmodule
// Note: this module is not marked keep as we want it swept away in synth (sim use only)
(* blackbox *)
module PUR (
input PUR
);
parameter RST_PULSE = 1;
endmodule
(* blackbox, keep *)
module GSR (
input GSR
);
endmodule
(* blackbox, keep *)
module SGSR (
input GSR, CLK
);
endmodule
(* blackbox *)
module PDPW16KD (
input DI35, DI34, DI33, DI32, DI31, DI30, DI29, DI28, DI27, DI26, DI25, DI24, DI23, DI22, DI21, DI20, DI19, DI18,
input DI17, DI16, DI15, DI14, DI13, DI12, DI11, DI10, DI9, DI8, DI7, DI6, DI5, DI4, DI3, DI2, DI1, DI0,
input ADW8, ADW7, ADW6, ADW5, ADW4, ADW3, ADW2, ADW1, ADW0,
input BE3, BE2, BE1, BE0, CEW, CLKW, CSW2, CSW1, CSW0,
input ADR13, ADR12, ADR11, ADR10, ADR9, ADR8, ADR7, ADR6, ADR5, ADR4, ADR3, ADR2, ADR1, ADR0,
input CER, OCER, CLKR, CSR2, CSR1, CSR0, RST,
output DO35, DO34, DO33, DO32, DO31, DO30, DO29, DO28, DO27, DO26, DO25, DO24, DO23, DO22, DO21, DO20, DO19, DO18,
output DO17, DO16, DO15, DO14, DO13, DO12, DO11, DO10, DO9, DO8, DO7, DO6, DO5, DO4, DO3, DO2, DO1, DO0
);
parameter DATA_WIDTH_W = 36;
parameter DATA_WIDTH_R = 36;
parameter GSR = "ENABLED";
parameter REGMODE = "NOREG";
parameter RESETMODE = "SYNC";
parameter ASYNC_RESET_RELEASE = "SYNC";
parameter CSDECODE_W = "0b000";
parameter CSDECODE_R = "0b000";
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_DATA = "STATIC";
parameter CLKWMUX = "CLKW";
parameter CLKRMUX = "CLKR";
endmodule

View File

@ -1,40 +0,0 @@
// Diamond flip-flops
module FD1P3AX(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3AY(input D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3BX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3DX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3IX(input CD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1P3JX(input PD, D, SP, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module FD1S3AX(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule
module FD1S3AY(input D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(|0), .DI(D), .Q(Q)); endmodule
module FD1S3BX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
module FD1S3DX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3IX(input CD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3JX(input PD, D, CK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
// TODO: Diamond latches
// module FL1P3AY(); endmodule
// module FL1P3AZ(); endmodule
// module FL1P3BX(); endmodule
// module FL1P3DX(); endmodule
// module FL1P3IY(); endmodule
// module FL1P3JY(); endmodule
// module FL1S3AX(); endmodule
// module FL1S3AY(); endmodule
// Diamond I/O registers
module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
// TODO: Diamond I/O latches
// module IFS1S1B(input PD, D, SCLK, output Q); endmodule
// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
// module IFS1S1J(input CD, D, SCLK, output Q); endmodule

View File

@ -1,14 +0,0 @@
// Diamond I/O buffers
module IB ((* iopad_external_pin *) input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
module IBPU ((* iopad_external_pin *) input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
module IBPD ((* iopad_external_pin *) input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
module OB (input I, (* iopad_external_pin *) output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule
module OBZ (input I, T, (* iopad_external_pin *) output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
module OBZPU(input I, T, (* iopad_external_pin *) output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
module OBZPD(input I, T, (* iopad_external_pin *) output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule
module BB (input I, T, output O, (* iopad_external_pin *) inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
module BBPU (input I, T, output O, (* iopad_external_pin *) inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
module BBPD (input I, T, output O, (* iopad_external_pin *) inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
module ILVDS(input A, AN, (* iopad_external_pin *) output Z ); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule
module OLVDS(input A, (* iopad_external_pin *) output Z, output ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule

View File

@ -1,681 +0,0 @@
// ---------------------------------------
(* abc9_lut=1, lib_whitebox *)
module LUT4(input A, B, C, D, output Z);
parameter [15:0] INIT = 16'h0000;
wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
assign Z = A ? s1[1] : s1[0];
specify
(A => Z) = 141;
(B => Z) = 275;
(C => Z) = 379;
(D => Z) = 379;
endspecify
endmodule
// This is a placeholder for ABC9 to extract the area/delay
// cost of 5-input LUTs and is not intended to be instantiated
// LUT5 = 2x LUT4 + PFUMX
(* abc9_lut=2 *)
module \$__ABC9_LUT5 (input M0, D, C, B, A, output Z);
specify
(M0 => Z) = 151;
(D => Z) = 239;
(C => Z) = 373;
(B => Z) = 477;
(A => Z) = 477;
endspecify
endmodule
// This is a placeholder for ABC9 to extract the area/delay
// of 6-input LUTs and is not intended to be instantiated
// LUT6 = 2x LUT5 + MUX2
(* abc9_lut=4 *)
module \$__ABC9_LUT6 (input M1, M0, D, C, B, A, output Z);
specify
(M1 => Z) = 148;
(M0 => Z) = 292;
(D => Z) = 380;
(C => Z) = 514;
(B => Z) = 618;
(A => Z) = 618;
endspecify
endmodule
// This is a placeholder for ABC9 to extract the area/delay
// of 7-input LUTs and is not intended to be instantiated
// LUT7 = 2x LUT6 + MUX2
(* abc9_lut=8 *)
module \$__ABC9_LUT7 (input M2, M1, M0, D, C, B, A, output Z);
specify
(M2 => Z) = 148;
(M1 => Z) = 289;
(M0 => Z) = 433;
(D => Z) = 521;
(C => Z) = 655;
(B => Z) = 759;
(A => Z) = 759;
endspecify
endmodule
// ---------------------------------------
(* abc9_box, lib_whitebox *)
module L6MUX21 (input D0, D1, SD, output Z);
assign Z = SD ? D1 : D0;
specify
(D0 => Z) = 140;
(D1 => Z) = 141;
(SD => Z) = 148;
endspecify
endmodule
// ---------------------------------------
(* abc9_box, lib_whitebox *)
module CCU2C(
(* abc9_carry *)
input CIN,
input A0, B0, C0, D0, A1, B1, C1, D1,
output S0, S1,
(* abc9_carry *)
output COUT
);
parameter [15:0] INIT0 = 16'h0000;
parameter [15:0] INIT1 = 16'h0000;
parameter INJECT1_0 = "YES";
parameter INJECT1_1 = "YES";
// First half
wire LUT4_0, LUT2_0;
LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));
LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));
wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
assign S0 = LUT4_0 ^ gated_cin_0;
wire gated_lut2_0 = (INJECT1_0 == "YES") ? 1'b0 : LUT2_0;
wire cout_0 = (~LUT4_0 & gated_lut2_0) | (LUT4_0 & CIN);
// Second half
wire LUT4_1, LUT2_1;
LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));
LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));
wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0;
assign S1 = LUT4_1 ^ gated_cin_1;
wire gated_lut2_1 = (INJECT1_1 == "YES") ? 1'b0 : LUT2_1;
assign COUT = (~LUT4_1 & gated_lut2_1) | (LUT4_1 & cout_0);
specify
(A0 => S0) = 379;
(B0 => S0) = 379;
(C0 => S0) = 275;
(D0 => S0) = 141;
(CIN => S0) = 257;
(A0 => S1) = 630;
(B0 => S1) = 630;
(C0 => S1) = 526;
(D0 => S1) = 392;
(A1 => S1) = 379;
(B1 => S1) = 379;
(C1 => S1) = 275;
(D1 => S1) = 141;
(CIN => S1) = 273;
(A0 => COUT) = 516;
(B0 => COUT) = 516;
(C0 => COUT) = 412;
(D0 => COUT) = 278;
(A1 => COUT) = 516;
(B1 => COUT) = 516;
(C1 => COUT) = 412;
(D1 => COUT) = 278;
(CIN => COUT) = 43;
endspecify
endmodule
// ---------------------------------------
module TRELLIS_RAM16X2 (
input DI0, DI1,
input WAD0, WAD1, WAD2, WAD3,
input WRE, WCK,
input RAD0, RAD1, RAD2, RAD3,
output DO0, DO1
);
parameter WCKMUX = "WCK";
parameter WREMUX = "WRE";
parameter INITVAL_0 = 16'h0000;
parameter INITVAL_1 = 16'h0000;
reg [1:0] mem[15:0];
integer i;
initial begin
for (i = 0; i < 16; i = i + 1)
mem[i] <= {INITVAL_1[i], INITVAL_0[i]};
end
wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
reg muxwre;
always @(*)
case (WREMUX)
"1": muxwre = 1'b1;
"0": muxwre = 1'b0;
"INV": muxwre = ~WRE;
default: muxwre = WRE;
endcase
always @(posedge muxwck)
if (muxwre)
mem[{WAD3, WAD2, WAD1, WAD0}] <= {DI1, DI0};
assign {DO1, DO0} = mem[{RAD3, RAD2, RAD1, RAD0}];
endmodule
// ---------------------------------------
(* abc9_box, lib_whitebox *)
module PFUMX (input ALUT, BLUT, C0, output Z);
assign Z = C0 ? ALUT : BLUT;
specify
(ALUT => Z) = 98;
(BLUT => Z) = 98;
(C0 => Z) = 151;
endspecify
endmodule
// ---------------------------------------
(* abc9_box, lib_whitebox *)
module TRELLIS_DPR16X4 (
input [3:0] DI,
input [3:0] WAD,
input WRE,
input WCK,
input [3:0] RAD,
output [3:0] DO
);
parameter WCKMUX = "WCK";
parameter WREMUX = "WRE";
parameter [63:0] INITVAL = 64'h0000000000000000;
reg [3:0] mem[15:0];
integer i;
initial begin
for (i = 0; i < 16; i = i + 1)
mem[i] <= INITVAL[4*i +: 4];
end
wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
reg muxwre;
always @(*)
case (WREMUX)
"1": muxwre = 1'b1;
"0": muxwre = 1'b0;
"INV": muxwre = ~WRE;
default: muxwre = WRE;
endcase
always @(posedge muxwck)
if (muxwre)
mem[WAD] <= DI;
assign DO = mem[RAD];
specify
// TODO
(RAD *> DO) = 0;
endspecify
endmodule
// ---------------------------------------
(* abc9_box, lib_whitebox *)
module DPR16X4C (
input [3:0] DI,
input WCK, WRE,
input [3:0] RAD,
input [3:0] WAD,
output [3:0] DO
);
// For legacy Lattice compatibility, INITIVAL is a hex
// string rather than a numeric parameter
parameter INITVAL = "0x0000000000000000";
function [63:0] convert_initval;
input [143:0] hex_initval;
reg done;
reg [63:0] temp;
reg [7:0] char;
integer i;
begin
done = 1'b0;
temp = 0;
for (i = 0; i < 16; i = i + 1) begin
if (!done) begin
char = hex_initval[8*i +: 8];
if (char == "x") begin
done = 1'b1;
end else begin
if (char >= "0" && char <= "9")
temp[4*i +: 4] = char - "0";
else if (char >= "A" && char <= "F")
temp[4*i +: 4] = 10 + char - "A";
else if (char >= "a" && char <= "f")
temp[4*i +: 4] = 10 + char - "a";
end
end
end
convert_initval = temp;
end
endfunction
localparam conv_initval = convert_initval(INITVAL);
reg [3:0] ram[0:15];
integer i;
initial begin
for (i = 0; i < 15; i = i + 1) begin
ram[i] <= conv_initval[4*i +: 4];
end
end
always @(posedge WCK)
if (WRE)
ram[WAD] <= DI;
assign DO = ram[RAD];
specify
// TODO
(RAD *> DO) = 0;
endspecify
endmodule
// ---------------------------------------
(* lib_whitebox *)
module LUT2(input A, B, output Z);
parameter [3:0] INIT = 4'h0;
wire [1:0] s1 = B ? INIT[ 3:2] : INIT[1:0];
assign Z = A ? s1[1] : s1[0];
endmodule
// ---------------------------------------
`ifdef YOSYS
(* abc9_flop=(SRMODE != "ASYNC"), abc9_box=(SRMODE == "ASYNC"), lib_whitebox *)
`endif
module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
parameter GSR = "ENABLED";
parameter [127:0] CEMUX = "1";
parameter CLKMUX = "CLK";
parameter LSRMUX = "LSR";
parameter SRMODE = "LSR_OVER_CE";
parameter REGSET = "RESET";
parameter [127:0] LSRMODE = "LSR";
wire muxce;
generate
case (CEMUX)
"1": assign muxce = 1'b1;
"0": assign muxce = 1'b0;
"INV": assign muxce = ~CE;
default: assign muxce = CE;
endcase
endgenerate
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
wire srval;
generate
if (LSRMODE == "PRLD")
assign srval = M;
else
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
endgenerate
initial Q = srval;
generate
if (SRMODE == "ASYNC") begin
always @(posedge muxclk, posedge muxlsr)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end else begin
always @(posedge muxclk)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end
endgenerate
specify
$setup(DI, negedge CLK &&& CLKMUX == "INV", 0);
$setup(CE, negedge CLK &&& CLKMUX == "INV", 0);
$setup(LSR, negedge CLK &&& CLKMUX == "INV", 0);
$setup(DI, posedge CLK &&& CLKMUX != "INV", 0);
$setup(CE, posedge CLK &&& CLKMUX != "INV", 0);
$setup(LSR, posedge CLK &&& CLKMUX != "INV", 0);
`ifndef YOSYS
if (SRMODE == "ASYNC" && muxlsr && CLKMUX == "INV") (negedge CLK => (Q : srval)) = 0;
if (SRMODE == "ASYNC" && muxlsr && CLKMUX != "INV") (posedge CLK => (Q : srval)) = 0;
`else
if (SRMODE == "ASYNC" && muxlsr) (LSR => Q) = 0; // Technically, this should be an edge sensitive path
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
if (!muxlsr && muxce && CLKMUX == "INV") (negedge CLK => (Q : DI)) = 0;
if (!muxlsr && muxce && CLKMUX != "INV") (posedge CLK => (Q : DI)) = 0;
endspecify
endmodule
// ---------------------------------------
(* keep *)
module TRELLIS_IO(
(* iopad_external_pin *)
inout B,
input I,
input T,
output O
);
parameter DIR = "INPUT";
reg T_pd;
always @(*) if (T === 1'bz) T_pd = 1'b0; else T_pd = T;
generate
if (DIR == "INPUT") begin
assign B = 1'bz;
assign O = B;
end else if (DIR == "OUTPUT") begin
assign B = T_pd ? 1'bz : I;
assign O = 1'bx;
end else if (DIR == "BIDIR") begin
assign B = T_pd ? 1'bz : I;
assign O = B;
end else begin
ERROR_UNKNOWN_IO_MODE error();
end
endgenerate
endmodule
// ---------------------------------------
module INV(input A, output Z);
assign Z = !A;
endmodule
// ---------------------------------------
module TRELLIS_COMB(
input A, B, C, D, M,
input FCI, F1, FXA, FXB,
input WD,
input WAD0, WAD1, WAD2, WAD3,
input WRE, WCK,
output F, FCO, OFX
);
parameter MODE = "LOGIC";
parameter INITVAL = 16'h0;
parameter CCU2_INJECT1 = "NO";
parameter WREMUX = "WRE";
parameter IS_Z1 = 1'b0;
generate
if (MODE == "LOGIC") begin: mode_logic
LUT4 #(.INIT(INITVAL)) lut4 (.A(A), .B(B), .C(C), .D(D), .Z(F));
end else if (MODE == "CCU2") begin: mode_ccu2
wire l4o, l2o;
LUT4 #(.INIT(INITVAL)) lut4_0(.A(A), .B(B), .C(C), .D(D), .Z(l4o));
LUT2 #(.INIT(INITVAL[3:0])) lut2_0(.A(A), .B(B), .Z(l2o));
wire gated_cin_0 = (CCU2_INJECT1 == "YES") ? 1'b0 : FCI;
assign F = l4o ^ gated_cin_0;
wire gated_lut2_0 = (CCU2_INJECT1 == "YES") ? 1'b0 : l2o;
wire FCO = (~l4o & gated_lut2_0) | (l4o & FCI);
end else if (MODE == "DPRAM") begin: mode_dpram
reg [15:0] ram = INITVAL;
always @(posedge WCK)
if (WRE)
ram[{WAD3, WAD2, WAD1, WAD0}] <= WD;
assign F = ram[{A, C, B, D}];
end else begin
$error("unsupported COMB mode %s", MODE);
end
if (IS_Z1)
L6MUX21 lutx_mux (.D0(FXA), .D1(FXB), .SD(M), .Z(OFX));
else
PFUMX lut5_mux (.ALUT(F1), .BLUT(F), .C0(M), .Z(OFX));
endgenerate
endmodule
(* blackbox *)
module DP16KD(
input DIA17, DIA16, DIA15, DIA14, DIA13, DIA12, DIA11, DIA10, DIA9, DIA8, DIA7, DIA6, DIA5, DIA4, DIA3, DIA2, DIA1, DIA0,
input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0,
input CEA, OCEA, CLKA, WEA, RSTA,
input CSA2, CSA1, CSA0,
output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0,
input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0,
input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0,
input CEB, OCEB, CLKB, WEB, RSTB,
input CSB2, CSB1, CSB0,
output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
);
parameter DATA_WIDTH_A = 18;
parameter DATA_WIDTH_B = 18;
parameter REGMODE_A = "NOREG";
parameter REGMODE_B = "NOREG";
parameter RESETMODE = "SYNC";
parameter ASYNC_RESET_RELEASE = "SYNC";
parameter CSDECODE_A = "0b000";
parameter CSDECODE_B = "0b000";
parameter WRITEMODE_A = "NORMAL";
parameter WRITEMODE_B = "NORMAL";
parameter DIA17MUX = "DIA17";
parameter DIA16MUX = "DIA16";
parameter DIA15MUX = "DIA15";
parameter DIA14MUX = "DIA14";
parameter DIA13MUX = "DIA13";
parameter DIA12MUX = "DIA12";
parameter DIA11MUX = "DIA11";
parameter DIA10MUX = "DIA10";
parameter DIA9MUX = "DIA9";
parameter DIA8MUX = "DIA8";
parameter DIA7MUX = "DIA7";
parameter DIA6MUX = "DIA6";
parameter DIA5MUX = "DIA5";
parameter DIA4MUX = "DIA4";
parameter DIA3MUX = "DIA3";
parameter DIA2MUX = "DIA2";
parameter DIA1MUX = "DIA1";
parameter DIA0MUX = "DIA0";
parameter ADA13MUX = "ADA13";
parameter ADA12MUX = "ADA12";
parameter ADA11MUX = "ADA11";
parameter ADA10MUX = "ADA10";
parameter ADA9MUX = "ADA9";
parameter ADA8MUX = "ADA8";
parameter ADA7MUX = "ADA7";
parameter ADA6MUX = "ADA6";
parameter ADA5MUX = "ADA5";
parameter ADA4MUX = "ADA4";
parameter ADA3MUX = "ADA3";
parameter ADA2MUX = "ADA2";
parameter ADA1MUX = "ADA1";
parameter ADA0MUX = "ADA0";
parameter CEAMUX = "CEA";
parameter OCEAMUX = "OCEA";
parameter CLKAMUX = "CLKA";
parameter WEAMUX = "WEA";
parameter RSTAMUX = "RSTA";
parameter CSA2MUX = "CSA2";
parameter CSA1MUX = "CSA1";
parameter CSA0MUX = "CSA0";
parameter DOA17MUX = "DOA17";
parameter DOA16MUX = "DOA16";
parameter DOA15MUX = "DOA15";
parameter DOA14MUX = "DOA14";
parameter DOA13MUX = "DOA13";
parameter DOA12MUX = "DOA12";
parameter DOA11MUX = "DOA11";
parameter DOA10MUX = "DOA10";
parameter DOA9MUX = "DOA9";
parameter DOA8MUX = "DOA8";
parameter DOA7MUX = "DOA7";
parameter DOA6MUX = "DOA6";
parameter DOA5MUX = "DOA5";
parameter DOA4MUX = "DOA4";
parameter DOA3MUX = "DOA3";
parameter DOA2MUX = "DOA2";
parameter DOA1MUX = "DOA1";
parameter DOA0MUX = "DOA0";
parameter DIB17MUX = "DIB17";
parameter DIB16MUX = "DIB16";
parameter DIB15MUX = "DIB15";
parameter DIB14MUX = "DIB14";
parameter DIB13MUX = "DIB13";
parameter DIB12MUX = "DIB12";
parameter DIB11MUX = "DIB11";
parameter DIB10MUX = "DIB10";
parameter DIB9MUX = "DIB9";
parameter DIB8MUX = "DIB8";
parameter DIB7MUX = "DIB7";
parameter DIB6MUX = "DIB6";
parameter DIB5MUX = "DIB5";
parameter DIB4MUX = "DIB4";
parameter DIB3MUX = "DIB3";
parameter DIB2MUX = "DIB2";
parameter DIB1MUX = "DIB1";
parameter DIB0MUX = "DIB0";
parameter ADB13MUX = "ADB13";
parameter ADB12MUX = "ADB12";
parameter ADB11MUX = "ADB11";
parameter ADB10MUX = "ADB10";
parameter ADB9MUX = "ADB9";
parameter ADB8MUX = "ADB8";
parameter ADB7MUX = "ADB7";
parameter ADB6MUX = "ADB6";
parameter ADB5MUX = "ADB5";
parameter ADB4MUX = "ADB4";
parameter ADB3MUX = "ADB3";
parameter ADB2MUX = "ADB2";
parameter ADB1MUX = "ADB1";
parameter ADB0MUX = "ADB0";
parameter CEBMUX = "CEB";
parameter OCEBMUX = "OCEB";
parameter CLKBMUX = "CLKB";
parameter WEBMUX = "WEB";
parameter RSTBMUX = "RSTB";
parameter CSB2MUX = "CSB2";
parameter CSB1MUX = "CSB1";
parameter CSB0MUX = "CSB0";
parameter DOB17MUX = "DOB17";
parameter DOB16MUX = "DOB16";
parameter DOB15MUX = "DOB15";
parameter DOB14MUX = "DOB14";
parameter DOB13MUX = "DOB13";
parameter DOB12MUX = "DOB12";
parameter DOB11MUX = "DOB11";
parameter DOB10MUX = "DOB10";
parameter DOB9MUX = "DOB9";
parameter DOB8MUX = "DOB8";
parameter DOB7MUX = "DOB7";
parameter DOB6MUX = "DOB6";
parameter DOB5MUX = "DOB5";
parameter DOB4MUX = "DOB4";
parameter DOB3MUX = "DOB3";
parameter DOB2MUX = "DOB2";
parameter DOB1MUX = "DOB1";
parameter DOB0MUX = "DOB0";
parameter WID = 0;
parameter GSR = "ENABLED";
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_DATA = "STATIC";
endmodule
`ifndef NO_INCLUDES
`include "cells_ff.vh"
`include "cells_io.vh"
`endif

View File

@ -1,17 +0,0 @@
module \$__MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_WIDTH = 18;
parameter B_WIDTH = 18;
parameter Y_WIDTH = 36;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
MULT18X18D _TECHMAP_REPLACE_ (
.A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .A4(A[4]), .A5(A[5]), .A6(A[6]), .A7(A[7]), .A8(A[8]), .A9(A[9]), .A10(A[10]), .A11(A[11]), .A12(A[12]), .A13(A[13]), .A14(A[14]), .A15(A[15]), .A16(A[16]), .A17(A[17]),
.B0(B[0]), .B1(B[1]), .B2(B[2]), .B3(B[3]), .B4(B[4]), .B5(B[5]), .B6(B[6]), .B7(B[7]), .B8(B[8]), .B9(B[9]), .B10(B[10]), .B11(B[11]), .B12(B[12]), .B13(B[13]), .B14(B[14]), .B15(B[15]), .B16(B[16]), .B17(B[17]),
.C17(1'b0), .C16(1'b0), .C15(1'b0), .C14(1'b0), .C13(1'b0), .C12(1'b0), .C11(1'b0), .C10(1'b0), .C9(1'b0), .C8(1'b0), .C7(1'b0), .C6(1'b0), .C5(1'b0), .C4(1'b0), .C3(1'b0), .C2(1'b0), .C1(1'b0), .C0(1'b0),
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0), .SIGNEDB(B_SIGNED ? 1'b1 : 1'b0), .SOURCEA(1'b0), .SOURCEB(1'b0),
.P0(Y[0]), .P1(Y[1]), .P2(Y[2]), .P3(Y[3]), .P4(Y[4]), .P5(Y[5]), .P6(Y[6]), .P7(Y[7]), .P8(Y[8]), .P9(Y[9]), .P10(Y[10]), .P11(Y[11]), .P12(Y[12]), .P13(Y[13]), .P14(Y[14]), .P15(Y[15]), .P16(Y[16]), .P17(Y[17]), .P18(Y[18]), .P19(Y[19]), .P20(Y[20]), .P21(Y[21]), .P22(Y[22]), .P23(Y[23]), .P24(Y[24]), .P25(Y[25]), .P26(Y[26]), .P27(Y[27]), .P28(Y[28]), .P29(Y[29]), .P30(Y[30]), .P31(Y[31]), .P32(Y[32]), .P33(Y[33]), .P34(Y[34]), .P35(Y[35])
);
endmodule

View File

@ -1,11 +0,0 @@
module \$_DLATCH_N_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = !E ? D : Q;
endmodule
module \$_DLATCH_P_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = E ? D : Q;
endmodule

View File

@ -1,457 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SynthEcp5Pass : public ScriptPass
{
SynthEcp5Pass() : ScriptPass("synth_ecp5", "synthesis for ECP5 FPGAs") { }
void on_register() override
{
RTLIL::constpad["synth_ecp5.abc9.W"] = "300";
}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_ecp5 [options]\n");
log("\n");
log("This command runs synthesis for ECP5 FPGAs.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
log(" -blif <file>\n");
log(" write the design to the specified BLIF file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -edif <file>\n");
log(" write the design to the specified EDIF file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -json <file>\n");
log(" write the design to the specified JSON file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
log(" -noflatten\n");
log(" do not flatten design before synthesis\n");
log("\n");
log(" -dff\n");
log(" run 'abc'/'abc9' with -dff option\n");
log("\n");
log(" -retime\n");
log(" run 'abc' with '-dff -D 1' options\n");
log("\n");
log(" -noccu2\n");
log(" do not use CCU2 cells in output netlist\n");
log("\n");
log(" -nodffe\n");
log(" do not use flipflops with CE in output netlist\n");
log("\n");
log(" -nobram\n");
log(" do not use block RAM cells in output netlist\n");
log("\n");
log(" -nolutram\n");
log(" do not use LUT RAM cells in output netlist\n");
log("\n");
log(" -nowidelut\n");
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -asyncprld\n");
log(" use async PRLD mode to implement ALDFF (EXPERIMENTAL)\n");
log("\n");
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
log("\n");
log(" -noabc9\n");
log(" disable use of new ABC9 flow\n");
log("\n");
log(" -vpr\n");
log(" generate an output netlist (and BLIF file) suitable for VPR\n");
log(" (this feature is experimental and incomplete)\n");
log("\n");
log(" -iopad\n");
log(" insert IO buffers\n");
log("\n");
log(" -nodsp\n");
log(" do not map multipliers to MULT18X18D\n");
log("\n");
log(" -no-rw-check\n");
log(" marks all recognized read ports as \"return don't-care value on\n");
log(" read/write collision\" (same result as setting the no_rw_check\n");
log(" attribute on all memories).\n");
log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_opt, blif_file, edif_file, json_file;
bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, iopad, nodsp, vpr, no_rw_check;
void clear_flags() override
{
top_opt = "-auto-top";
blif_file = "";
edif_file = "";
json_file = "";
noccu2 = false;
nodffe = false;
nobram = false;
nolutram = false;
nowidelut = false;
asyncprld = false;
flatten = true;
dff = false;
retime = false;
abc2 = false;
vpr = false;
abc9 = true;
iopad = false;
nodsp = false;
no_rw_check = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
string run_from, run_to;
clear_flags();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-top" && argidx+1 < args.size()) {
top_opt = "-top " + args[++argidx];
continue;
}
if (args[argidx] == "-blif" && argidx+1 < args.size()) {
blif_file = args[++argidx];
continue;
}
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
edif_file = args[++argidx];
continue;
}
if (args[argidx] == "-json" && argidx+1 < args.size()) {
json_file = args[++argidx];
continue;
}
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
break;
run_from = args[++argidx].substr(0, pos);
run_to = args[argidx].substr(pos+1);
continue;
}
if (args[argidx] == "-flatten") {
flatten = true;
continue;
}
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
}
if (args[argidx] == "-dff") {
dff = true;
continue;
}
if (args[argidx] == "-retime") {
retime = true;
continue;
}
if (args[argidx] == "-noccu2") {
noccu2 = true;
continue;
}
if (args[argidx] == "-nodffe") {
nodffe = true;
continue;
}
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
if (args[argidx] == "-asyncprld") {
asyncprld = true;
continue;
}
if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
nolutram = true;
continue;
}
if (args[argidx] == "-nowidelut" || /*deprecated alias*/ args[argidx] == "-nomux") {
nowidelut = true;
continue;
}
if (args[argidx] == "-abc2") {
abc2 = true;
continue;
}
if (args[argidx] == "-vpr") {
vpr = true;
continue;
}
if (args[argidx] == "-abc9") {
// removed, ABC9 is on by default.
continue;
}
if (args[argidx] == "-noabc9") {
abc9 = false;
continue;
}
if (args[argidx] == "-iopad") {
iopad = true;
continue;
}
if (args[argidx] == "-nodsp") {
nodsp = true;
continue;
}
if (args[argidx] == "-no-rw-check") {
no_rw_check = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
if (abc9 && retime)
log_cmd_error("-retime option not currently compatible with -abc9!\n");
log_header(design, "Executing SYNTH_ECP5 pass.\n");
log_push();
run_script(design, run_from, run_to);
log_pop();
}
void script() override
{
std::string no_rw_check_opt = "";
if (no_rw_check)
no_rw_check_opt = " -no-rw-check";
if (help_mode)
no_rw_check_opt = " [-no-rw-check]";
if (check_label("begin"))
{
run("read_verilog -lib -specify +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt));
}
if (check_label("coarse"))
{
run("proc");
if (flatten || help_mode)
run("flatten");
run("tribuf -logic");
run("deminout");
run("opt_expr");
run("opt_clean");
run("check");
run("opt -nodffe -nosdff");
run("fsm");
run("opt");
run("wreduce");
run("peepopt");
run("opt_clean");
run("share");
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
run("opt_expr");
run("opt_clean");
if (!nodsp) {
run("techmap -map +/mul2dsp.v -map +/ecp5/dsp_map.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)");
run("chtype -set $mul t:$__soft_mul", "(unless -nodsp)");
}
run("alumacc");
run("opt");
run("memory -nomap" + no_rw_check_opt);
run("opt_clean");
}
if (check_label("map_ram"))
{
std::string args = "";
if (help_mode)
args += " [-no-auto-block] [-no-auto-distributed]";
else {
if (nobram)
args += " -no-auto-block";
if (nolutram)
args += " -no-auto-distributed";
}
run("memory_libmap -lib +/ecp5/lutrams.txt -lib +/ecp5/brams.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/ecp5/lutrams_map.v -map +/ecp5/brams_map.v");
}
if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
}
if (check_label("map_gates"))
{
if (noccu2)
run("techmap");
else
run("techmap -map +/techmap.v -map +/ecp5/arith_map.v");
if (help_mode || iopad) {
run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad OBZ ~T:I:O -tinoutpad BB ~T:O:I:B A:top", "(only if '-iopad')");
run("attrmvcp -attr src -attr LOC t:OB %x:+[O] t:OBZ %x:+[O] t:BB %x:+[B]");
run("attrmvcp -attr src -attr LOC -driven t:IB %x:+[I]");
}
run("opt -fast");
if (retime || help_mode)
run("abc -dff -D 1", "(only if -retime)");
}
if (check_label("map_ffs"))
{
run("opt_clean");
std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
}
if (help_mode) {
dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
} else if (asyncprld) {
dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
} else {
dfflegalize_args += " -cell $_DLATCH_?_ x";
}
run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)");
if ((abc9 && dff) || help_mode)
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff)");
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
run("opt_expr -undriven -mux_undef");
run("simplemap");
run("lattice_gsr");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
}
if (check_label("map_luts"))
{
if (abc2 || help_mode)
run("abc", " (only if -abc2)");
if (!asyncprld || help_mode)
run("techmap -map +/ecp5/latches_map.v", "(skip if -asyncprld)");
if (abc9) {
std::string abc9_opts;
if (nowidelut)
abc9_opts += " -maxlut 4";
std::string k = "synth_ecp5.abc9.W";
if (active_design && active_design->scratchpad.count(k))
abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k));
else
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k));
if (nowidelut)
abc9_opts += " -maxlut 4";
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
} else {
std::string abc_args = " -dress";
if (nowidelut)
abc_args += " -lut 4";
else
abc_args += " -lut 4:7";
if (dff)
abc_args += " -dff";
run("abc" + abc_args);
}
run("clean");
}
if (check_label("map_cells"))
{
if (help_mode)
run("techmap -map +/ecp5/cells_map.v", "(skip if -vpr)");
else if (!vpr)
run("techmap -map +/ecp5/cells_map.v");
run("opt_lut_ins -tech lattice");
run("clean");
}
if (check_label("check"))
{
run("autoname");
run("hierarchy -check");
run("stat");
run("check -noinit");
run("blackbox =A:whitebox");
}
if (check_label("blif"))
{
if (!blif_file.empty() || help_mode) {
if (vpr || help_mode) {
run(stringf("opt_clean -purge"),
" (vpr mode)");
run(stringf("write_blif -attr -cname -conn -param %s",
help_mode ? "<file-name>" : blif_file.c_str()),
" (vpr mode)");
}
if (!vpr)
run(stringf("write_blif -gates -attr -param %s",
help_mode ? "<file-name>" : blif_file.c_str()),
" (non-vpr mode)");
}
}
if (check_label("edif"))
{
if (!edif_file.empty() || help_mode)
run(stringf("write_edif %s", help_mode ? "<file-name>" : edif_file));
}
if (check_label("json"))
{
if (!json_file.empty() || help_mode)
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file));
}
}
} SynthEcp5Pass;
PRIVATE_NAMESPACE_END

View File

@ -8,6 +8,7 @@ $(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_xtra_gw2a.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_xtra_gw5a.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/arith_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams_map_gw5a.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/brams.txt))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams_map.v))
$(eval $(call add_share_file,share/gowin,techlibs/gowin/lutrams.txt))

View File

@ -0,0 +1,399 @@
`define DEF_FUNCS \
function [255:0] init_slice_x8; \
input integer idx; \
integer i; \
for (i = 0; i < 32; i = i + 1) begin \
init_slice_x8[i*8+:8] = INIT[(idx * 32 + i) * 9+:8]; \
end \
endfunction \
function [287:0] init_slice_x9; \
input integer idx; \
init_slice_x9 = INIT[idx * 288+:288]; \
endfunction \
`define x8_width(width) (width / 9 * 8 + width % 9)
`define x8_rd_data(data) {1'bx, data[31:24], 1'bx, data[23:16], 1'bx, data[15:8], 1'bx, data[7:0]}
`define x8_wr_data(data) {data[34:27], data[25:18], data[16:9], data[7:0]}
`define addrbe_always(width, addr) (width < 18 ? addr : width == 18 ? {addr[13:4], 4'b0011} : {addr[13:5], 5'b01111})
`define INIT(func) \
.INIT_RAM_00(func('h00)), \
.INIT_RAM_01(func('h01)), \
.INIT_RAM_02(func('h02)), \
.INIT_RAM_03(func('h03)), \
.INIT_RAM_04(func('h04)), \
.INIT_RAM_05(func('h05)), \
.INIT_RAM_06(func('h06)), \
.INIT_RAM_07(func('h07)), \
.INIT_RAM_08(func('h08)), \
.INIT_RAM_09(func('h09)), \
.INIT_RAM_0A(func('h0a)), \
.INIT_RAM_0B(func('h0b)), \
.INIT_RAM_0C(func('h0c)), \
.INIT_RAM_0D(func('h0d)), \
.INIT_RAM_0E(func('h0e)), \
.INIT_RAM_0F(func('h0f)), \
.INIT_RAM_10(func('h10)), \
.INIT_RAM_11(func('h11)), \
.INIT_RAM_12(func('h12)), \
.INIT_RAM_13(func('h13)), \
.INIT_RAM_14(func('h14)), \
.INIT_RAM_15(func('h15)), \
.INIT_RAM_16(func('h16)), \
.INIT_RAM_17(func('h17)), \
.INIT_RAM_18(func('h18)), \
.INIT_RAM_19(func('h19)), \
.INIT_RAM_1A(func('h1a)), \
.INIT_RAM_1B(func('h1b)), \
.INIT_RAM_1C(func('h1c)), \
.INIT_RAM_1D(func('h1d)), \
.INIT_RAM_1E(func('h1e)), \
.INIT_RAM_1F(func('h1f)), \
.INIT_RAM_20(func('h20)), \
.INIT_RAM_21(func('h21)), \
.INIT_RAM_22(func('h22)), \
.INIT_RAM_23(func('h23)), \
.INIT_RAM_24(func('h24)), \
.INIT_RAM_25(func('h25)), \
.INIT_RAM_26(func('h26)), \
.INIT_RAM_27(func('h27)), \
.INIT_RAM_28(func('h28)), \
.INIT_RAM_29(func('h29)), \
.INIT_RAM_2A(func('h2a)), \
.INIT_RAM_2B(func('h2b)), \
.INIT_RAM_2C(func('h2c)), \
.INIT_RAM_2D(func('h2d)), \
.INIT_RAM_2E(func('h2e)), \
.INIT_RAM_2F(func('h2f)), \
.INIT_RAM_30(func('h30)), \
.INIT_RAM_31(func('h31)), \
.INIT_RAM_32(func('h32)), \
.INIT_RAM_33(func('h33)), \
.INIT_RAM_34(func('h34)), \
.INIT_RAM_35(func('h35)), \
.INIT_RAM_36(func('h36)), \
.INIT_RAM_37(func('h37)), \
.INIT_RAM_38(func('h38)), \
.INIT_RAM_39(func('h39)), \
.INIT_RAM_3A(func('h3a)), \
.INIT_RAM_3B(func('h3b)), \
.INIT_RAM_3C(func('h3c)), \
.INIT_RAM_3D(func('h3d)), \
.INIT_RAM_3E(func('h3e)), \
.INIT_RAM_3F(func('h3f)),
module $__GOWIN_SP_ (...);
parameter INIT = 0;
parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_A_WIDTH = 36;
parameter PORT_A_OPTION_WRITE_MODE = 0;
input PORT_A_CLK;
input PORT_A_CLK_EN;
input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
`DEF_FUNCS
wire RST = OPTION_RESET_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST;
wire [13:0] AD = `addrbe_always(PORT_A_WIDTH, PORT_A_ADDR);
generate
if (PORT_A_WIDTH < 9) begin
wire [31:0] DI = `x8_wr_data(PORT_A_WR_DATA);
wire [31:0] DO;
assign PORT_A_RD_DATA = `x8_rd_data(DO);
SP #(
`INIT(init_slice_x8)
.READ_MODE(1'b0),
.WRITE_MODE(PORT_A_OPTION_WRITE_MODE),
.BIT_WIDTH(`x8_width(PORT_A_WIDTH)),
.BLK_SEL(3'b000),
.RESET_MODE(OPTION_RESET_MODE),
) _TECHMAP_REPLACE_ (
.BLKSEL(3'b000),
.CLK(PORT_A_CLK),
.CE(PORT_A_CLK_EN),
.WRE(PORT_A_WR_EN),
.RESET(RST),
.OCE(1'b1),
.AD(AD),
.DI(DI),
.DO(DO),
);
end else begin
wire [35:0] DI = PORT_A_WR_DATA;
wire [35:0] DO;
assign PORT_A_RD_DATA = DO;
SPX9 #(
`INIT(init_slice_x9)
.READ_MODE(1'b0),
.WRITE_MODE(PORT_A_OPTION_WRITE_MODE),
.BIT_WIDTH(PORT_A_WIDTH),
.BLK_SEL(3'b000),
.RESET_MODE(OPTION_RESET_MODE),
) _TECHMAP_REPLACE_ (
.BLKSEL(3'b000),
.CLK(PORT_A_CLK),
.CE(PORT_A_CLK_EN),
.WRE(PORT_A_WR_EN),
.RESET(RST),
.OCE(1'b1),
.AD(AD),
.DI(DI),
.DO(DO),
);
end
endgenerate
endmodule
module $__GOWIN_DP_ (...);
parameter INIT = 0;
parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_A_WIDTH = 18;
parameter PORT_A_OPTION_WRITE_MODE = 0;
parameter PORT_B_WIDTH = 18;
parameter PORT_B_OPTION_WRITE_MODE = 0;
input PORT_A_CLK;
input PORT_A_CLK_EN;
input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
input PORT_B_CLK;
input PORT_B_CLK_EN;
input PORT_B_WR_EN;
input PORT_B_RD_SRST;
input PORT_B_RD_ARST;
input [13:0] PORT_B_ADDR;
input [PORT_A_WIDTH-1:0] PORT_B_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_B_RD_DATA;
`DEF_FUNCS
wire RSTA = OPTION_RESET_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST;
wire RSTB = OPTION_RESET_MODE == "SYNC" ? PORT_B_RD_SRST : PORT_B_RD_ARST;
wire [13:0] ADA = `addrbe_always(PORT_A_WIDTH, PORT_A_ADDR);
wire [13:0] ADB = `addrbe_always(PORT_B_WIDTH, PORT_B_ADDR);
generate
if (PORT_A_WIDTH < 9 || PORT_B_WIDTH < 9) begin
wire [15:0] DIA = `x8_wr_data(PORT_A_WR_DATA);
wire [15:0] DIB = `x8_wr_data(PORT_B_WR_DATA);
wire [15:0] DOA;
wire [15:0] DOB;
assign PORT_A_RD_DATA = `x8_rd_data(DOA);
assign PORT_B_RD_DATA = `x8_rd_data(DOB);
DPB #(
`INIT(init_slice_x8)
.READ_MODE0(1'b0),
.READ_MODE1(1'b0),
.WRITE_MODE0(PORT_A_OPTION_WRITE_MODE),
.WRITE_MODE1(PORT_B_OPTION_WRITE_MODE),
.BIT_WIDTH_0(`x8_width(PORT_A_WIDTH)),
.BIT_WIDTH_1(`x8_width(PORT_B_WIDTH)),
.BLK_SEL_0(3'b000),
.BLK_SEL_1(3'b000),
.RESET_MODE(OPTION_RESET_MODE),
) _TECHMAP_REPLACE_ (
.BLKSELA(3'b000),
.BLKSELB(3'b000),
.CLKA(PORT_A_CLK),
.CEA(PORT_A_CLK_EN),
.WREA(PORT_A_WR_EN),
.RESETA(RSTA),
.OCEA(1'b1),
.ADA(ADA),
.DIA(DIA),
.DOA(DOA),
.CLKB(PORT_B_CLK),
.CEB(PORT_B_CLK_EN),
.WREB(PORT_B_WR_EN),
.RESETB(RSTB),
.OCEB(1'b1),
.ADB(ADB),
.DIB(DIB),
.DOB(DOB),
);
end else begin
wire [17:0] DIA = PORT_A_WR_DATA;
wire [17:0] DIB = PORT_B_WR_DATA;
wire [17:0] DOA;
wire [17:0] DOB;
assign PORT_A_RD_DATA = DOA;
assign PORT_B_RD_DATA = DOB;
DPX9B #(
`INIT(init_slice_x9)
.READ_MODE0(1'b0),
.READ_MODE1(1'b0),
.WRITE_MODE0(PORT_A_OPTION_WRITE_MODE),
.WRITE_MODE1(PORT_B_OPTION_WRITE_MODE),
.BIT_WIDTH_0(PORT_A_WIDTH),
.BIT_WIDTH_1(PORT_B_WIDTH),
.BLK_SEL_0(3'b000),
.BLK_SEL_1(3'b000),
.RESET_MODE(OPTION_RESET_MODE),
) _TECHMAP_REPLACE_ (
.BLKSELA(3'b000),
.BLKSELB(3'b000),
.CLKA(PORT_A_CLK),
.CEA(PORT_A_CLK_EN),
.WREA(PORT_A_WR_EN),
.RESETA(RSTA),
.OCEA(1'b1),
.ADA(ADA),
.DIA(DIA),
.DOA(DOA),
.CLKB(PORT_B_CLK),
.CEB(PORT_B_CLK_EN),
.WREB(PORT_B_WR_EN),
.RESETB(RSTB),
.OCEB(1'b1),
.ADB(ADB),
.DIB(DIB),
.DOB(DOB),
);
end
endgenerate
endmodule
module $__GOWIN_SDP_ (...);
parameter INIT = 0;
parameter OPTION_RESET_MODE = "SYNC";
parameter PORT_R_WIDTH = 18;
parameter PORT_W_WIDTH = 18;
input PORT_R_CLK;
input PORT_R_CLK_EN;
input PORT_R_RD_SRST;
input PORT_R_RD_ARST;
input [13:0] PORT_R_ADDR;
output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;
input PORT_W_CLK;
input PORT_W_CLK_EN;
input PORT_W_WR_EN;
input [13:0] PORT_W_ADDR;
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
`DEF_FUNCS
wire RST = OPTION_RESET_MODE == "SYNC" ? PORT_R_RD_SRST : PORT_R_RD_ARST;
wire [13:0] ADW = `addrbe_always(PORT_W_WIDTH, PORT_W_ADDR);
wire WRE = PORT_W_CLK_EN & PORT_W_WR_EN;
generate
if (PORT_W_WIDTH < 9 || PORT_R_WIDTH < 9) begin
wire [31:0] DI = `x8_wr_data(PORT_W_WR_DATA);
wire [31:0] DO;
assign PORT_R_RD_DATA = `x8_rd_data(DO);
SDPB #(
`INIT(init_slice_x8)
.READ_MODE(1'b0),
.BIT_WIDTH_0(`x8_width(PORT_W_WIDTH)),
.BIT_WIDTH_1(`x8_width(PORT_R_WIDTH)),
.BLK_SEL_0(3'b000),
.BLK_SEL_1(3'b000),
.RESET_MODE(OPTION_RESET_MODE),
) _TECHMAP_REPLACE_ (
.BLKSELA(3'b000),
.BLKSELB(3'b000),
.CLKA(PORT_W_CLK),
.CEA(WRE),
.ADA(ADW),
.DI(DI),
.CLKB(PORT_R_CLK),
.CEB(PORT_R_CLK_EN),
.RESET(RST),
.OCE(1'b1),
.ADB(PORT_R_ADDR),
.DO(DO),
);
end else begin
wire [35:0] DI = PORT_W_WR_DATA;
wire [35:0] DO;
assign PORT_R_RD_DATA = DO;
SDPX9B #(
`INIT(init_slice_x9)
.READ_MODE(1'b0),
.BIT_WIDTH_0(PORT_W_WIDTH),
.BIT_WIDTH_1(PORT_R_WIDTH),
.BLK_SEL_0(3'b000),
.BLK_SEL_1(3'b000),
.RESET_MODE(OPTION_RESET_MODE),
) _TECHMAP_REPLACE_ (
.BLKSELA(3'b000),
.BLKSELB(3'b000),
.CLKA(PORT_W_CLK),
.CEA(WRE),
.ADA(ADW),
.DI(DI),
.CLKB(PORT_R_CLK),
.CEB(PORT_R_CLK_EN),
.RESET(RST),
.OCE(1'b1),
.ADB(PORT_R_ADDR),
.DO(DO),
);
end
endgenerate
endmodule

View File

@ -57,6 +57,9 @@ struct SynthGowinPass : public ScriptPass
log(" -nodffe\n");
log(" do not use flipflops with CE in output netlist\n");
log("\n");
log(" -strict-gw5a-dffs\n");
log(" use only DFFSE/DFFRE/DFFPE/DFFCE flipflops for the GW5A family\n");
log("\n");
log(" -nobram\n");
log(" do not use BRAM cells in output netlist\n");
log("\n");
@ -91,13 +94,16 @@ struct SynthGowinPass : public ScriptPass
log(" The following families are supported:\n");
log(" 'gw1n', 'gw2a', 'gw5a'.\n");
log("\n");
log(" -setundef\n");
log(" set undriven wires and parameters to zero\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_opt, vout_file, json_file, family;
bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads, noalu, no_rw_check;
bool retime, nobram, nolutram, flatten, nodffe, strict_gw5a_dffs, nowidelut, abc9, noiopads, noalu, no_rw_check, setundef;
void clear_flags() override
{
@ -109,12 +115,14 @@ struct SynthGowinPass : public ScriptPass
flatten = true;
nobram = false;
nodffe = false;
strict_gw5a_dffs = false;
nolutram = false;
nowidelut = false;
abc9 = true;
noiopads = false;
noalu = false;
no_rw_check = false;
setundef = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@ -165,6 +173,10 @@ struct SynthGowinPass : public ScriptPass
nodffe = true;
continue;
}
if (args[argidx] == "-strict-gw5a-dffs") {
strict_gw5a_dffs = true;
continue;
}
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
@ -193,6 +205,10 @@ struct SynthGowinPass : public ScriptPass
no_rw_check = true;
continue;
}
if (args[argidx] == "-setundef") {
setundef = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -248,7 +264,7 @@ struct SynthGowinPass : public ScriptPass
args += " -no-auto-distributed";
}
run("memory_libmap -lib +/gowin/lutrams.txt -lib +/gowin/brams.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/gowin/lutrams_map.v -map +/gowin/brams_map.v");
run(stringf("techmap -map +/gowin/lutrams_map.v -map +/gowin/brams_map%s.v", family == "gw5a" ? "_gw5a" : ""));
}
if (check_label("map_ffram"))
@ -276,10 +292,18 @@ struct SynthGowinPass : public ScriptPass
if (check_label("map_ffs"))
{
run("opt_clean");
if (nodffe)
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFF_?P?_ r -cell $_DFF_?P?_ r");
else
run("dfflegalize -cell $_DFF_?_ 0 -cell $_DFFE_?P_ 0 -cell $_SDFF_?P?_ r -cell $_SDFFE_?P?P_ r -cell $_DFF_?P?_ r -cell $_DFFE_?P?P_ r");
if (family == "gw5a") {
if (strict_gw5a_dffs) {
run("dfflegalize -cell $_SDFFE_PP?P_ r -cell $_DFFE_PP?P_ r");
} else {
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFFE_PP?P_ r -cell $_DFFE_PP?P_ r");
}
} else {
if (nodffe)
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFF_?P?_ r -cell $_DFF_?P?_ r");
else
run("dfflegalize -cell $_DFF_?_ 0 -cell $_DFFE_?P_ 0 -cell $_SDFF_?P?_ r -cell $_SDFFE_?P?P_ r -cell $_DFF_?P?_ r -cell $_DFFE_?P?P_ r");
}
run("techmap -map +/gowin/cells_map.v");
run("opt_expr -mux_undef");
run("simplemap");
@ -305,10 +329,11 @@ struct SynthGowinPass : public ScriptPass
{
run("techmap -map +/gowin/cells_map.v");
run("opt_lut_ins -tech gowin");
run("setundef -undriven -params -zero");
if (setundef || help_mode)
run("setundef -undriven -params -zero", "(only if -setundef)");
run("hilomap -singleton -hicell VCC V -locell GND G");
if (!vout_file.empty() || help_mode) // vendor output requires 1-bit wires
run("splitnets -ports", "(only if -vout used)");
run("splitnets -ports", "(only if -vout)");
run("clean");
run("autoname");
}

View File

@ -4,25 +4,49 @@ OBJS += techlibs/lattice/lattice_gsr.o
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_ff.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_io.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map_trellis.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/common_sim.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/parse_init.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/ccu2d_sim.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/ccu2c_sim.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_ecp5.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo2.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo3.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo3d.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_ecp5.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo2.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo3.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo3d.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map_trellis.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_trellis.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_nexus.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lrams_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lrams_nexus.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_16kd.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_16kd.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_8kc.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_8kc.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_nexus.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_ccu2c.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_ccu2d.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/latches_map.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/dsp_map_18x18.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/dsp_map_nexus.v))
$(eval $(call add_share_file,share/ecp5,techlibs/lattice/cells_ff.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/lattice/cells_io.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/lattice/common_sim.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/lattice/ccu2c_sim.vh))
$(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_sim_ecp5.v,cells_sim.v))
$(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_bb_ecp5.v,cells_bb.v))
$(eval $(call add_share_file,share/nexus,techlibs/lattice/parse_init.vh))
$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_sim_nexus.v,cells_sim.v))
$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_bb_nexus.v,cells_xtra.v))

View File

@ -17,204 +17,6 @@ module SGSR (...);
input CLK;
endmodule
(* blackbox *)
module DP16KD (...);
parameter CLKAMUX = "CLKA";
parameter CLKBMUX = "CLKB";
parameter DATA_WIDTH_A = 18;
parameter DATA_WIDTH_B = 18;
parameter REGMODE_A = "NOREG";
parameter REGMODE_B = "NOREG";
parameter RESETMODE = "SYNC";
parameter ASYNC_RESET_RELEASE = "SYNC";
parameter WRITEMODE_A = "NORMAL";
parameter WRITEMODE_B = "NORMAL";
parameter CSDECODE_A = "0b000";
parameter CSDECODE_B = "0b000";
parameter GSR = "ENABLED";
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_DATA = "STATIC";
input DIA17;
input DIA16;
input DIA15;
input DIA14;
input DIA13;
input DIA12;
input DIA11;
input DIA10;
input DIA9;
input DIA8;
input DIA7;
input DIA6;
input DIA5;
input DIA4;
input DIA3;
input DIA2;
input DIA1;
input DIA0;
input ADA13;
input ADA12;
input ADA11;
input ADA10;
input ADA9;
input ADA8;
input ADA7;
input ADA6;
input ADA5;
input ADA4;
input ADA3;
input ADA2;
input ADA1;
input ADA0;
input CEA;
input OCEA;
input CLKA;
input WEA;
input CSA2;
input CSA1;
input CSA0;
input RSTA;
input DIB17;
input DIB16;
input DIB15;
input DIB14;
input DIB13;
input DIB12;
input DIB11;
input DIB10;
input DIB9;
input DIB8;
input DIB7;
input DIB6;
input DIB5;
input DIB4;
input DIB3;
input DIB2;
input DIB1;
input DIB0;
input ADB13;
input ADB12;
input ADB11;
input ADB10;
input ADB9;
input ADB8;
input ADB7;
input ADB6;
input ADB5;
input ADB4;
input ADB3;
input ADB2;
input ADB1;
input ADB0;
input CEB;
input OCEB;
input CLKB;
input WEB;
input CSB2;
input CSB1;
input CSB0;
input RSTB;
output DOA17;
output DOA16;
output DOA15;
output DOA14;
output DOA13;
output DOA12;
output DOA11;
output DOA10;
output DOA9;
output DOA8;
output DOA7;
output DOA6;
output DOA5;
output DOA4;
output DOA3;
output DOA2;
output DOA1;
output DOA0;
output DOB17;
output DOB16;
output DOB15;
output DOB14;
output DOB13;
output DOB12;
output DOB11;
output DOB10;
output DOB9;
output DOB8;
output DOB7;
output DOB6;
output DOB5;
output DOB4;
output DOB3;
output DOB2;
output DOB1;
output DOB0;
endmodule
(* blackbox *)
module PDPW16KD (...);
parameter CLKRMUX = "CLKR";

View File

@ -1,191 +0,0 @@
module \$_DFF_N_ (input D, C, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
else
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
endgenerate
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
endmodule
module \$_DFF_P_ (input D, C, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
else
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(1'b0), .DI(D), .Q(Q));
endgenerate
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
endmodule
module \$_DFFE_NN_ (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
else
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
endgenerate
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
endmodule
module \$_DFFE_PN_ (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
else
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
endgenerate
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
endmodule
module \$_DFFE_NP_ (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
else
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
endgenerate
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
endmodule
module \$_DFFE_PP_ (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
else
TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q));
endgenerate
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
endmodule
module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_NP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_NP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_PP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_DFFE_PP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_NP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_NP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_NP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_NP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_PP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_PP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_ALDFF_NP_ (input C, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
module \$_ALDFF_PP_ (input C, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
module \$_ALDFFE_NPN_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
module \$_ALDFFE_NPP_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
module \$_ALDFFE_PPN_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
module \$_ALDFFE_PPP_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
`include "cells_ff.vh"
`include "cells_io.vh"
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
(* force_downto *)
input [WIDTH-1:0] A;
output Y;
generate
if (WIDTH == 1) begin
localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}};
LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y),
.A(1'b0), .B(1'b0), .C(1'b0), .D(A[0]));
end else
if (WIDTH == 2) begin
localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}};
LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y),
.A(1'b0), .B(1'b0), .C(A[0]), .D(A[1]));
end else
if (WIDTH == 3) begin
localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}};
LUT4 #(.INIT(INIT)) _TECHMAP_REPLACE_ (.Z(Y),
.A(1'b0), .B(A[0]), .C(A[1]), .D(A[2]));
end else
if (WIDTH == 4) begin
LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
`ifndef NO_PFUMUX
end else
if (WIDTH == 5) begin
wire f0, f1;
LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y));
end else
if (WIDTH == 6) begin
wire f0, f1, f2, f3, g0, g1;
LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y));
end else
if (WIDTH == 7) begin
wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1;
LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2));
PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3));
L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0));
L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1));
L6MUX21 mux7 (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y));
`endif
end else begin
wire _TECHMAP_FAIL_ = 1;
end
endgenerate
endmodule
`endif

View File

@ -1,6 +1,223 @@
`include "common_sim.vh"
`include "ccu2c_sim.vh"
(* blackbox *)
module DP16KD(
input DIA17, DIA16, DIA15, DIA14, DIA13, DIA12, DIA11, DIA10, DIA9, DIA8, DIA7, DIA6, DIA5, DIA4, DIA3, DIA2, DIA1, DIA0,
input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0,
input CEA, OCEA, CLKA, WEA, RSTA,
input CSA2, CSA1, CSA0,
output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0,
input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0,
input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0,
input CEB, OCEB, CLKB, WEB, RSTB,
input CSB2, CSB1, CSB0,
output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
);
parameter DATA_WIDTH_A = 18;
parameter DATA_WIDTH_B = 18;
parameter REGMODE_A = "NOREG";
parameter REGMODE_B = "NOREG";
parameter RESETMODE = "SYNC";
parameter ASYNC_RESET_RELEASE = "SYNC";
parameter CSDECODE_A = "0b000";
parameter CSDECODE_B = "0b000";
parameter WRITEMODE_A = "NORMAL";
parameter WRITEMODE_B = "NORMAL";
parameter DIA17MUX = "DIA17";
parameter DIA16MUX = "DIA16";
parameter DIA15MUX = "DIA15";
parameter DIA14MUX = "DIA14";
parameter DIA13MUX = "DIA13";
parameter DIA12MUX = "DIA12";
parameter DIA11MUX = "DIA11";
parameter DIA10MUX = "DIA10";
parameter DIA9MUX = "DIA9";
parameter DIA8MUX = "DIA8";
parameter DIA7MUX = "DIA7";
parameter DIA6MUX = "DIA6";
parameter DIA5MUX = "DIA5";
parameter DIA4MUX = "DIA4";
parameter DIA3MUX = "DIA3";
parameter DIA2MUX = "DIA2";
parameter DIA1MUX = "DIA1";
parameter DIA0MUX = "DIA0";
parameter ADA13MUX = "ADA13";
parameter ADA12MUX = "ADA12";
parameter ADA11MUX = "ADA11";
parameter ADA10MUX = "ADA10";
parameter ADA9MUX = "ADA9";
parameter ADA8MUX = "ADA8";
parameter ADA7MUX = "ADA7";
parameter ADA6MUX = "ADA6";
parameter ADA5MUX = "ADA5";
parameter ADA4MUX = "ADA4";
parameter ADA3MUX = "ADA3";
parameter ADA2MUX = "ADA2";
parameter ADA1MUX = "ADA1";
parameter ADA0MUX = "ADA0";
parameter CEAMUX = "CEA";
parameter OCEAMUX = "OCEA";
parameter CLKAMUX = "CLKA";
parameter WEAMUX = "WEA";
parameter RSTAMUX = "RSTA";
parameter CSA2MUX = "CSA2";
parameter CSA1MUX = "CSA1";
parameter CSA0MUX = "CSA0";
parameter DOA17MUX = "DOA17";
parameter DOA16MUX = "DOA16";
parameter DOA15MUX = "DOA15";
parameter DOA14MUX = "DOA14";
parameter DOA13MUX = "DOA13";
parameter DOA12MUX = "DOA12";
parameter DOA11MUX = "DOA11";
parameter DOA10MUX = "DOA10";
parameter DOA9MUX = "DOA9";
parameter DOA8MUX = "DOA8";
parameter DOA7MUX = "DOA7";
parameter DOA6MUX = "DOA6";
parameter DOA5MUX = "DOA5";
parameter DOA4MUX = "DOA4";
parameter DOA3MUX = "DOA3";
parameter DOA2MUX = "DOA2";
parameter DOA1MUX = "DOA1";
parameter DOA0MUX = "DOA0";
parameter DIB17MUX = "DIB17";
parameter DIB16MUX = "DIB16";
parameter DIB15MUX = "DIB15";
parameter DIB14MUX = "DIB14";
parameter DIB13MUX = "DIB13";
parameter DIB12MUX = "DIB12";
parameter DIB11MUX = "DIB11";
parameter DIB10MUX = "DIB10";
parameter DIB9MUX = "DIB9";
parameter DIB8MUX = "DIB8";
parameter DIB7MUX = "DIB7";
parameter DIB6MUX = "DIB6";
parameter DIB5MUX = "DIB5";
parameter DIB4MUX = "DIB4";
parameter DIB3MUX = "DIB3";
parameter DIB2MUX = "DIB2";
parameter DIB1MUX = "DIB1";
parameter DIB0MUX = "DIB0";
parameter ADB13MUX = "ADB13";
parameter ADB12MUX = "ADB12";
parameter ADB11MUX = "ADB11";
parameter ADB10MUX = "ADB10";
parameter ADB9MUX = "ADB9";
parameter ADB8MUX = "ADB8";
parameter ADB7MUX = "ADB7";
parameter ADB6MUX = "ADB6";
parameter ADB5MUX = "ADB5";
parameter ADB4MUX = "ADB4";
parameter ADB3MUX = "ADB3";
parameter ADB2MUX = "ADB2";
parameter ADB1MUX = "ADB1";
parameter ADB0MUX = "ADB0";
parameter CEBMUX = "CEB";
parameter OCEBMUX = "OCEB";
parameter CLKBMUX = "CLKB";
parameter WEBMUX = "WEB";
parameter RSTBMUX = "RSTB";
parameter CSB2MUX = "CSB2";
parameter CSB1MUX = "CSB1";
parameter CSB0MUX = "CSB0";
parameter DOB17MUX = "DOB17";
parameter DOB16MUX = "DOB16";
parameter DOB15MUX = "DOB15";
parameter DOB14MUX = "DOB14";
parameter DOB13MUX = "DOB13";
parameter DOB12MUX = "DOB12";
parameter DOB11MUX = "DOB11";
parameter DOB10MUX = "DOB10";
parameter DOB9MUX = "DOB9";
parameter DOB8MUX = "DOB8";
parameter DOB7MUX = "DOB7";
parameter DOB6MUX = "DOB6";
parameter DOB5MUX = "DOB5";
parameter DOB4MUX = "DOB4";
parameter DOB3MUX = "DOB3";
parameter DOB2MUX = "DOB2";
parameter DOB1MUX = "DOB1";
parameter DOB0MUX = "DOB0";
parameter WID = 0;
parameter GSR = "ENABLED";
parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
parameter INIT_DATA = "STATIC";
endmodule
`ifndef NO_INCLUDES
`include "cells_ff.vh"

View File

@ -121,12 +121,7 @@ devices = [
#Cell("XOR3"),
#Cell("XOR4"),
#Cell("XOR5"),
Cell("DP16KD", extra_params={
# Optional clock inverters, present in prjtrellis data but
# not in Diamond bb models.
"CLKAMUX": "CLKA",
"CLKBMUX": "CLKB",
}),
#Cell("DP16KD"),
Cell("PDPW16KD", extra_params={
# Optional clock inverters, present in prjtrellis data but
# not in Diamond bb models.

View File

@ -280,7 +280,7 @@ if __name__ == '__main__':
for device, cells in devices:
xtract_cells_decl(device, cells, dirs, out)
with open('cells_xtra.v', 'w') as f:
f.write('// Created by cells_xtra.py from Lattice models\n')
with open('cells_bb_nexus.v', 'w') as f:
f.write('// Created by cells_xtra_nexus.py from Lattice models\n')
f.write('\n')
f.write(out.getvalue())

View File

@ -324,7 +324,7 @@ module TRELLIS_IO(
);
parameter DIR = "INPUT";
reg T_pd;
always @(*) if (T === 1'bz) T_pd <= 1'b0; else T_pd <= T;
always @(*) if (T === 1'bz) T_pd = 1'b0; else T_pd = T;
generate
if (DIR == "INPUT") begin

View File

@ -1,12 +0,0 @@
ram distributed $__TRELLIS_DPR16X4_ {
abits 4;
width 4;
cost 4;
init any;
prune_rom;
port sw "W" {
clock anyedge;
}
port ar "R" {
}
}

View File

@ -1,30 +0,0 @@
module $__TRELLIS_DPR16X4_(...);
parameter INIT = 64'bx;
parameter PORT_W_CLK_POL = 1;
input PORT_W_CLK;
input [3:0] PORT_W_ADDR;
input [3:0] PORT_W_WR_DATA;
input PORT_W_WR_EN;
input [3:0] PORT_R_ADDR;
output [3:0] PORT_R_RD_DATA;
localparam WCKMUX = PORT_W_CLK_POL ? "WCK" : "INV";
TRELLIS_DPR16X4 #(
.INITVAL(INIT),
.WCKMUX(WCKMUX),
.WREMUX("WRE")
) _TECHMAP_REPLACE_ (
.RAD(PORT_R_ADDR),
.DO(PORT_R_RD_DATA),
.WAD(PORT_W_ADDR),
.DI(PORT_W_WR_DATA),
.WCK(PORT_W_CLK),
.WRE(PORT_W_WR_EN)
);
endmodule

View File

@ -35,13 +35,32 @@ struct SynthLatticePass : public ScriptPass
RTLIL::constpad["synth_lattice.abc9.W"] = "300";
}
struct DSPRule {
int a_maxwidth;
int b_maxwidth;
int a_minwidth;
int b_minwidth;
std::string prim;
};
const std::vector<DSPRule> dsp_rules_nexus = {
{36, 36, 22, 22, "$__NX_MUL36X36"},
{36, 18, 22, 10, "$__NX_MUL36X18"},
{18, 18, 10, 4, "$__NX_MUL18X18"},
{18, 18, 4, 10, "$__NX_MUL18X18"},
{ 9, 9, 4, 4, "$__NX_MUL9X9"},
};
const std::vector<DSPRule> dsp_rules_ecp5 = {
{18, 18, 2, 2, "$__MUL18X18"},
};
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_lattice [options]\n");
log("\n");
log("This command runs synthesis for Lattice FPGAs (excluding iCE40 and Nexus).\n");
log("This command runs synthesis for Lattice FPGAs (excluding iCE40).\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
@ -54,6 +73,8 @@ struct SynthLatticePass : public ScriptPass
log(" - xo2: MachXO2\n");
log(" - xo3: MachXO3L/LF\n");
log(" - xo3d: MachXO3D\n");
log(" - lifcl: CrossLink-NX\n");
log(" - lfd2nx: Certus-NX\n");
//log(" - xo: MachXO (EXPERIMENTAL)\n");
//log(" - pm: Platform Manager (EXPERIMENTAL)\n");
//log(" - pm2: Platform Manager 2 (EXPERIMENTAL)\n");
@ -113,14 +134,18 @@ struct SynthLatticePass : public ScriptPass
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
log("\n");
log(" -abc9\n");
log(" use new ABC9 flow (EXPERIMENTAL)\n");
log(" -noabc9\n");
log(" disable use of new ABC9 flow\n");
log("\n");
log(" -iopad\n");
log(" insert IO buffers\n");
log(" (by default enabled on Nexus FPGAs)\n");
log("\n");
log(" -noiopad\n");
log(" do not insert IO buffers\n");
log("\n");
log(" -nodsp\n");
log(" do not map multipliers to MULT18X18D\n");
log(" do not infer DSP multipliers\n");
log("\n");
log(" -no-rw-check\n");
log(" marks all recognized read ports as \"return don't-care value on\n");
@ -140,7 +165,9 @@ struct SynthLatticePass : public ScriptPass
string top_opt, edif_file, json_file, family;
bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, iopad, nodsp, no_rw_check, have_dsp;
bool cmp2softlogic;
string postfix, arith_map, brams_map, dsp_map;
string postfix, arith_map, brams_map, dsp_map, cells_map, map_ram_default, widelut_abc;
bool is_nexus;
std::vector<DSPRule> dsp_rules;
void clear_flags() override
{
@ -158,7 +185,7 @@ struct SynthLatticePass : public ScriptPass
dff = false;
retime = false;
abc2 = false;
abc9 = false;
abc9 = true;
iopad = false;
nodsp = false;
no_rw_check = false;
@ -168,12 +195,18 @@ struct SynthLatticePass : public ScriptPass
dsp_map = "";
have_dsp = false;
cmp2softlogic = false;
is_nexus = false;
map_ram_default = "";
cells_map = "";
widelut_abc = "4:7";
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
string run_from, run_to;
bool force_abc9 = false;
bool force_widelut = false;
bool force_iopad = false;
clear_flags();
size_t argidx;
@ -254,11 +287,23 @@ struct SynthLatticePass : public ScriptPass
continue;
}
if (args[argidx] == "-abc9") {
abc9 = true;
// removed, ABC9 is on by default.
force_abc9 = true;
continue;
}
if (args[argidx] == "-noabc9") {
force_abc9 = true;
abc9 = false;
continue;
}
if (args[argidx] == "-iopad") {
iopad = true;
force_iopad = true;
continue;
}
if (args[argidx] == "-noiopad") {
iopad = false;
force_iopad = true;
continue;
}
if (args[argidx] == "-nodsp") {
@ -285,7 +330,9 @@ struct SynthLatticePass : public ScriptPass
arith_map = "_ccu2c";
brams_map = "_16kd";
dsp_map = "_18x18";
dsp_rules = dsp_rules_ecp5;
have_dsp = true;
cells_map = "_trellis";
} else if (family == "xo2" ||
family == "xo3" ||
family == "xo3d" /* ||
@ -293,8 +340,24 @@ struct SynthLatticePass : public ScriptPass
postfix = "_" + family;
arith_map = "_ccu2d";
brams_map = "_8kc";
cells_map = "_trellis";
have_dsp = false;
if (!force_widelut) nowidelut = true;
if (!force_abc9) abc9 = false;
} else if (family == "lifcl" ||
family == "lfd2nx") {
is_nexus = true;
postfix = "_nexus";
arith_map = "_nexus";
brams_map = "_nexus";
dsp_map = "_nexus";
dsp_rules = dsp_rules_nexus;
have_dsp = true;
map_ram_default = " -no-auto-huge";
cells_map = "_nexus";
widelut_abc = "4:5";
if (!force_iopad) iopad = true;
if (!force_abc9) abc9 = false;
/* } else if (family == "xo" ||
family == "pm") {
} else if (family == "xp" ||
@ -358,9 +421,17 @@ struct SynthLatticePass : public ScriptPass
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
run("opt_expr");
run("opt_clean");
if (have_dsp && !nodsp) {
run("techmap -map +/mul2dsp.v -map +/lattice/dsp_map" + dsp_map + ".v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)");
run("chtype -set $mul t:$__soft_mul", "(unless -nodsp)");
if (help_mode) {
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
run("techmap -map +/lattice/dsp_map" + dsp_map + ".v", "(unless -nodsp)");
} else if (have_dsp && !nodsp) {
for (const auto &rule : dsp_rules) {
run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s",
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim));
run("chtype -set $mul t:$__soft_mul");
}
run("techmap -map +/lattice/dsp_map" + dsp_map + ".v");
}
if (family == "xo3" || help_mode)
run("booth", "(only if '-family xo3')");
@ -372,7 +443,7 @@ struct SynthLatticePass : public ScriptPass
if (check_label("map_ram"))
{
std::string args = "";
std::string args = map_ram_default;
if (help_mode)
args += " [-no-auto-block] [-no-auto-distributed]";
else {
@ -381,8 +452,13 @@ struct SynthLatticePass : public ScriptPass
if (nolutram)
args += " -no-auto-distributed";
}
run("memory_libmap -lib +/lattice/lutrams.txt -lib +/lattice/brams" + brams_map + ".txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/lattice/lutrams_map.v -map +/lattice/brams_map" + brams_map + ".v");
if (!is_nexus) {
run("memory_libmap -lib +/lattice/lutrams" + cells_map + ".txt -lib +/lattice/brams" + brams_map + ".txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/lattice/lutrams_map" + cells_map + ".v -map +/lattice/brams_map" + brams_map + ".v");
} else {
run("memory_libmap -lib +/lattice/lutrams" + cells_map + ".txt -lib +/lattice/brams" + brams_map + ".txt -lib +/lattice/lrams_nexus.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/lattice/lutrams_map" + cells_map + ".v -map +/lattice/brams_map" + brams_map + ".v -map +/lattice/lrams_map_nexus.v");
}
}
if (check_label("map_ffram"))
@ -411,27 +487,37 @@ struct SynthLatticePass : public ScriptPass
if (check_label("map_ffs"))
{
run("opt_clean");
std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
}
if (help_mode) {
dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
} else if (asyncprld) {
dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
if (!is_nexus) {
std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
}
if (help_mode) {
dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
} else if (asyncprld) {
dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
} else {
dfflegalize_args += " -cell $_DLATCH_?_ x";
}
run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)");
} else {
dfflegalize_args += " -cell $_DLATCH_?_ x";
std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r";
}
run("dfflegalize" + dfflegalize_args, "($_*DFFE_* only if not -nodffe)");
}
run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)");
run("opt_merge");
if ((abc9 && dff) || help_mode)
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff)");
run("techmap -D NO_LUT -map +/lattice/cells_map.v");
run("techmap -D NO_LUT -map +/lattice/cells_map" + cells_map + ".v");
run("opt_expr -undriven -mux_undef");
run("simplemap");
run("lattice_gsr");
if (!is_nexus) run("lattice_gsr");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
}
@ -462,7 +548,7 @@ struct SynthLatticePass : public ScriptPass
if (nowidelut)
abc_args += " -lut 4";
else
abc_args += " -lut 4:7";
abc_args += " -lut " + widelut_abc;
if (dff)
abc_args += " -dff";
run("abc" + abc_args);
@ -472,8 +558,14 @@ struct SynthLatticePass : public ScriptPass
if (check_label("map_cells"))
{
run("techmap -map +/lattice/cells_map.v");
run("opt_lut_ins -tech lattice");
run("techmap -map +/lattice/cells_map" + cells_map + ".v");
if (is_nexus) {
// This is needed for Radiant, but perhaps not optimal for nextpnr...
run("setundef -zero");
run("hilomap -singleton -hicell VHI Z -locell VLO Z");
} else {
run("opt_lut_ins -tech lattice");
}
run("clean");
}
@ -500,11 +592,49 @@ struct SynthLatticePass : public ScriptPass
}
} SynthLatticePass;
/*
struct SynthNexusPass : public Pass
{
SynthNexusPass() : Pass("synth_nexus", "synthesis for Nexus FPGAs") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_nexus [options]\n");
log("\n");
log("This command runs synthesis for Nexus FPGAs.\n");
log("\n");
log("This is a wrapper pass, for details take a look at help message for synth_lattice.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
args[0] = "synth_lattice";
args.insert(args.begin()+1, std::string());
args.insert(args.begin()+1, std::string());
args[1] = "-family";
args[2] = "lifcl";
Pass::call(design, args);
}
} SynthNexusPass;
struct SynthEcp5Pass : public Pass
{
SynthEcp5Pass() : Pass("synth_ecp5", "synthesis for ECP5 FPGAs") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_ecp5 [options]\n");
log("\n");
log("This command runs synthesis for ECP5 FPGAs.\n");
log("\n");
log("This is a wrapper pass, for details take a look at help message for synth_lattice.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
args[0] = "synth_lattice";
@ -515,6 +645,5 @@ struct SynthEcp5Pass : public Pass
Pass::call(design, args);
}
} SynthEcp5Pass;
*/
PRIVATE_NAMESPACE_END

View File

@ -77,6 +77,6 @@ end
print(" endtask", file=f)
print("endmodule", file=f)
diamond_models = "/usr/local/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u"
subprocess.call(["iverilog", "-s", "testbench", "-o", "work_ff/testbench", "-Dmixed_hdl", "-DNO_INCLUDES", "-y", diamond_models, "work_ff/cells_ff_gate.v", "../cells_sim.v", "work_ff/testbench.v"])
diamond_models = "/usr/local/diamond/3.12/cae_library/simulation/verilog/ecp5u"
subprocess.call(["iverilog", "-s", "testbench", "-o", "work_ff/testbench", "-Dmixed_hdl", "-DNO_INCLUDES", "-I..", "-y", diamond_models, "work_ff/cells_ff_gate.v", "../cells_sim_ecp5.v", "work_ff/testbench.v"])
subprocess.call(["vvp", "work_ff/testbench"])

View File

@ -1,16 +0,0 @@
OBJS += techlibs/nexus/synth_nexus.o
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_sim.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/parse_init.vh))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_xtra.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams.txt))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams.txt))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/dsp_map.v))

View File

@ -1,11 +0,0 @@
module \$_DLATCH_N_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = !E ? D : Q;
endmodule
module \$_DLATCH_P_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = E ? D : Q;
endmodule

View File

@ -1,419 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2020 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SynthNexusPass : public ScriptPass
{
SynthNexusPass() : ScriptPass("synth_nexus", "synthesis for Lattice Nexus FPGAs") { }
void on_register() override
{
RTLIL::constpad["synth_nexus.abc9.W"] = "300";
}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_nexus [options]\n");
log("\n");
log("This command runs synthesis for Lattice Nexus FPGAs.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
log(" -family <device>\n");
log(" run synthesis for the specified Nexus device\n");
log(" supported values: lifcl, lfd2nx\n");
log("\n");
log(" -json <file>\n");
log(" write the design to the specified JSON file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -vm <file>\n");
log(" write the design to the specified structural Verilog file. writing of\n");
log(" an output file is omitted if this parameter is not specified.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
log(" -noflatten\n");
log(" do not flatten design before synthesis\n");
log("\n");
log(" -dff\n");
log(" run 'abc'/'abc9' with -dff option\n");
log("\n");
log(" -retime\n");
log(" run 'abc' with '-dff -D 1' options\n");
log("\n");
log(" -noccu2\n");
log(" do not use CCU2 cells in output netlist\n");
log("\n");
log(" -nodffe\n");
log(" do not use flipflops with CE in output netlist\n");
log("\n");
log(" -nolram\n");
log(" do not use large RAM cells in output netlist\n");
log(" note that large RAM must be explicitly requested with a (* lram *)\n");
log(" attribute on the memory.\n");
log("\n");
log(" -nobram\n");
log(" do not use block RAM cells in output netlist\n");
log("\n");
log(" -nolutram\n");
log(" do not use LUT RAM cells in output netlist\n");
log("\n");
log(" -nowidelut\n");
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -noiopad\n");
log(" do not insert IO buffers\n");
log("\n");
log(" -nodsp\n");
log(" do not infer DSP multipliers\n");
log("\n");
log(" -abc9\n");
log(" use new ABC9 flow (EXPERIMENTAL)\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_opt, json_file, vm_file, family;
bool noccu2, nodffe, nolram, nobram, nolutram, nowidelut, noiopad, nodsp, flatten, dff, retime, abc9;
void clear_flags() override
{
top_opt = "-auto-top";
family = "lifcl";
json_file = "";
vm_file = "";
noccu2 = false;
nodffe = false;
nolram = false;
nobram = false;
nolutram = false;
nowidelut = false;
noiopad = false;
nodsp = false;
flatten = true;
dff = false;
retime = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
string run_from, run_to;
clear_flags();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-top" && argidx+1 < args.size()) {
top_opt = "-top " + args[++argidx];
continue;
}
if (args[argidx] == "-json" && argidx+1 < args.size()) {
json_file = args[++argidx];
continue;
}
if (args[argidx] == "-vm" && argidx+1 < args.size()) {
vm_file = args[++argidx];
continue;
}
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
break;
run_from = args[++argidx].substr(0, pos);
run_to = args[argidx].substr(pos+1);
continue;
}
if ((args[argidx] == "-family") && argidx+1 < args.size()) {
family = args[++argidx];
continue;
}
if (args[argidx] == "-flatten") {
flatten = true;
continue;
}
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
}
if (args[argidx] == "-dff") {
dff = true;
continue;
}
if (args[argidx] == "-nodsp") {
nodsp = true;
continue;
}
if (args[argidx] == "-retime") {
retime = true;
continue;
}
if (args[argidx] == "-noccu2") {
noccu2 = true;
continue;
}
if (args[argidx] == "-nodffe") {
nodffe = true;
continue;
}
if (args[argidx] == "-nolram") {
nolram = true;
continue;
}
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
if (args[argidx] == "-nolutram") {
nolutram = true;
continue;
}
if (args[argidx] == "-nowidelut") {
nowidelut = true;
continue;
}
if (args[argidx] == "-noiopad") {
noiopad = true;
continue;
}
if (args[argidx] == "-abc9") {
abc9 = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
if (abc9 && retime)
log_cmd_error("-retime option not currently compatible with -abc9!\n");
log_header(design, "Executing SYNTH_NEXUS pass.\n");
log_push();
run_script(design, run_from, run_to);
log_pop();
}
struct DSPRule {
int a_maxwidth;
int b_maxwidth;
int a_minwidth;
int b_minwidth;
std::string prim;
};
const std::vector<DSPRule> dsp_rules = {
{36, 36, 22, 22, "$__NX_MUL36X36"},
{36, 18, 22, 10, "$__NX_MUL36X18"},
{18, 18, 10, 4, "$__NX_MUL18X18"},
{18, 18, 4, 10, "$__NX_MUL18X18"},
{ 9, 9, 4, 4, "$__NX_MUL9X9"},
};
void script() override
{
if (family != "lifcl" && family != "lfd2nx")
log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family);
if (check_label("begin"))
{
run("read_verilog -lib -specify +/nexus/cells_sim.v +/nexus/cells_xtra.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt));
}
if (check_label("coarse"))
{
run("proc");
if (flatten || help_mode)
run("flatten");
run("tribuf -logic");
run("deminout");
run("opt_expr");
run("opt_clean");
run("check");
run("opt -nodffe -nosdff");
run("fsm");
run("opt");
run("wreduce");
run("peepopt");
run("opt_clean");
run("share");
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
run("opt_expr");
run("opt_clean");
if (help_mode) {
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
run("techmap -map +/nexus/dsp_map.v", "(unless -nodsp)");
} else if (!nodsp) {
for (const auto &rule : dsp_rules) {
run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s",
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str()));
run("chtype -set $mul t:$__soft_mul");
}
run("techmap -map +/nexus/dsp_map.v");
}
run("alumacc");
run("opt");
run("memory -nomap");
run("opt_clean");
}
if (check_label("map_ram"))
{
std::string args = "";
args += " -no-auto-huge";
if (help_mode)
args += " [-no-auto-block] [-no-auto-distributed]";
else {
if (nobram)
args += " -no-auto-block";
if (nolutram)
args += " -no-auto-distributed";
}
run("memory_libmap -lib +/nexus/lutrams.txt -lib +/nexus/brams.txt -lib +/nexus/lrams.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/nexus/lutrams_map.v -map +/nexus/brams_map.v -map +/nexus/lrams_map.v");
}
if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine");
}
if (check_label("map_gates"))
{
if (noccu2)
run("techmap");
else
run("techmap -map +/techmap.v -map +/nexus/arith_map.v");
if (help_mode || !noiopad)
run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad OBZ ~T:I:O -tinoutpad BB ~T:O:I:B A:top", "(skip if '-noiopad')");
run("opt -fast");
if (retime || help_mode)
run("abc -dff -D 1", "(only if -retime)");
}
if (check_label("map_ffs"))
{
run("opt_clean");
std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r";
}
run("dfflegalize" + dfflegalize_args, "($_*DFFE_* only if not -nodffe)");
if ((abc9 && dff) || help_mode)
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff");
run("techmap -D NO_LUT -map +/nexus/cells_map.v");
run("opt_expr -undriven -mux_undef");
run("simplemap");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
}
if (check_label("map_luts"))
{
run("techmap -map +/nexus/latches_map.v");
if (abc9) {
std::string abc9_opts;
if (nowidelut)
abc9_opts += " -maxlut 4";
std::string k = "synth_nexus.abc9.W";
if (active_design && active_design->scratchpad.count(k))
abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k));
else
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k));
if (nowidelut)
abc9_opts += " -maxlut 4";
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
} else {
std::string abc_args = " -dress";
if (nowidelut)
abc_args += " -lut 4";
else
abc_args += " -lut 4:5";
if (dff)
abc_args += " -dff";
run("abc" + abc_args);
}
run("clean");
}
if (check_label("map_cells"))
{
run("techmap -map +/nexus/cells_map.v");
// This is needed for Radiant, but perhaps not optimal for nextpnr...
run("setundef -zero");
run("hilomap -singleton -hicell VHI Z -locell VLO Z");
run("clean");
}
if (check_label("check"))
{
run("autoname");
run("hierarchy -check");
run("stat");
run("check -noinit");
run("blackbox =A:whitebox");
}
if (check_label("json"))
{
if (!json_file.empty() || help_mode)
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file));
}
if (check_label("vm"))
{
if (!vm_file.empty() || help_mode)
run(stringf("write_verilog %s", help_mode ? "<file-name>" : vm_file));
}
}
} SynthNexusPass;
PRIVATE_NAMESPACE_END

View File

@ -1,5 +1,5 @@
libcache -verbose
libcache -enable busdef.lib
libcache -enable bus*f.lib
logger -expect log "Caching is disabled by default." 1
logger -expect log "Caching is enabled for `busdef.lib'." 1

Some files were not shown because too many files have changed in this diff Show More