3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-06-26 10:38:47 +00:00

Merge pull request #24 from YosysHQ/main

bump fork for version 0.45
This commit is contained in:
Eder Monteiro 2024-09-03 09:55:50 -03:00 committed by GitHub
commit e794961432
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
112 changed files with 17726 additions and 452 deletions

View file

@ -86,7 +86,11 @@ jobs:
name: "Build nix flake"
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
with:
@ -94,4 +98,4 @@ jobs:
- uses: cachix/install-nix-action@v26
with:
install_url: https://releases.nixos.org/nix/nix-2.18.1/install
- run: nix build .?submodules=1
- run: nix build .?submodules=1 -L

52
.github/workflows/prepare-docs.yml vendored Normal file
View file

@ -0,0 +1,52 @@
name: Build docs artifact with Verific
on: push
jobs:
prepare-docs:
# docs builds are needed for anything on main, any tagged versions, and any tag
# or branch starting with docs-preview
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/docs-preview') || startsWith(github.ref, 'refs/tags/') }}
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
with:
persist-credentials: false
submodules: true
- name: Runtime environment
run: |
echo "procs=$(nproc)" >> $GITHUB_ENV
- name: Build Yosys
run: |
make config-clang
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
echo "ENABLE_CCACHE := 1" >> Makefile.conf
make -j${{ env.procs }} ENABLE_LTO=1
- name: Prepare docs
shell: bash
run:
make docs/prep TARGETS= EXTRA_TARGETS=
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: cmd-ref-${{ github.sha }}
path: |
docs/source/cmd
docs/source/generated
docs/source/_images
docs/source/code_examples
- name: Trigger RTDs build
uses: dfm/rtds-action@v1.1.0
with:
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
webhook_token: ${{ secrets.RTDS_WEBHOOK_TOKEN }}
commit_ref: ${{ github.ref }}

View file

@ -40,8 +40,8 @@ jobs:
- os: macos-13
compiler: 'clang'
# oldest clang not available on ubuntu-latest
- os: ubuntu-22.04
compiler: 'clang-11'
- os: ubuntu-20.04
compiler: 'clang-10'
fail-fast: false
steps:
- name: Checkout Yosys

View file

@ -3,7 +3,7 @@ name: Build and run tests with Verific (Linux)
on: [push, pull_request]
jobs:
pre_job:
pre-job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
@ -11,18 +11,16 @@ jobs:
- id: skip_check
uses: fkirc/skip-duplicate-actions@v5
with:
paths_ignore: '["**/README.md"]'
# don't cancel previous builds
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
# cancel previous builds if a new commit is pushed
cancel_others: 'true'
# only run on push *or* pull_request, not both
concurrent_skipping: 'same_content_newer'
# we have special actions when running on main, so this should be off
skip_after_successful_duplicate: 'false'
test-verific:
needs: pre_job
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: [self-hosted, linux, x64]
needs: pre-job
if: needs.pre-job.outputs.should_skip != 'true'
runs-on: [self-hosted, linux, x64, fast]
steps:
- name: Checkout Yosys
uses: actions/checkout@v4
@ -47,30 +45,6 @@ jobs:
run: |
make install DESTDIR=${GITHUB_WORKSPACE}/.local PREFIX=
- name: Checkout Documentation
if: ${{ github.ref == 'refs/heads/main' }}
uses: actions/checkout@v4
with:
path: 'yosys-cmd-ref'
repository: 'YosysHQ-Docs/yosys-cmd-ref'
fetch-depth: 0
token: ${{ secrets.CI_DOCS_UPDATE_PAT }}
persist-credentials: true
- name: Update documentation
if: ${{ github.ref == 'refs/heads/main' }}
run: |
make docs
rm -rf docs/build
cd yosys-cmd-ref
rm -rf *
git checkout README.md
cp -R ../docs/* .
rm -rf util/__pycache__
git add -A .
git diff-index --quiet HEAD || git commit -m "Update"
git push
- name: Checkout SBY
uses: actions/checkout@v4
with:

20
.readthedocs.yaml Normal file
View file

@ -0,0 +1,20 @@
# .readthedocs.yaml
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
build:
os: ubuntu-22.04
tools:
python: '3.12'
formats:
- pdf
sphinx:
configuration: docs/source/conf.py
fail_on_warning: true
python:
install:
- requirements: docs/source/requirements.txt

View file

@ -2,9 +2,17 @@
List of major changes and improvements between releases
=======================================================
Yosys 0.44 .. Yosys 0.45-dev
Yosys 0.45 .. Yosys 0.46-dev
--------------------------
Yosys 0.44 .. Yosys 0.45
--------------------------
* Various
- Added cell types help messages.
* New back-ends
- Added initial NG-Ultra support. ( synth_nanoxplore )
Yosys 0.43 .. Yosys 0.44
--------------------------
* Various

View file

@ -153,7 +153,7 @@ ifeq ($(OS), Haiku)
CXXFLAGS += -D_DEFAULT_SOURCE
endif
YOSYS_VER := 0.44+0
YOSYS_VER := 0.45+0
# Note: We arrange for .gitcommit to contain the (short) commit hash in
# tarballs generated with git-archive(1) using .gitattributes. The git repo
@ -169,7 +169,7 @@ endif
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 80ba43d.. | wc -l`/;" Makefile
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 9ed031d.. | wc -l`/;" Makefile
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
@ -807,7 +807,7 @@ check-git-abc:
exit 1; \
fi
abc/abc$(EXE) abc/libabc.a: check-git-abc
abc/abc$(EXE) abc/libabc.a: | check-git-abc
$(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)
@ -877,6 +877,7 @@ endif
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
+cd tests/arch/nanoxplore && bash run-test.sh $(SEEDOPT)
+cd tests/arch/nexus && bash run-test.sh $(SEEDOPT)
+cd tests/arch/quicklogic/pp3 && bash run-test.sh $(SEEDOPT)
+cd tests/arch/quicklogic/qlf_k6n10f && bash run-test.sh $(SEEDOPT)
@ -984,8 +985,8 @@ docs/guidelines docs/source/generated:
# some commands return an error and print the usage text to stderr
define DOC_USAGE_STDERR
docs/source/generated/$(1): $(PROGRAM_PREFIX)$(1) docs/source/generated
-$(Q) ./$$< --help 2> $$@
docs/source/generated/$(1): $(TARGETS) docs/source/generated
-$(Q) ./$(PROGRAM_PREFIX)$(1) --help 2> $$@
endef
DOCS_USAGE_STDERR := yosys-config yosys-filterlib
@ -998,8 +999,8 @@ $(foreach usage,$(DOCS_USAGE_STDERR),$(eval $(call DOC_USAGE_STDERR,$(usage))))
# others print to stdout
define DOC_USAGE_STDOUT
docs/source/generated/$(1): $(PROGRAM_PREFIX)$(1) docs/source/generated
$(Q) ./$$< --help > $$@
docs/source/generated/$(1): $(TARGETS) docs/source/generated
$(Q) ./$(PROGRAM_PREFIX)$(1) --help > $$@
endef
DOCS_USAGE_STDOUT := yosys yosys-smtbmc yosys-witness
$(foreach usage,$(DOCS_USAGE_STDOUT),$(eval $(call DOC_USAGE_STDOUT,$(usage))))
@ -1009,8 +1010,11 @@ docs/usage: $(addprefix docs/source/generated/,$(DOCS_USAGE_STDOUT) $(DOCS_USAGE
docs/reqs:
$(Q) $(MAKE) -C docs reqs
.PHONY: docs/prep
docs/prep: docs/source/cmd/abc.rst docs/gen_examples docs/gen_images docs/guidelines docs/usage
DOC_TARGET ?= html
docs: docs/source/cmd/abc.rst docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs
docs: docs/prep
$(Q) $(MAKE) -C docs $(DOC_TARGET)
clean:

View file

@ -629,11 +629,21 @@ following are used for building the website:
$ sudo apt install pdf2svg faketime
Or for MacOS, using homebrew:
$ brew install pdf2svg libfaketime
PDFLaTeX, included with most LaTeX distributions, is also needed during the
build process for the website. Or, run the following:
$ sudo apt install texlive-latex-base texlive-latex-extra latexmk
Or for MacOS, using homebrew:
$ brew install basictex
$ sudo tlmgr update --self
$ sudo tlmgr install collection-latexextra latexmk tex-gyre
The Python package, Sphinx, is needed along with those listed in
`docs/source/requirements.txt`:

2
abc

@ -1 +1 @@
Subproject commit 28d955ca97a1c4be3aed4062aec0241a734fac5d
Subproject commit 2188bc71228b0788569d83ad2b7e7b91ca5dcc09

View file

@ -51,6 +51,9 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
}
}
f << stringf("%d'", width);
if (data.flags & RTLIL::CONST_FLAG_SIGNED) {
f << stringf("s");
}
if (data.is_fully_undef_x_only()) {
f << "x";
} else {

View file

@ -250,6 +250,7 @@ test-macros:
.PHONY: images
images:
$(MAKE) -C source/_images
$(MAKE) -C source/_images convert
.PHONY: reqs
reqs:

View file

@ -8,24 +8,22 @@ FAKETIME := TZ='Z' faketime -f '2022-01-01 00:00:00 x0,001'
CODE_EXAMPLES := ../code_examples/*/Makefile
examples: $(CODE_EXAMPLES)
# target to convert specified dot file(s)
# target to convert all dot files
# needs to be run *after* examples, otherwise no dot files will be found
.PHONY: convert
TARG_DOT ?=
convert: $(TARG_DOT:.dot=.pdf) $(TARG_DOT:.dot=.svg)
DOT_FILES := $(shell find . -name *.dot)
convert: $(DOT_FILES:.dot=.pdf) $(DOT_FILES:.dot=.svg)
# use empty FORCE target because .PHONY ignores % expansion, using find allows
# us to generate everything in one pass, since we don't know all of the possible
# outputs until the sub-makes run
# use empty FORCE target because .PHONY ignores % expansion
FORCE:
../%/Makefile: FORCE
@make -C $(@D) dots
@mkdir -p $*
@find $(@D) -name *.dot -exec cp -u {} -t $* \;
@find $* -name *.dot -printf "%p " | xargs -i make --no-print-directory convert TARG_DOT="{}"
@find $(@D) -name *.dot -exec rsync -t {} $* \;
# find and build all tex files
.PHONY: all_tex
TEX_FILES := $(wildcard **/*.tex)
TEX_FILES := $(shell find . -name *.tex)
all_tex: $(TEX_FILES:.tex=.pdf) $(TEX_FILES:.tex=.svg)
%.pdf: %.dot

View file

@ -13,7 +13,7 @@ dots: $(DOTS)
$(YOSYS) $<
%.dot: %_full.dot
gvpack -u $*_full.dot -o $@
gvpack -u -o $@ $*_full.dot
.PHONY: clean
clean:

View file

@ -1,13 +1,13 @@
TARGETS += proc_01 proc_02 proc_03
TARGETS += memory_01 memory_02
TARGETS += techmap_01
DOT_TARGETS += proc_01 proc_02 proc_03
DOT_TARGETS += memory_01 memory_02
DOT_TARGETS += techmap_01
PROGRAM_PREFIX :=
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
DOTS = $(addsuffix .dot,$(TARGETS))
DOTS = $(addsuffix .dot,$(DOT_TARGETS))
.PHONY: all dots
all: dots

View file

@ -5,7 +5,7 @@ import os
project = 'YosysHQ Yosys'
author = 'YosysHQ GmbH'
copyright ='2024 YosysHQ GmbH'
yosys_ver = "0.44"
yosys_ver = "0.45"
# select HTML theme
html_theme = 'furo'
@ -43,15 +43,42 @@ highlight_language = 'none'
extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex']
if os.getenv("READTHEDOCS"):
# Use rtds_action if we are building on read the docs and have a github token env var
if os.getenv("GITHUB_TOKEN"):
extensions += ['rtds_action']
rtds_action_github_repo = "YosysHQ/yosys"
rtds_action_path = "."
rtds_action_artifact_prefix = "cmd-ref-"
rtds_action_github_token = os.environ["GITHUB_TOKEN"]
else:
# We're on read the docs but have no github token, this is probably a PR preview build
html_theme_options["announcement"] = 'Missing content? Check <a class="reference internal" href="https://tyrtd--2.org.readthedocs.build/en/2/appendix/building_docs.html#pr-previews-and-limitations">PR preview limitations</a>.'
html_theme_options["light_css_variables"]["color-announcement-background"] = "var(--color-admonition-title-background--caution)"
html_theme_options["light_css_variables"]["color-announcement-text"] = "var(--color-content-foreground)"
# Ensure that autosectionlabel will produce unique names
autosectionlabel_prefix_document = True
autosectionlabel_maxdepth = 1
# include todos for previews
extensions.append('sphinx.ext.todo')
# set version
if os.getenv("READTHEDOCS") and os.getenv("READTHEDOCS_VERSION") == "latest":
release = yosys_ver + "-dev"
if os.getenv("READTHEDOCS"):
rtds_version = os.getenv("READTHEDOCS_VERSION")
if rtds_version == "latest":
release = yosys_ver + "-dev"
todo_include_todos = False
elif rtds_version.startswith("docs"):
release = rtds_version
todo_include_todos = True
else:
release = yosys_ver
todo_include_todos = False
else:
release = yosys_ver
todo_include_todos = True
# assign figure numbers
numfig = True
@ -66,10 +93,6 @@ latex_elements = {
'''
}
# include todos during rewrite
extensions.append('sphinx.ext.todo')
todo_include_todos = False
# custom cmd-ref parsing/linking
sys.path += [os.path.dirname(__file__) + "/../"]
extensions.append('util.cmdref')

View file

@ -138,7 +138,8 @@ To use a compiler different than the default, use:
.. seealso::
Refer to :doc:`/test_suites` for details on testing Yosys once compiled.
Refer to :doc:`/yosys_internals/extending_yosys/test_suites` for details on
testing Yosys once compiled.
Source tree and build system
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -193,7 +194,7 @@ directories:
``tests/``
This directory contains the suite of unit tests and regression tests used by
Yosys. See :doc:`/test_suites`.
Yosys. See :doc:`/yosys_internals/extending_yosys/test_suites`.
The top-level Makefile includes :file:`frontends/{*}/Makefile.inc`,
:file:`passes/{*}/Makefile.inc` and :file:`backends/{*}/Makefile.inc`. So when

View file

@ -40,6 +40,5 @@ available, go to :ref:`commandindex`.
getting_started/index
using_yosys/index
yosys_internals/index
test_suites
appendix

View file

@ -1,2 +1,3 @@
furo
sphinxcontrib-bibtex
rtds-action

View file

@ -3,6 +3,8 @@ More scripting
.. todo:: brief overview for the more scripting index
.. todo:: troubleshooting document(?)
.. toctree::
:maxdepth: 3

View file

@ -27,6 +27,14 @@ keyword: Frontends
.. todo:: more info on other ``read_*`` commands, also is this the first time we
mention verific?
.. note::
The Verific frontend for Yosys, which provides the :cmd:ref:`verific`
command, requires Yosys to be built with Verific. For full functionality,
custom modifications to the Verific source code from YosysHQ are required,
but limited useability can be achieved with some stock Verific builds. Check
:doc:`/yosys_internals/extending_yosys/build_verific` for more.
Others:
- :doc:`/cmd/read`

View file

@ -1,6 +0,0 @@
Troubleshooting
~~~~~~~~~~~~~~~
.. todo:: troubleshooting document(?)
See :doc:`/cmd/bugpoint`

View file

@ -1,5 +1,5 @@
The ABC toolbox
---------------
===============
.. role:: yoscrypt(code)
:language: yoscrypt
@ -21,7 +21,7 @@ global view of the mapping problem.
.. _ABC: https://github.com/berkeley-abc/abc
ABC: the unit delay model, simple and efficient
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-----------------------------------------------
The :cmd:ref:`abc` pass uses a highly simplified view of an FPGA:
@ -66,7 +66,7 @@ But this approach has drawbacks, too:
before clock edge) which affect the delay of a path.
ABC9: the generalised delay model, realistic and flexible
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---------------------------------------------------------
ABC9 uses a more detailed and accurate model of an FPGA:
@ -101,3 +101,81 @@ optimise better around those boxes, and also permute inputs to give the critical
path the fastest inputs.
.. todo:: more about logic minimization & register balancing et al with ABC
Setting up a flow for ABC9
--------------------------
Much of the configuration comes from attributes and ``specify`` blocks in
Verilog simulation models.
``specify`` syntax
~~~~~~~~~~~~~~~~~~
Since ``specify`` is a relatively obscure part of the Verilog standard, a quick
guide to the syntax:
.. code-block:: verilog
specify // begins a specify block
(A => B) = 123; // simple combinational path from A to B with a delay of 123.
(A *> B) = 123; // simple combinational path from A to all bits of B with a delay of 123 for all.
if (FOO) (A => B) = 123; // paths may apply under specific conditions.
(posedge CLK => (Q : D)) = 123; // combinational path triggered on the positive edge of CLK; used for clock-to-Q arrival paths.
$setup(A, posedge CLK, 123); // setup constraint for an input relative to a clock.
endspecify // ends a specify block
By convention, all delays in ``specify`` blocks are in integer picoseconds.
Files containing ``specify`` blocks should be read with the ``-specify`` option
to :cmd:ref:`read_verilog` so that they aren't skipped.
LUTs
^^^^
LUTs need to be annotated with an ``(* abc9_lut=N *)`` attribute, where ``N`` is
the relative area of that LUT model. For example, if an architecture can combine
LUTs to produce larger LUTs, then the combined LUTs would have increasingly
larger ``N``. Conversely, if an architecture can split larger LUTs into smaller
LUTs, then the smaller LUTs would have smaller ``N``.
LUTs are generally specified with simple combinational paths from the LUT inputs
to the LUT output.
DFFs
^^^^
DFFs should be annotated with an ``(* abc9_flop *)`` attribute, however ABC9 has
some specific requirements for this to be valid: - the DFF must initialise to
zero (consider using :cmd:ref:`dfflegalize` to ensure this). - the DFF cannot
have any asynchronous resets/sets (see the simplification idiom and the Boxes
section for what to do here).
It is worth noting that in pure ``abc9`` mode, only the setup and arrival times
are passed to ABC9 (specifically, they are modelled as buffers with the given
delay). In ``abc9 -dff``, the flop itself is passed to ABC9, permitting
sequential optimisations.
Some vendors have universal DFF models which include async sets/resets even when
they're unused. Therefore *the simplification idiom* exists to handle this: by
using a ``techmap`` file to discover flops which have a constant driver to those
asynchronous controls, they can be mapped into an intermediate, simplified flop
which qualifies as an ``(* abc9_flop *)``, ran through :cmd:ref:`abc9`, and then
mapped back to the original flop. This is used in :cmd:ref:`synth_intel_alm` and
:cmd:ref:`synth_quicklogic` for the PolarPro3.
DFFs are usually specified to have setup constraints against the clock on the
input signals, and an arrival time for the ``Q`` output.
Boxes
^^^^^
A "box" is a purely-combinational piece of hard logic. If the logic is exposed
to ABC9, it's a "whitebox", otherwise it's a "blackbox". Carry chains would be
best implemented as whiteboxes, but a DSP would be best implemented as a
blackbox (multipliers are too complex to easily work with). LUT RAMs can be
implemented as whiteboxes too.
Boxes are arguably the biggest advantage that ABC9 has over ABC: by being aware
of carry chains and DSPs, it avoids optimising for a path that isn't the actual
critical path, while the generally-longer paths result in ABC9 being able to
reduce design area by mapping other logic to larger-but-slower cells.

View file

@ -90,8 +90,10 @@ Mapping to hardware
For this example, we are using a Liberty file to describe a cell library which
our internal cell library will be mapped to:
.. todo:: find a Liberty pygments style?
.. literalinclude:: /code_examples/intro/mycells.lib
:language: Liberty
:language: text
:linenos:
:name: mycells-lib
:caption: :file:`mycells.lib`

View file

@ -697,6 +697,9 @@ TDP with multiple read ports
Patterns only supported with Verific
------------------------------------
The following patterns are only supported when the design is read in using the
Verific front-end.
Synchronous SDP with write-first behavior via blocking assignments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -1,76 +0,0 @@
Setting up a flow for ABC9
--------------------------
Much of the configuration comes from attributes and ``specify`` blocks in
Verilog simulation models.
``specify`` syntax
~~~~~~~~~~~~~~~~~~
Since ``specify`` is a relatively obscure part of the Verilog standard, a quick
guide to the syntax:
.. code-block:: verilog
specify // begins a specify block
(A => B) = 123; // simple combinational path from A to B with a delay of 123.
(A *> B) = 123; // simple combinational path from A to all bits of B with a delay of 123 for all.
if (FOO) (A => B) = 123; // paths may apply under specific conditions.
(posedge CLK => (Q : D)) = 123; // combinational path triggered on the positive edge of CLK; used for clock-to-Q arrival paths.
$setup(A, posedge CLK, 123); // setup constraint for an input relative to a clock.
endspecify // ends a specify block
By convention, all delays in ``specify`` blocks are in integer picoseconds.
Files containing ``specify`` blocks should be read with the ``-specify`` option
to :cmd:ref:`read_verilog` so that they aren't skipped.
LUTs
^^^^
LUTs need to be annotated with an ``(* abc9_lut=N *)`` attribute, where ``N`` is
the relative area of that LUT model. For example, if an architecture can combine
LUTs to produce larger LUTs, then the combined LUTs would have increasingly
larger ``N``. Conversely, if an architecture can split larger LUTs into smaller
LUTs, then the smaller LUTs would have smaller ``N``.
LUTs are generally specified with simple combinational paths from the LUT inputs
to the LUT output.
DFFs
^^^^
DFFs should be annotated with an ``(* abc9_flop *)`` attribute, however ABC9 has
some specific requirements for this to be valid: - the DFF must initialise to
zero (consider using :cmd:ref:`dfflegalize` to ensure this). - the DFF cannot
have any asynchronous resets/sets (see the simplification idiom and the Boxes
section for what to do here).
It is worth noting that in pure ``abc9`` mode, only the setup and arrival times
are passed to ABC9 (specifically, they are modelled as buffers with the given
delay). In ``abc9 -dff``, the flop itself is passed to ABC9, permitting
sequential optimisations.
Some vendors have universal DFF models which include async sets/resets even when
they're unused. Therefore *the simplification idiom* exists to handle this: by
using a ``techmap`` file to discover flops which have a constant driver to those
asynchronous controls, they can be mapped into an intermediate, simplified flop
which qualifies as an ``(* abc9_flop *)``, ran through :cmd:ref:`abc9`, and then
mapped back to the original flop. This is used in :cmd:ref:`synth_intel_alm` and
:cmd:ref:`synth_quicklogic` for the PolarPro3.
DFFs are usually specified to have setup constraints against the clock on the
input signals, and an arrival time for the ``Q`` output.
Boxes
^^^^^
A "box" is a purely-combinational piece of hard logic. If the logic is exposed
to ABC9, it's a "whitebox", otherwise it's a "blackbox". Carry chains would be
best implemented as whiteboxes, but a DSP would be best implemented as a
blackbox (multipliers are too complex to easily work with). LUT RAMs can be
implemented as whiteboxes too.
Boxes are arguably the biggest advantage that ABC9 has over ABC: by being aware
of carry chains and DSPs, it avoids optimising for a path that isn't the actual
critical path, while the generally-longer paths result in ABC9 being able to
reduce design area by mapping other logic to larger-but-slower cells.

View file

@ -0,0 +1,155 @@
Compiling with Verific library
==============================
The easiest way to get Yosys with Verific support is to `contact YosysHQ`_ for a
`Tabby CAD Suite`_ evaluation license and download link. The TabbyCAD Suite
includes additional patches and a custom extensions library in order to get the
most out of the Verific parser when using Yosys.
If you already have a license for the Verific parser, in either source or binary
form, you may be able to compile Yosys with partial Verific support yourself.
.. _contact YosysHQ : https://www.yosyshq.com/contact
.. _Tabby CAD Suite: https://www.yosyshq.com/tabby-cad-datasheet
The Yosys-Verific patch
-----------------------
YosysHQ maintains and develops a patch for Verific in order to better integrate
with Yosys and to provide features required by some of the formal verification
front-end tools. To license this patch for your own Yosys builds, `contact
YosysHQ`_.
.. warning::
While synthesis from RTL may be possible without this patch, YosysHQ provides
no guarantees of correctness and is unable to provide support.
We recommend against using unpatched Yosys+Verific builds in conjunction with
the formal verification front-end tools unless you are familiar with their inner
workings. There are cases where the tools will appear to work, while producing
incorrect results.
.. note::
Some of the formal verification front-end tools may not be fully supported
without the full TabbyCAD suite. If you want to use these tools, including
SBY, make sure to ask us if the Yosys-Verific patch is right for you.
Compile options
---------------
To enable Verific support ``ENABLE_VERIFIC`` has to be set to ``1`` and
``VERIFIC_DIR`` needs to point to the location where the library is located.
============== ========================== ===============================
Parameter Default Description
============== ========================== ===============================
ENABLE_VERIFIC 0 Enable compilation with Verific
VERIFIC_DIR /usr/local/src/verific_lib Library and headers location
============== ========================== ===============================
Since there are multiple Verific library builds and they can have different
features, there are compile options to select them.
================================= ======= ===================================
Parameter Default Description
================================= ======= ===================================
ENABLE_VERIFIC_SYSTEMVERILOG 1 SystemVerilog support
ENABLE_VERIFIC_VHDL 1 VHDL support
ENABLE_VERIFIC_HIER_TREE 1 Hierarchy tree support
ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS 0 YosysHQ specific extensions support
ENABLE_VERIFIC_EDIF 0 EDIF support
ENABLE_VERIFIC_LIBERTY 0 Liberty file support
================================= ======= ===================================
To find the compile options used for a given Yosys build, call ``yosys-config
--cxxflags``. This documentation was built with the following compile options:
.. literalinclude:: /generated/yosys-config
:start-at: --cxxflags
:end-before: --linkflags
.. note::
The YosysHQ specific extensions are only available with the TabbyCAD suite.
Required Verific features
~~~~~~~~~~~~~~~~~~~~~~~~~
The following features, along with their corresponding Yosys build parameters,
are required for the Yosys-Verific patch:
* RTL elaboration with
* SystemVerilog with ``ENABLE_VERIFIC_SYSTEMVERILOG``, and/or
* VHDL support with ``ENABLE_VERIFIC_VHDL``.
* Hierarchy tree support and static elaboration with
``ENABLE_VERIFIC_HIER_TREE``.
Please be aware that the following Verific configuration build parameter needs
to be enabled in order to create the fully supported build:
::
database/DBCompileFlags.h:
DB_PRESERVE_INITIAL_VALUE
.. note::
Yosys+Verific builds may compile without these features, but we provide no
guarantees and cannot offer support if they are disabled or the Yosys-Verific
patch is not used.
Optional Verific features
~~~~~~~~~~~~~~~~~~~~~~~~~
The following Verific features are available with TabbyCAD and can be enabled in
Yosys builds:
* EDIF support with ``ENABLE_VERIFIC_EDIF``, and
* Liberty file support with ``ENABLE_VERIFIC_LIBERTY``.
Partially supported builds
~~~~~~~~~~~~~~~~~~~~~~~~~~
This section describes Yosys+Verific configurations which we have confirmed as
working in the past, however they are not a part of our regular tests so we
cannot guarantee they are still functional.
To be able to compile Yosys with Verific, the Verific library must have support
for at least one HDL language with RTL elaboration enabled. The following table
lists a series of build configurations which are possible, but only provide a
limited subset of features. Please note that support is limited without YosysHQ
specific extensions of Verific library.
Configuration values:
a. ``ENABLE_VERIFIC_SYSTEMVERILOG``
b. ``ENABLE_VERIFIC_VHDL``
c. ``ENABLE_VERIFIC_HIER_TREE``
d. ``ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS``
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| | Configuration values |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| Features | a | b | c | d |
+==========================================================================+=====+=====+=====+=====+
| SystemVerilog + RTL elaboration | 1 | 0 | 0 | 0 |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| VHDL + RTL elaboration | 0 | 1 | 0 | 0 |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| SystemVerilog + VHDL + RTL elaboration | 1 | 1 | 0 | 0 |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| SystemVerilog + RTL elaboration + Static elaboration + Hier tree | 1 | 0 | 1 | 0 |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| VHDL + RTL elaboration + Static elaboration + Hier tree | 0 | 1 | 1 | 0 |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
| SystemVerilog + VHDL + RTL elaboration + Static elaboration + Hier tree | 1 | 1 | 1 | 0 |
+--------------------------------------------------------------------------+-----+-----+-----+-----+
.. note::
In case your Verific build has EDIF and/or Liberty support, you can enable
those options. These are not mentioned above for simplification and since
they are disabled by default.

View file

@ -1,11 +1,14 @@
Extending Yosys
---------------
Working with the Yosys codebase
-------------------------------
.. todo:: brief overview for the extending Yosys index
This section goes into additional detail on the Yosys source code and git
repository. This information is not needed for simply using Yosys, but may be
of interest for developers looking to customise Yosys builds.
.. toctree::
:maxdepth: 3
extensions
abc_flow
build_verific
test_suites

View file

@ -53,47 +53,12 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&
return module->wires_.at(id);
}
static RTLIL::SigSpec create_inv_cell(RTLIL::Module *module, RTLIL::SigSpec A)
{
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_NOT_));
cell->setPort(ID::A, A);
cell->setPort(ID::Y, module->addWire(NEW_ID));
return cell->getPort(ID::Y);
}
static RTLIL::SigSpec create_xor_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
{
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_XOR_));
cell->setPort(ID::A, A);
cell->setPort(ID::B, B);
cell->setPort(ID::Y, module->addWire(NEW_ID));
return cell->getPort(ID::Y);
}
static RTLIL::SigSpec create_and_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
{
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_AND_));
cell->setPort(ID::A, A);
cell->setPort(ID::B, B);
cell->setPort(ID::Y, module->addWire(NEW_ID));
return cell->getPort(ID::Y);
}
static RTLIL::SigSpec create_or_cell(RTLIL::Module *module, RTLIL::SigSpec A, RTLIL::SigSpec B)
{
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($_OR_));
cell->setPort(ID::A, A);
cell->setPort(ID::B, B);
cell->setPort(ID::Y, module->addWire(NEW_ID));
return cell->getPort(ID::Y);
}
static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack, token_t next_token)
{
int top = int(stack.size())-1;
if (0 <= top-1 && stack[top].type == 0 && stack[top-1].type == '!') {
token_t t = token_t(0, create_inv_cell(module, stack[top].sig));
token_t t = token_t(0, module->NotGate(NEW_ID, stack[top].sig));
stack.pop_back();
stack.pop_back();
stack.push_back(t);
@ -101,7 +66,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top-1 && stack[top].type == '\'' && stack[top-1].type == 0) {
token_t t = token_t(0, create_inv_cell(module, stack[top-1].sig));
token_t t = token_t(0, module->NotGate(NEW_ID, stack[top-1].sig));
stack.pop_back();
stack.pop_back();
stack.push_back(t);
@ -116,7 +81,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top-2 && stack[top-2].type == 1 && stack[top-1].type == '^' && stack[top].type == 1) {
token_t t = token_t(1, create_xor_cell(module, stack[top-2].sig, stack[top].sig));
token_t t = token_t(1, module->XorGate(NEW_ID, stack[top-2].sig, stack[top].sig));
stack.pop_back();
stack.pop_back();
stack.pop_back();
@ -132,7 +97,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top-1 && stack[top-1].type == 2 && stack[top].type == 2) {
token_t t = token_t(2, create_and_cell(module, stack[top-1].sig, stack[top].sig));
token_t t = token_t(2, module->AndGate(NEW_ID, stack[top-1].sig, stack[top].sig));
stack.pop_back();
stack.pop_back();
stack.push_back(t);
@ -140,7 +105,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top-2 && stack[top-2].type == 2 && (stack[top-1].type == '*' || stack[top-1].type == '&') && stack[top].type == 2) {
token_t t = token_t(2, create_and_cell(module, stack[top-2].sig, stack[top].sig));
token_t t = token_t(2, module->AndGate(NEW_ID, stack[top-2].sig, stack[top].sig));
stack.pop_back();
stack.pop_back();
stack.pop_back();
@ -156,7 +121,7 @@ static bool parse_func_reduce(RTLIL::Module *module, std::vector<token_t> &stack
}
if (0 <= top-2 && stack[top-2].type == 3 && (stack[top-1].type == '+' || stack[top-1].type == '|') && stack[top].type == 3) {
token_t t = token_t(3, create_or_cell(module, stack[top-2].sig, stack[top].sig));
token_t t = token_t(3, module->OrGate(NEW_ID, stack[top-2].sig, stack[top].sig));
stack.pop_back();
stack.pop_back();
stack.pop_back();
@ -221,12 +186,12 @@ static RTLIL::SigSpec create_tristate(RTLIL::Module *module, RTLIL::SigSpec func
RTLIL::Cell *cell = module->addCell(NEW_ID, ID($tribuf));
cell->setParam(ID::WIDTH, GetSize(func));
cell->setPort(ID::A, func);
cell->setPort(ID::EN, create_inv_cell(module, three_state));
cell->setPort(ID::EN, module->NotGate(NEW_ID, three_state));
cell->setPort(ID::Y, module->addWire(NEW_ID));
return cell->getPort(ID::Y);
}
static void create_ff(RTLIL::Module *module, LibertyAst *node)
static void create_ff(RTLIL::Module *module, const LibertyAst *node)
{
RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0))));
RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
@ -303,7 +268,7 @@ static void create_ff(RTLIL::Module *module, LibertyAst *node)
log_assert(!cell->type.empty());
}
static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_ignore_miss_data_latch)
static bool create_latch(RTLIL::Module *module, const LibertyAst *node, bool flag_ignore_miss_data_latch)
{
RTLIL::SigSpec iq_sig(module->addWire(RTLIL::escape_id(node->args.at(0))));
RTLIL::SigSpec iqn_sig(module->addWire(RTLIL::escape_id(node->args.at(1))));
@ -422,7 +387,7 @@ static bool create_latch(RTLIL::Module *module, LibertyAst *node, bool flag_igno
return true;
}
void parse_type_map(std::map<std::string, std::tuple<int, int, bool>> &type_map, LibertyAst *ast)
void parse_type_map(std::map<std::string, std::tuple<int, int, bool>> &type_map, const LibertyAst *ast)
{
for (auto type_node : ast->children)
{
@ -604,7 +569,7 @@ struct LibertyFrontend : public Frontend {
for (auto node : cell->children)
{
if (node->id == "pin" && node->args.size() == 1) {
LibertyAst *dir = node->find("direction");
const LibertyAst *dir = node->find("direction");
if (!dir || (dir->value != "input" && dir->value != "output" && dir->value != "inout" && dir->value != "internal"))
{
if (!flag_ignore_miss_dir)
@ -625,10 +590,10 @@ struct LibertyFrontend : public Frontend {
if (!flag_lib)
log_error("Error in cell %s: bus interfaces are only supported in -lib mode.\n", log_id(cell_name));
LibertyAst *dir = node->find("direction");
const LibertyAst *dir = node->find("direction");
if (dir == nullptr) {
LibertyAst *pin = node->find("pin");
const LibertyAst *pin = node->find("pin");
if (pin != nullptr)
dir = pin->find("direction");
}
@ -639,7 +604,7 @@ struct LibertyFrontend : public Frontend {
if (dir->value == "internal")
continue;
LibertyAst *bus_type_node = node->find("bus_type");
const LibertyAst *bus_type_node = node->find("bus_type");
if (!bus_type_node || !type_map.count(bus_type_node->value))
log_error("Unknown or unsupported type for bus interface %s on cell %s.\n",
@ -681,7 +646,7 @@ struct LibertyFrontend : public Frontend {
{
if (node->id == "pin" && node->args.size() == 1)
{
LibertyAst *dir = node->find("direction");
const LibertyAst *dir = node->find("direction");
if (flag_lib && dir->value == "internal")
continue;
@ -704,7 +669,7 @@ struct LibertyFrontend : public Frontend {
if (flag_lib)
continue;
LibertyAst *func = node->find("function");
const LibertyAst *func = node->find("function");
if (func == NULL)
{
if (dir->value != "inout") { // allow inout with missing function, can be used for power pins
@ -719,7 +684,7 @@ struct LibertyFrontend : public Frontend {
}
} else {
RTLIL::SigSpec out_sig = parse_func_expr(module, func->value.c_str());
LibertyAst *three_state = node->find("three_state");
const LibertyAst *three_state = node->find("three_state");
if (three_state) {
out_sig = create_tristate(module, out_sig, three_state->value.c_str());
}

View file

@ -88,7 +88,7 @@ USING_YOSYS_NAMESPACE
"\\"[^ \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]+'[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; }
[0-9]+'s?[01xzm-]* { rtlil_frontend_yylval.string = strdup(yytext); return TOK_VALUE; }
-?[0-9]+ {
char *end = nullptr;
errno = 0;

View file

@ -412,8 +412,16 @@ 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) {
while (*ep != 0) {
RTLIL::State bit = RTLIL::Sx;
switch (*ep) {
case '0': bit = RTLIL::S0; break;
@ -424,7 +432,9 @@ constant:
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) {
@ -438,6 +448,9 @@ constant:
$$ = new RTLIL::Const;
for (auto it = bits.begin(); it != bits.end(); it++)
$$->bits.push_back(*it);
if (is_signed) {
$$->flags |= RTLIL::CONST_FLAG_SIGNED;
}
free($1);
} |
TOK_INT {

View file

@ -721,13 +721,17 @@ int main(int argc, char **argv)
ru_buffer.ru_utime.tv_usec += ru_buffer_children.ru_utime.tv_usec;
ru_buffer.ru_stime.tv_sec += ru_buffer_children.ru_stime.tv_sec;
ru_buffer.ru_stime.tv_usec += ru_buffer_children.ru_stime.tv_usec;
#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
ru_buffer.ru_maxrss = std::max(ru_buffer.ru_maxrss, ru_buffer_children.ru_maxrss);
#endif
}
#if defined(__linux__) || defined(__FreeBSD__)
meminfo = stringf(", MEM: %.2f MB peak",
ru_buffer.ru_maxrss / 1024.0);
#elif defined(__APPLE__)
// https://stackoverflow.com/questions/59913657/strange-values-of-get-rusage-maxrss-on-macos-and-linux
meminfo = stringf(", MEM: %.2f MB peak",
ru_buffer.ru_maxrss / (1024.0 * 1024.0));
#endif
log("End of script. Logfile hash: %s%sCPU: user %.2fs system %.2fs%s\n", hash.c_str(),
stats_divider.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec,

View file

@ -832,7 +832,7 @@ std::string Fmt::render() const
}
} else log_abort();
if (part.justify == FmtPart::NUMERIC && part.group && part.padding == '0') {
int group_size = part.base == 10 ? 3 : 4;
size_t group_size = part.base == 10 ? 3 : 4;
while (prefix.size() + buf.size() < part.width) {
if (buf.size() % (group_size + 1) == group_size)
buf += '_';

View file

@ -1228,7 +1228,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
if (ff.has_srst && ff.has_ce && ff.ce_over_srst) {
int srst = importDefSigSpec(ff.sig_srst, timestep-1).at(0);
std::vector<int> rval = importDefSigSpec(ff.val_srst, timestep-1);
int undef_srst;
int undef_srst = -1;
std::vector<int> undef_rval;
if (model_undef) {
undef_srst = importUndefSigSpec(ff.sig_srst, timestep-1).at(0);
@ -1242,7 +1242,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
if (ff.has_ce) {
int ce = importDefSigSpec(ff.sig_ce, timestep-1).at(0);
std::vector<int> old_q = importDefSigSpec(ff.sig_q, timestep-1);
int undef_ce;
int undef_ce = -1;
std::vector<int> undef_old_q;
if (model_undef) {
undef_ce = importUndefSigSpec(ff.sig_ce, timestep-1).at(0);
@ -1256,7 +1256,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
if (ff.has_srst && !(ff.has_ce && ff.ce_over_srst)) {
int srst = importDefSigSpec(ff.sig_srst, timestep-1).at(0);
std::vector<int> rval = importDefSigSpec(ff.val_srst, timestep-1);
int undef_srst;
int undef_srst = -1;
std::vector<int> undef_rval;
if (model_undef) {
undef_srst = importUndefSigSpec(ff.sig_srst, timestep-1).at(0);

View file

@ -1907,7 +1907,8 @@ void fstWriterClose(void *ctx)
int zfd;
int fourpack_duo = 0;
#ifndef __MINGW32__
char *fnam = (char *)malloc(strlen(xc->filename) + 5 + 1);
auto fnam_size = strlen(xc->filename) + 5 + 1;
char *fnam = (char *)malloc(fnam_size);
#endif
fixup_offs = ftello(xc->handle);
@ -1991,7 +1992,7 @@ void fstWriterClose(void *ctx)
fflush(xc->handle);
#ifndef __MINGW32__
sprintf(fnam, "%s.hier", xc->filename);
snprintf(fnam, fnam_size, "%s.hier", xc->filename);
unlink(fnam);
free(fnam);
#endif
@ -2616,7 +2617,7 @@ fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t ele
uint32_t i;
name_len = strlen(name);
elem_count_len = sprintf(elem_count_buf, "%" PRIu32, elem_count);
elem_count_len = snprintf(elem_count_buf, sizeof(elem_count_buf), "%" PRIu32, elem_count);
literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
@ -3579,7 +3580,8 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
if (!xc->fh) {
fst_off_t offs_cache = ftello(xc->f);
char *fnam = (char *)malloc(strlen(xc->filename) + 6 + 16 + 32 + 1);
auto fnam_size = strlen(xc->filename) + 6 + 16 + 32 + 1;
char *fnam = (char *)malloc(fnam_size);
unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN);
fst_off_t hl, uclen;
fst_off_t clen = 0;
@ -3594,7 +3596,7 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4;
}
sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc);
snprintf(fnam, fnam_size, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc);
fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET);
uclen = fstReaderUint64(xc->f);
#ifndef __MINGW32__
@ -4239,9 +4241,10 @@ int fstReaderInit(struct fstReaderContext *xc)
if (!seclen)
return (0); /* not finished compressing, this is a failed read */
hf = (char *)calloc(1, flen + 16 + 32 + 1);
size_t hf_size = flen + 16 + 32 + 1;
hf = (char *)calloc(1, hf_size);
sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc);
snprintf(hf, hf_size, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc);
fcomp = fopen(hf, "w+b");
if (!fcomp) {
fcomp = tmpfile_open(&xc->f_nam);
@ -4799,21 +4802,21 @@ int fstReaderIterBlocks2(void *ctx,
if (beg_tim) {
if (dumpvars_state == 1) {
wx_len = sprintf(wx_buf, "$end\n");
wx_len = snprintf(wx_buf, 6, "$end\n");
fstWritex(xc, wx_buf, wx_len);
dumpvars_state = 2;
}
wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", beg_tim);
wx_len = snprintf(wx_buf, 20, "#%" PRIu64 "\n", beg_tim);
fstWritex(xc, wx_buf, wx_len);
if (!dumpvars_state) {
wx_len = sprintf(wx_buf, "$dumpvars\n");
wx_len = snprintf(wx_buf, 11, "$dumpvars\n");
fstWritex(xc, wx_buf, wx_len);
dumpvars_state = 1;
}
}
if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) {
if (beg_tim == xc->blackout_times[cur_blackout]) {
wx_len = sprintf(wx_buf, "$dump%s $end\n",
wx_len = snprintf(wx_buf, 16, "$dump%s $end\n",
(xc->blackout_activity[cur_blackout++]) ? "on" : "off");
fstWritex(xc, wx_buf, wx_len);
}
@ -4914,7 +4917,7 @@ int fstReaderIterBlocks2(void *ctx,
clone_d[j] = srcdata[7 - j];
}
}
sprintf((char *)xc->temp_signal_value_buf, "%.16g", d);
snprintf((char *)xc->temp_signal_value_buf, 32, "%.16g", d);
value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
xc->temp_signal_value_buf);
}
@ -4936,7 +4939,7 @@ int fstReaderIterBlocks2(void *ctx,
}
fstVcdID(vcdid_buf, idx + 1);
wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf);
wx_len = snprintf(wx_buf, sizeof(wx_buf), "r%.16g %s\n", d, vcdid_buf);
fstWritex(xc, wx_buf, wx_len);
}
}
@ -5179,21 +5182,21 @@ int fstReaderIterBlocks2(void *ctx,
}
if (dumpvars_state == 1) {
wx_len = sprintf(wx_buf, "$end\n");
wx_len = snprintf(wx_buf, 6, "$end\n");
fstWritex(xc, wx_buf, wx_len);
dumpvars_state = 2;
}
wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", time_table[i]);
wx_len = snprintf(wx_buf, 20, "#%" PRIu64 "\n", time_table[i]);
fstWritex(xc, wx_buf, wx_len);
if (!dumpvars_state) {
wx_len = sprintf(wx_buf, "$dumpvars\n");
wx_len = snprintf(wx_buf, 11, "$dumpvars\n");
fstWritex(xc, wx_buf, wx_len);
dumpvars_state = 1;
}
if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) {
if (time_table[i] == xc->blackout_times[cur_blackout]) {
wx_len = sprintf(wx_buf, "$dump%s $end\n",
wx_len = snprintf(wx_buf, 16, "$dump%s $end\n",
(xc->blackout_activity[cur_blackout++]) ? "on" : "off");
fstWritex(xc, wx_buf, wx_len);
}
@ -5407,7 +5410,7 @@ int fstReaderIterBlocks2(void *ctx,
clone_d[j] = srcdata[7 - j];
}
}
sprintf((char *)xc->temp_signal_value_buf, "%.16g", d);
snprintf((char *)xc->temp_signal_value_buf, 32, "%.16g", d);
value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
xc->temp_signal_value_buf);
}
@ -5427,7 +5430,7 @@ int fstReaderIterBlocks2(void *ctx,
}
}
wx_len = sprintf(wx_buf, "r%.16g", d);
wx_len = snprintf(wx_buf, sizeof(wx_buf), "r%.16g", d);
fstWritex(xc, wx_buf, wx_len);
}
}
@ -5523,7 +5526,7 @@ static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle
}
}
sprintf((char *)buf, "%.16g", d);
snprintf((char *)buf, 32, "%.16g", d);
}
}
@ -5536,7 +5539,9 @@ char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facid
fst_off_t blkpos = 0, prev_blkpos;
uint64_t beg_tim, end_tim, beg_tim2, end_tim2;
int sectype;
#ifdef FST_DEBUG
unsigned int secnum = 0;
#endif
uint64_t seclen;
uint64_t tsec_uclen = 0, tsec_clen = 0;
uint64_t tsec_nitems;
@ -5620,7 +5625,9 @@ char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facid
}
blkpos += seclen;
#ifdef FST_DEBUG
secnum++;
#endif
}
xc->rvat_beg_tim = beg_tim;
@ -6041,7 +6048,7 @@ process_value:
}
}
sprintf(buf, "r%.16g", d);
snprintf(buf, 32, "r%.16g", d);
return (buf);
}
} else {

View file

@ -0,0 +1,37 @@
--- System.cc
+++ System.cc
@@ -43,7 +43,7 @@ static inline int memReadStat(int field)
pid_t pid = getpid();
int value;
- sprintf(name, "/proc/%d/statm", pid);
+ snprintf(name, 256, "/proc/%d/statm", pid);
FILE* in = fopen(name, "rb");
if (in == NULL) return 0;
@@ -60,7 +60,7 @@ static inline int memReadPeak(void)
char name[256];
pid_t pid = getpid();
- sprintf(name, "/proc/%d/status", pid);
+ snprintf(name, 256, "/proc/%d/status", pid);
FILE* in = fopen(name, "rb");
if (in == NULL) return 0;
--- Vec.h
+++ Vec.h
@@ -100,7 +100,13 @@ void vec<T,_Size>::capacity(Size min_cap) {
Size add = max((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2
const Size size_max = std::numeric_limits<Size>::max();
if ( ((size_max <= std::numeric_limits<int>::max()) && (add > size_max - cap))
- || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) )
+ || (
+#ifdef _DEFAULT_SOURCE
+ ((data = (T*)::reallocarray(data, (cap += add), sizeof(T))) == NULL)
+#else
+ ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL)
+#endif
+ && errno == ENOMEM) )
throw OutOfMemoryException();
}

View file

@ -17,3 +17,4 @@ patch -p0 < 00_PATCH_remove_zlib.patch
patch -p0 < 00_PATCH_no_fpu_control.patch
patch -p0 < 00_PATCH_typofixes.patch
patch -p0 < 00_PATCH_wasm.patch
patch -p0 < 00_PATCH_warnings.patch

View file

@ -43,7 +43,7 @@ static inline int memReadStat(int field)
pid_t pid = getpid();
int value;
sprintf(name, "/proc/%d/statm", pid);
snprintf(name, 256, "/proc/%d/statm", pid);
FILE* in = fopen(name, "rb");
if (in == NULL) return 0;
@ -60,7 +60,7 @@ static inline int memReadPeak(void)
char name[256];
pid_t pid = getpid();
sprintf(name, "/proc/%d/status", pid);
snprintf(name, 256, "/proc/%d/status", pid);
FILE* in = fopen(name, "rb");
if (in == NULL) return 0;

View file

@ -100,7 +100,13 @@ void vec<T,_Size>::capacity(Size min_cap) {
Size add = max((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2
const Size size_max = std::numeric_limits<Size>::max();
if ( ((size_max <= std::numeric_limits<int>::max()) && (add > size_max - cap))
|| (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) )
|| (
#ifdef _DEFAULT_SOURCE
((data = (T*)::reallocarray(data, (cap += add), sizeof(T))) == NULL)
#else
((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL)
#endif
&& errno == ENOMEM) )
throw OutOfMemoryException();
}

View file

@ -141,7 +141,7 @@ struct ExecPass : public Pass {
}
} else
log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.", args[argidx].c_str());
log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.\n", args[argidx].c_str());
}
}

View file

@ -361,7 +361,7 @@ void read_liberty_cellarea(dict<IdString, cell_area_t> &cell_area, string libert
if (cell->id != "cell" || cell->args.size() != 1)
continue;
LibertyAst *ar = cell->find("area");
const LibertyAst *ar = cell->find("area");
bool is_flip_flop = cell->find("ff") != nullptr;
if (ar != nullptr && !ar->value.empty())
cell_area["\\" + cell->args[0]] = {/*area=*/atof(ar->value.c_str()), is_flip_flop};

View file

@ -63,10 +63,12 @@ match add
define <bool> constport_signed param(add, !varport_A ? \A_SIGNED : \B_SIGNED).as_bool()
define <bool> varport_signed param(add, varport_A ? \A_SIGNED : \B_SIGNED).as_bool();
define <bool> offset_negative ((port(add, constport).bits().back() == State::S1) ^ (is_sub && varport_A))
define <bool> const_negative (constport_signed && (port(add, constport).bits().back() == State::S1))
define <bool> offset_negative ((is_sub && varport_A) ^ const_negative)
// checking some value boundaries as well:
// data[...-c +:W1] is fine for +/-var (pad at LSB, all data still accessible)
// data[...-c +:W1] is fine for any signed var (pad at LSB, all data still accessible)
// unsigned shift may underflow (eg var-3 with var<3) -> cannot be converted
// data[...+c +:W1] is only fine for +var(add) and var unsigned
// (+c cuts lower C bits, making them inaccessible, a signed var could try to access them)
// either its an add or the variable port is A (it must be positive)
@ -74,6 +76,8 @@ match add
// -> data[var+c +:W1] (with var signed) is illegal
filter !(!offset_negative && varport_signed)
// -> data >> (var-c) (with var unsigned) is illegal
filter !(offset_negative && !varport_signed)
// state-variables are assigned at the end only:
// shift the log2scale offset in-front of add to get true value: (var+c)<<N -> (var<<N)+(c<<N)

View file

@ -54,90 +54,35 @@ RTLIL::SigSpec find_any_lvalue(const RTLIL::Process *proc)
}
void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, RTLIL::SigSpec clk, bool clk_polarity,
std::map<RTLIL::SigSpec, std::set<RTLIL::SyncRule*>> &async_rules, RTLIL::Process *proc)
std::vector<std::pair<RTLIL::SigSpec, RTLIL::SyncRule*>> &async_rules, RTLIL::Process *proc)
{
// A signal should be set/cleared if there is a load trigger that is enabled
// such that the load value is 1/0 and it is the highest priority trigger
RTLIL::SigSpec sig_sr_set = RTLIL::SigSpec(0, sig_d.size());
RTLIL::SigSpec sig_sr_clr = RTLIL::SigSpec(0, sig_d.size());
for (auto &it : async_rules)
// Reverse iterate through the rules as the first ones are the highest priority
// so need to be at the top of the mux trees
for (auto it = async_rules.crbegin(); it != async_rules.crend(); it++)
{
RTLIL::SigSpec sync_value = it.first;
RTLIL::SigSpec sync_value_inv;
RTLIL::SigSpec sync_high_signals;
RTLIL::SigSpec sync_low_signals;
const auto& [sync_value, rule] = *it;
const auto pos_trig = rule->type == RTLIL::SyncType::ST1 ? rule->signal : mod->Not(NEW_ID, rule->signal);
for (auto &it2 : it.second)
if (it2->type == RTLIL::SyncType::ST0)
sync_low_signals.append(it2->signal);
else if (it2->type == RTLIL::SyncType::ST1)
sync_high_signals.append(it2->signal);
else
log_abort();
// If pos_trig is true, we have priority at this point in the tree so
// set a bit if sync_value has a set bit. Otherwise, defer to the rest
// of the priority tree
sig_sr_set = mod->Mux(NEW_ID, sig_sr_set, sync_value, pos_trig);
if (sync_low_signals.size() > 1) {
RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($reduce_or));
cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
cell->parameters[ID::A_WIDTH] = RTLIL::Const(sync_low_signals.size());
cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
cell->setPort(ID::A, sync_low_signals);
cell->setPort(ID::Y, sync_low_signals = mod->addWire(NEW_ID));
}
if (sync_low_signals.size() > 0) {
RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($not));
cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
cell->parameters[ID::A_WIDTH] = RTLIL::Const(sync_low_signals.size());
cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
cell->setPort(ID::A, sync_low_signals);
cell->setPort(ID::Y, mod->addWire(NEW_ID));
sync_high_signals.append(cell->getPort(ID::Y));
}
if (sync_high_signals.size() > 1) {
RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($reduce_or));
cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
cell->parameters[ID::A_WIDTH] = RTLIL::Const(sync_high_signals.size());
cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
cell->setPort(ID::A, sync_high_signals);
cell->setPort(ID::Y, sync_high_signals = mod->addWire(NEW_ID));
}
RTLIL::Cell *inv_cell = mod->addCell(NEW_ID, ID($not));
inv_cell->parameters[ID::A_SIGNED] = RTLIL::Const(0);
inv_cell->parameters[ID::A_WIDTH] = RTLIL::Const(sig_d.size());
inv_cell->parameters[ID::Y_WIDTH] = RTLIL::Const(sig_d.size());
inv_cell->setPort(ID::A, sync_value);
inv_cell->setPort(ID::Y, sync_value_inv = mod->addWire(NEW_ID, sig_d.size()));
RTLIL::Cell *mux_set_cell = mod->addCell(NEW_ID, ID($mux));
mux_set_cell->parameters[ID::WIDTH] = RTLIL::Const(sig_d.size());
mux_set_cell->setPort(ID::A, sig_sr_set);
mux_set_cell->setPort(ID::B, sync_value);
mux_set_cell->setPort(ID::S, sync_high_signals);
mux_set_cell->setPort(ID::Y, sig_sr_set = mod->addWire(NEW_ID, sig_d.size()));
RTLIL::Cell *mux_clr_cell = mod->addCell(NEW_ID, ID($mux));
mux_clr_cell->parameters[ID::WIDTH] = RTLIL::Const(sig_d.size());
mux_clr_cell->setPort(ID::A, sig_sr_clr);
mux_clr_cell->setPort(ID::B, sync_value_inv);
mux_clr_cell->setPort(ID::S, sync_high_signals);
mux_clr_cell->setPort(ID::Y, sig_sr_clr = mod->addWire(NEW_ID, sig_d.size()));
// Same deal with clear bit
const auto sync_value_inv = mod->Not(NEW_ID, sync_value);
sig_sr_clr = mod->Mux(NEW_ID, sig_sr_clr, sync_value_inv, pos_trig);
}
std::stringstream sstr;
sstr << "$procdff$" << (autoidx++);
RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($dffsr));
RTLIL::Cell *cell = mod->addDffsr(sstr.str(), clk, sig_sr_set, sig_sr_clr, sig_d, sig_q, clk_polarity);
cell->attributes = proc->attributes;
cell->parameters[ID::WIDTH] = RTLIL::Const(sig_d.size());
cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity, 1);
cell->parameters[ID::SET_POLARITY] = RTLIL::Const(true, 1);
cell->parameters[ID::CLR_POLARITY] = RTLIL::Const(true, 1);
cell->setPort(ID::D, sig_d);
cell->setPort(ID::Q, sig_q);
cell->setPort(ID::CLK, clk);
cell->setPort(ID::SET, sig_sr_set);
cell->setPort(ID::CLR, sig_sr_clr);
log(" created %s cell `%s' with %s edge clock and multiple level-sensitive resets.\n",
cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative");
@ -204,7 +149,6 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
while (1)
{
RTLIL::SigSpec sig = find_any_lvalue(proc);
bool free_sync_level = false;
if (sig.size() == 0)
break;
@ -213,13 +157,17 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
mod->name.c_str(), log_signal(sig), mod->name.c_str(), proc->name.c_str());
RTLIL::SigSpec insig = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
RTLIL::SigSpec rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
RTLIL::SyncRule *sync_level = NULL;
RTLIL::SyncRule *sync_edge = NULL;
RTLIL::SyncRule *sync_always = NULL;
bool global_clock = false;
std::map<RTLIL::SigSpec, std::set<RTLIL::SyncRule*>> many_async_rules;
// A priority ordered set of rules, pairing the value to be assigned for
// that rule to the rule
std::vector<std::pair<RTLIL::SigSpec, RTLIL::SyncRule*>> async_rules;
// Needed when the async rules are collapsed into one as async_rules
// works with pointers to SyncRule
RTLIL::SyncRule single_async_rule;
for (auto sync : proc->syncs)
for (auto &action : sync->actions)
@ -228,14 +176,9 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
continue;
if (sync->type == RTLIL::SyncType::ST0 || sync->type == RTLIL::SyncType::ST1) {
if (sync_level != NULL && sync_level != sync) {
// log_error("Multiple level sensitive events found for this signal!\n");
many_async_rules[rstval].insert(sync_level);
rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
}
rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
RTLIL::SigSpec rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
sig.replace(action.first, action.second, &rstval);
sync_level = sync;
async_rules.emplace_back(rstval, sync);
}
else if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
if (sync_edge != NULL && sync_edge != sync)
@ -260,59 +203,51 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
action.first.remove2(sig, &action.second);
}
if (many_async_rules.size() > 0)
// If all async rules assign the same value, priority ordering between
// them doesn't matter so they can be collapsed together into one rule
// with the disjunction of triggers
if (!async_rules.empty() &&
std::all_of(async_rules.begin(), async_rules.end(), [&](auto& p) {
return p.first == async_rules.front().first;
}))
{
many_async_rules[rstval].insert(sync_level);
if (many_async_rules.size() == 1)
{
sync_level = new RTLIL::SyncRule;
sync_level->type = RTLIL::SyncType::ST1;
sync_level->signal = mod->addWire(NEW_ID);
sync_level->actions.push_back(RTLIL::SigSig(sig, rstval));
free_sync_level = true;
const auto rstval = async_rules.front().first;
RTLIL::SigSpec inputs, compare;
for (auto &it : many_async_rules[rstval]) {
inputs.append(it->signal);
compare.append(it->type == RTLIL::SyncType::ST0 ? RTLIL::State::S1 : RTLIL::State::S0);
}
log_assert(inputs.size() == compare.size());
// The trigger is the disjunction of existing triggers
// (with appropriate negation)
RTLIL::SigSpec triggers;
for (const auto &[_, it] : async_rules)
triggers.append(it->type == RTLIL::SyncType::ST1 ? it->signal : mod->Not(NEW_ID, it->signal));
RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($ne));
cell->parameters[ID::A_SIGNED] = RTLIL::Const(false, 1);
cell->parameters[ID::B_SIGNED] = RTLIL::Const(false, 1);
cell->parameters[ID::A_WIDTH] = RTLIL::Const(inputs.size());
cell->parameters[ID::B_WIDTH] = RTLIL::Const(inputs.size());
cell->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
cell->setPort(ID::A, inputs);
cell->setPort(ID::B, compare);
cell->setPort(ID::Y, sync_level->signal);
// Put this into the dummy sync rule so it can be treated the same
// as ones coming from the module
single_async_rule.type = RTLIL::SyncType::ST1;
single_async_rule.signal = mod->ReduceOr(NEW_ID, triggers);
single_async_rule.actions.push_back(RTLIL::SigSig(sig, rstval));
many_async_rules.clear();
}
else
{
rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
sync_level = NULL;
}
// Replace existing rules with this new rule
async_rules.clear();
async_rules.emplace_back(rstval, &single_async_rule);
}
SigSpec sig_q = sig;
ce.assign_map.apply(insig);
ce.assign_map.apply(rstval);
ce.assign_map.apply(sig);
if (rstval == sig && sync_level) {
if (sync_level->type == RTLIL::SyncType::ST1)
insig = mod->Mux(NEW_ID, insig, sig, sync_level->signal);
// If the reset value assigns the reg to itself, add this as part of
// the input signal and delete the rule
if (async_rules.size() == 1 && async_rules.front().first == sig) {
const auto& [_, rule] = async_rules.front();
if (rule->type == RTLIL::SyncType::ST1)
insig = mod->Mux(NEW_ID, insig, sig, rule->signal);
else
insig = mod->Mux(NEW_ID, sig, insig, sync_level->signal);
rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
sync_level = NULL;
insig = mod->Mux(NEW_ID, sig, insig, rule->signal);
async_rules.clear();
}
if (sync_always) {
if (sync_edge || sync_level || many_async_rules.size() > 0)
if (sync_edge || !async_rules.empty())
log_error("Mixed always event with edge and/or level sensitive events!\n");
log(" created direct connection (no actual register cell created).\n");
mod->connect(RTLIL::SigSig(sig, insig));
@ -322,28 +257,34 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
if (!sync_edge && !global_clock)
log_error("Missing edge-sensitive event for this signal!\n");
if (many_async_rules.size() > 0)
// More than one reset value so we derive a dffsr formulation
if (async_rules.size() > 1)
{
log_warning("Complex async reset for dff `%s'.\n", log_signal(sig));
gen_dffsr_complex(mod, insig, sig, sync_edge->signal, sync_edge->type == RTLIL::SyncType::STp, many_async_rules, proc);
gen_dffsr_complex(mod, insig, sig, sync_edge->signal, sync_edge->type == RTLIL::SyncType::STp, async_rules, proc);
return;
}
else if (!rstval.is_fully_const() && !ce.eval(rstval))
// If there is a reset condition in the async rules, use it
SigSpec rstval = async_rules.empty() ? RTLIL::SigSpec(RTLIL::State::Sz, sig.size()) : async_rules.front().first;
RTLIL::SyncRule* sync_level = async_rules.empty() ? nullptr : async_rules.front().second;
ce.assign_map.apply(rstval);
if (!rstval.is_fully_const() && !ce.eval(rstval))
{
log_warning("Async reset value `%s' is not constant!\n", log_signal(rstval));
gen_aldff(mod, insig, rstval, sig_q,
sync_edge->type == RTLIL::SyncType::STp,
sync_level && sync_level->type == RTLIL::SyncType::ST1,
sync_edge->signal, sync_level->signal, proc);
return;
}
else
gen_dff(mod, insig, rstval.as_const(), sig_q,
sync_edge && sync_edge->type == RTLIL::SyncType::STp,
sync_level && sync_level->type == RTLIL::SyncType::ST1,
sync_edge ? sync_edge->signal : SigSpec(),
sync_level ? &sync_level->signal : NULL, proc);
if (free_sync_level)
delete sync_level;
gen_dff(mod, insig, rstval.as_const(), sig_q,
sync_edge && sync_edge->type == RTLIL::SyncType::STp,
sync_level && sync_level->type == RTLIL::SyncType::ST1,
sync_edge ? sync_edge->signal : SigSpec(),
sync_level ? &sync_level->signal : NULL, proc);
}
}

View file

@ -1718,7 +1718,7 @@ struct AbcPass : public Pass {
show_tempdir = true;
}
size_t argidx, g_argidx;
size_t argidx, g_argidx = -1;
bool g_arg_from_cmd = false;
#if defined(__wasm)
const char *pwd = ".";

View file

@ -76,7 +76,7 @@ static void logmap_all()
logmap(ID($_DFFSR_PPP_));
}
static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol)
static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::string &pin_name, bool &pin_pol)
{
if (cell == nullptr || attr == nullptr || attr->value.empty())
return false;
@ -115,9 +115,9 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
return false;
}
static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, std::vector<std::string> &dont_use_cells)
static void find_cell(const LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, std::vector<std::string> &dont_use_cells)
{
LibertyAst *best_cell = nullptr;
const LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
bool best_cell_noninv = false;
@ -131,7 +131,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (cell->id != "cell" || cell->args.size() != 1)
continue;
LibertyAst *dn = cell->find("dont_use");
const LibertyAst *dn = cell->find("dont_use");
if (dn != nullptr && dn->value == "true")
continue;
@ -147,7 +147,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (dont_use)
continue;
LibertyAst *ff = cell->find("ff");
const LibertyAst *ff = cell->find("ff");
if (ff == nullptr)
continue;
@ -174,7 +174,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
this_cell_ports[cell_next_pin] = 'D';
double area = 0;
LibertyAst *ar = cell->find("area");
const LibertyAst *ar = cell->find("area");
if (ar != nullptr && !ar->value.empty())
area = atof(ar->value.c_str());
@ -186,7 +186,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (pin->id != "pin" || pin->args.size() != 1)
continue;
LibertyAst *dir = pin->find("direction");
const LibertyAst *dir = pin->find("direction");
if (dir == nullptr || dir->value == "internal")
continue;
num_pins++;
@ -194,7 +194,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0)
goto continue_cell_loop;
LibertyAst *func = pin->find("function");
const LibertyAst *func = pin->find("function");
if (dir->value == "output" && func != nullptr) {
std::string value = func->value;
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))
@ -239,9 +239,9 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has
}
}
static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, std::vector<std::string> &dont_use_cells)
static void find_cell_sr(const LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, std::vector<std::string> &dont_use_cells)
{
LibertyAst *best_cell = nullptr;
const LibertyAst *best_cell = nullptr;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
bool best_cell_noninv = false;
@ -255,7 +255,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (cell->id != "cell" || cell->args.size() != 1)
continue;
LibertyAst *dn = cell->find("dont_use");
const LibertyAst *dn = cell->find("dont_use");
if (dn != nullptr && dn->value == "true")
continue;
@ -271,7 +271,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (dont_use)
continue;
LibertyAst *ff = cell->find("ff");
const LibertyAst *ff = cell->find("ff");
if (ff == nullptr)
continue;
@ -294,7 +294,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
this_cell_ports[cell_next_pin] = 'D';
double area = 0;
LibertyAst *ar = cell->find("area");
const LibertyAst *ar = cell->find("area");
if (ar != nullptr && !ar->value.empty())
area = atof(ar->value.c_str());
@ -306,7 +306,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (pin->id != "pin" || pin->args.size() != 1)
continue;
LibertyAst *dir = pin->find("direction");
const LibertyAst *dir = pin->find("direction");
if (dir == nullptr || dir->value == "internal")
continue;
num_pins++;
@ -314,7 +314,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool
if (dir->value == "input" && this_cell_ports.count(pin->args[0]) == 0)
goto continue_cell_loop;
LibertyAst *func = pin->find("function");
const LibertyAst *func = pin->find("function");
if (dir->value == "output" && func != nullptr) {
std::string value = func->value;
for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t"))

View file

@ -32,9 +32,6 @@
using namespace Yosys;
std::set<std::string> LibertyAst::blacklist;
std::set<std::string> LibertyAst::whitelist;
LibertyAst::~LibertyAst()
{
for (auto child : children)
@ -42,7 +39,7 @@ LibertyAst::~LibertyAst()
children.clear();
}
LibertyAst *LibertyAst::find(std::string name)
const LibertyAst *LibertyAst::find(std::string name) const
{
for (auto child : children)
if (child->id == name)
@ -50,7 +47,7 @@ LibertyAst *LibertyAst::find(std::string name)
return NULL;
}
void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_ok)
void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string indent, std::string path, bool path_ok) const
{
if (whitelist.count(path + "/*") > 0)
path_ok = true;
@ -77,7 +74,7 @@ void LibertyAst::dump(FILE *f, std::string indent, std::string path, bool path_o
if (!children.empty()) {
fprintf(f, " {\n");
for (size_t i = 0; i < children.size(); i++)
children[i]->dump(f, indent + " ", path, path_ok);
children[i]->dump(f, blacklist, whitelist, indent + " ", path, path_ok);
fprintf(f, "%s}\n", indent.c_str());
} else
fprintf(f, " ;\n");
@ -406,9 +403,9 @@ void LibertyParser::error(const std::string &str)
/**** END: http://svn.clairexen.net/tools/trunk/examples/check.h ****/
LibertyAst *find_non_null(LibertyAst *node, const char *name)
const LibertyAst *find_non_null(const LibertyAst *node, const char *name)
{
LibertyAst *ret = node->find(name);
const LibertyAst *ret = node->find(name);
if (ret == NULL)
fprintf(stderr, "Error: expected to find `%s' node.\n", name);
return ret;
@ -455,7 +452,7 @@ std::string func2vl(std::string str)
return str;
}
void event2vl(LibertyAst *ast, std::string &edge, std::string &expr)
void event2vl(const LibertyAst *ast, std::string &edge, std::string &expr)
{
edge.clear();
expr.clear();
@ -489,7 +486,7 @@ void clear_preset_var(std::string var, std::string type)
}
}
void gen_verilogsim_cell(LibertyAst *ast)
void gen_verilogsim_cell(const LibertyAst *ast)
{
if (ast->find("statetable") != NULL)
return;
@ -522,8 +519,8 @@ void gen_verilogsim_cell(LibertyAst *ast)
if (child->id != "pin")
continue;
CHECK_NV(child->args.size(), == 1);
LibertyAst *dir = find_non_null(child, "direction");
LibertyAst *func = child->find("function");
const LibertyAst *dir = find_non_null(child, "direction");
const LibertyAst *func = child->find("function");
printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str());
if (func != NULL)
printf(" assign %s = %s; // %s\n", child->args[0].c_str(), func2vl(func->value).c_str(), func->value.c_str());
@ -649,7 +646,7 @@ void gen_verilogsim_cell(LibertyAst *ast)
printf("endmodule\n");
}
void gen_verilogsim(LibertyAst *ast)
void gen_verilogsim(const LibertyAst *ast)
{
CHECK_COND(ast->id == "library");
@ -668,6 +665,7 @@ void usage()
int main(int argc, char **argv)
{
bool flag_verilogsim = false;
std::set<std::string> whitelist, blacklist;
if (argc > 3)
usage();
@ -678,26 +676,26 @@ int main(int argc, char **argv)
flag_verilogsim = true;
if (!strcmp(argv[1], "-") || !strcmp(argv[1], "-verilogsim"))
{
LibertyAst::whitelist.insert("/library");
LibertyAst::whitelist.insert("/library/cell");
LibertyAst::whitelist.insert("/library/cell/area");
LibertyAst::whitelist.insert("/library/cell/cell_footprint");
LibertyAst::whitelist.insert("/library/cell/dont_touch");
LibertyAst::whitelist.insert("/library/cell/dont_use");
LibertyAst::whitelist.insert("/library/cell/ff");
LibertyAst::whitelist.insert("/library/cell/ff/*");
LibertyAst::whitelist.insert("/library/cell/latch");
LibertyAst::whitelist.insert("/library/cell/latch/*");
LibertyAst::whitelist.insert("/library/cell/pin");
LibertyAst::whitelist.insert("/library/cell/pin/clock");
LibertyAst::whitelist.insert("/library/cell/pin/direction");
LibertyAst::whitelist.insert("/library/cell/pin/driver_type");
LibertyAst::whitelist.insert("/library/cell/pin/function");
LibertyAst::whitelist.insert("/library/cell/pin_opposite");
LibertyAst::whitelist.insert("/library/cell/pin/state_function");
LibertyAst::whitelist.insert("/library/cell/pin/three_state");
LibertyAst::whitelist.insert("/library/cell/statetable");
LibertyAst::whitelist.insert("/library/cell/statetable/*");
whitelist.insert("/library");
whitelist.insert("/library/cell");
whitelist.insert("/library/cell/area");
whitelist.insert("/library/cell/cell_footprint");
whitelist.insert("/library/cell/dont_touch");
whitelist.insert("/library/cell/dont_use");
whitelist.insert("/library/cell/ff");
whitelist.insert("/library/cell/ff/*");
whitelist.insert("/library/cell/latch");
whitelist.insert("/library/cell/latch/*");
whitelist.insert("/library/cell/pin");
whitelist.insert("/library/cell/pin/clock");
whitelist.insert("/library/cell/pin/direction");
whitelist.insert("/library/cell/pin/driver_type");
whitelist.insert("/library/cell/pin/function");
whitelist.insert("/library/cell/pin_opposite");
whitelist.insert("/library/cell/pin/state_function");
whitelist.insert("/library/cell/pin/three_state");
whitelist.insert("/library/cell/statetable");
whitelist.insert("/library/cell/statetable/*");
}
else
{
@ -723,10 +721,10 @@ int main(int argc, char **argv)
if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n' || *p == '#') {
if (!id.empty()) {
if (mode == '-')
LibertyAst::blacklist.insert(id);
blacklist.insert(id);
else
if (mode == '+')
LibertyAst::whitelist.insert(id);
whitelist.insert(id);
else
goto syntax_error;
}
@ -764,7 +762,7 @@ int main(int argc, char **argv)
if (flag_verilogsim)
gen_verilogsim(parser.ast);
else
parser.ast->dump(stdout);
parser.ast->dump(stdout, blacklist, whitelist);
}
if (argc == 3)

View file

@ -33,32 +33,35 @@ namespace Yosys
std::vector<std::string> args;
std::vector<LibertyAst*> children;
~LibertyAst();
LibertyAst *find(std::string name);
void dump(FILE *f, std::string indent = "", std::string path = "", bool path_ok = false);
static std::set<std::string> blacklist;
static std::set<std::string> whitelist;
const LibertyAst *find(std::string name) const;
typedef std::set<std::string> sieve;
void dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string indent = "", std::string path = "", bool path_ok = false) const;
};
struct LibertyParser
class LibertyParser
{
private:
std::istream &f;
int line;
LibertyAst *ast;
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
~LibertyParser() { if (ast) delete ast; }
/* lexer return values:
'v': identifier, string, array range [...] -> str holds the token string
'n': newline
anything else is a single character.
*/
/* lexer return values:
'v': identifier, string, array range [...] -> str holds the token string
'n': newline
anything else is a single character.
*/
int lexer(std::string &str);
LibertyAst *parse();
LibertyAst *parse();
void error();
void error(const std::string &str);
void error(const std::string &str);
public:
const LibertyAst *ast;
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
~LibertyParser() { if (ast) delete ast; }
};
}
#endif

View file

@ -371,6 +371,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $shl (A, B, Y)
//-
//- A logical shift-left operation. This corresponds to the Verilog '<<' operator.
//-
module \$shl (A, B, Y);
parameter A_SIGNED = 0;
@ -395,6 +401,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $shr (A, B, Y)
//-
//- A logical shift-right operation. This corresponds to the Verilog '>>' operator.
//-
module \$shr (A, B, Y);
parameter A_SIGNED = 0;
@ -419,6 +431,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $sshl (A, B, Y)
//-
//- An arithmatic shift-left operation.
//- This corresponds to the Verilog '<<<' operator.
//-
module \$sshl (A, B, Y);
parameter A_SIGNED = 0;
@ -443,6 +462,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $sshr (A, B, Y)
//-
//- An arithmatic shift-right operation.
//- This corresponds to the Verilog '>>>' operator.
//-
module \$sshr (A, B, Y);
parameter A_SIGNED = 0;
@ -639,6 +665,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $lt (A, B, Y)
//-
//- A less-than comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '<' operator.
//-
module \$lt (A, B, Y);
parameter A_SIGNED = 0;
@ -663,6 +696,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $le (A, B, Y)
//-
//- A less-than-or-equal-to comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '<=' operator.
//-
module \$le (A, B, Y);
parameter A_SIGNED = 0;
@ -687,6 +727,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $eq (A, B, Y)
//-
//- An equality comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '==' operator.
//-
module \$eq (A, B, Y);
parameter A_SIGNED = 0;
@ -711,6 +758,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $ne (A, B, Y)
//-
//- An inequality comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '!=' operator.
//-
module \$ne (A, B, Y);
parameter A_SIGNED = 0;
@ -735,6 +789,15 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $eqx (A, B, Y)
//-
//- An exact equality comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '===' operator.
//- Unlike equality comparison that can give 'x' as output,
//- an exact equality comparison will strictly give '0' or '1' as output.
//-
module \$eqx (A, B, Y);
parameter A_SIGNED = 0;
@ -759,6 +822,15 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $nex (A, B, Y)
//-
//- An exact inequality comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '!==' operator.
//- Unlike inequality comparison that can give 'x' as output,
//- an exact inequality comparison will strictly give '0' or '1' as output.
//-
module \$nex (A, B, Y);
parameter A_SIGNED = 0;
@ -783,6 +855,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $ge (A, B, Y)
//-
//- A greater-than-or-equal-to comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '>=' operator.
//-
module \$ge (A, B, Y);
parameter A_SIGNED = 0;
@ -807,6 +886,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $gt (A, B, Y)
//-
//- A greater-than comparison between inputs 'A' and 'B'.
//- This corresponds to the Verilog '>' operator.
//-
module \$gt (A, B, Y);
parameter A_SIGNED = 0;
@ -831,6 +917,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $add (A, B, Y)
//-
//- Addition of inputs 'A' and 'B'. This corresponds to the Verilog '+' operator.
//-
module \$add (A, B, Y);
parameter A_SIGNED = 0;
@ -855,6 +947,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $sub (A, B, Y)
//-
//- Subtraction between inputs 'A' and 'B'.
//- This corresponds to the Verilog '-' operator.
//-
module \$sub (A, B, Y);
parameter A_SIGNED = 0;
@ -879,6 +978,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $mul (A, B, Y)
//-
//- Multiplication of inputs 'A' and 'B'.
//- This corresponds to the Verilog '*' operator.
//-
module \$mul (A, B, Y);
parameter A_SIGNED = 0;
@ -1191,6 +1297,14 @@ endgenerate
endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $pow (A, B, Y)
//-
//- Exponentiation of an input (Y = A ** B).
//- This corresponds to the Verilog '**' operator.
//-
`ifndef SIMLIB_NOPOW
module \$pow (A, B, Y);
@ -1222,6 +1336,12 @@ endmodule
`endif
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $logic_not (A, Y)
//-
//- A logical inverter. This corresponds to the Verilog unary prefix '!' operator.
//-
module \$logic_not (A, Y);
parameter A_SIGNED = 0;
@ -1243,6 +1363,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $logic_and (A, B, Y)
//-
//- A logical AND. This corresponds to the Verilog '&&' operator.
//-
module \$logic_and (A, B, Y);
parameter A_SIGNED = 0;
@ -1267,6 +1393,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $logic_or (A, B, Y)
//-
//- A logical OR. This corresponds to the Verilog '||' operator.
//-
module \$logic_or (A, B, Y);
parameter A_SIGNED = 0;
@ -1306,6 +1438,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $concat (A, B, Y)
//-
//- Concatenation of inputs into a single output ( Y = {B, A} ).
//-
module \$concat (A, B, Y);
parameter A_WIDTH = 0;
@ -1321,6 +1459,12 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $mux (A, B, S, Y)
//-
//- Multiplexer i.e selecting between two inputs based on select signal.
//-
module \$mux (A, B, S, Y);
parameter WIDTH = 0;
@ -1396,6 +1540,13 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $demux (A, S, Y)
//-
//- Demultiplexer i.e routing single input to several outputs based on select signal.
//- Unselected outputs are driven to zero.
//-
module \$demux (A, S, Y);
parameter WIDTH = 1;
@ -1460,6 +1611,14 @@ endmodule
// --------------------------------------------------------
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
//- $tribuf (A, EN, Y)
//-
//- A tri-state buffer.
//- This buffer conditionally drives the output with the value of the input
//- based on the enable signal.
//-
module \$tribuf (A, EN, Y);
parameter WIDTH = 0;

View file

@ -618,6 +618,21 @@ module OSER4(D3, D2, D1, D0, TX1, TX0, FCLK, PCLK, RESET, Q1, Q0);
parameter HWL = "false";
endmodule
module OSER4_MEM (Q0, Q1, D0, D1, D2, D3, TX0, TX1, PCLK, FCLK, TCLK, RESET) ;
parameter GSREN = "";
parameter LSREN = "";
parameter HWL = "";
parameter TCLK_SOURCE = "";
parameter TXCLK_POL = "";
input D0, D1, D2, D3;
input TX0, TX1;
input PCLK, FCLK, TCLK, RESET;
output Q0, Q1;
parameter ID = "";
endmodule
module OSER8(D7, D6, D5, D4, D3, D2, D1, D0, TX3, TX2, TX1, TX0, FCLK, PCLK, RESET, Q1, Q0);
output Q1;
output Q0;
@ -729,6 +744,21 @@ RESET, CALIB, D);
parameter LSREN = "true";
endmodule
module IDES4_MEM (Q0, Q1, Q2, Q3, D, WADDR,
RADDR, CALIB, PCLK, FCLK, ICLK, RESET) ;
parameter GSREN = "";
parameter LSREN = "";
input D, ICLK, FCLK, PCLK;
input [2:0] WADDR;
input [2:0] RADDR;
input CALIB, RESET;
output Q0,Q1,Q2,Q3;
parameter ID = "";
endmodule
module IDES8(Q7, Q6, Q5, Q4, Q3, Q2, Q1, Q0, FCLK, PCLK,
RESET, CALIB, D);
input D;
@ -842,6 +872,28 @@ module IDDRC(D, CLK, CLEAR, Q0, Q1);
parameter Q1_INIT = 1'b0;
endmodule
module DQS(DQSR90, DQSW0, DQSW270, RPOINT, WPOINT, RVALID, RBURST, RFLAG,
WFLAG, DQSIN, DLLSTEP, WSTEP, READ, RLOADN, RMOVE, RDIR, WLOADN, WMOVE, WDIR,
HOLD, RCLKSEL, PCLK, FCLK, RESET) ;
input DQSIN,PCLK,FCLK,RESET;
input [3:0] READ;
input [2:0] RCLKSEL;
input [7:0] DLLSTEP;
input [7:0] WSTEP;
input RLOADN, RMOVE, RDIR, WLOADN, WMOVE, WDIR, HOLD;
output DQSR90, DQSW0, DQSW270;
output [2:0] RPOINT, WPOINT;
output RVALID,RBURST, RFLAG, WFLAG;
parameter FIFO_MODE_SEL = "";
parameter RD_PNTR = "";
parameter DQS_MODE = "";
parameter HWL = "";
parameter GSREN = "";
parameter ID = "";
endmodule
(* blackbox *)
module ODDR(D0, D1, TX, CLK, Q0, Q1);
input D0;

View file

@ -0,0 +1,31 @@
OBJS += techlibs/nanoxplore/synth_nanoxplore.o
OBJS += techlibs/nanoxplore/nx_carry.o
# Techmap
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/arith_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/brams_init.vh))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/brams_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/brams.txt))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_bb.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_bb_l.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_bb_m.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_bb_u.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_sim.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_sim_l.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_sim_m.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_sim_u.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_wrap.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_wrap_l.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_wrap_m.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_wrap_u.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/io_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/latches_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_init.vh))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_rams_l.txt))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_rams_m.txt))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_rams_u.txt))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_rams_map_l.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_rams_map_m.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/rf_rams_map_u.v))

View file

@ -0,0 +1,76 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2024 Miodrag Milanovic <micko@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
(* techmap_celltype = "$alu" *)
module _80_nx_cy_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;
(* force_downto *)
wire [Y_WIDTH-1:0] COx;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
(* 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));
(* force_downto *)
wire [Y_WIDTH-1:0] AA = A_buf;
(* force_downto *)
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice
NX_CY_1BIT #(.first(i==0))
alu_i (
.CI(i==0 ? CI : COx[i-1]),
.A(AA[i]),
.B(BB[i]),
.S(Y[i]),
.CO(COx[i])
);
end: slice
endgenerate
NX_CY_1BIT alu_cout(
.CI(COx[Y_WIDTH-1]),
.A(1'b0),
.B(1'b0),
.S(CO[Y_WIDTH-1])
);
/* End implementation */
assign X = AA ^ BB;
endmodule

View file

@ -0,0 +1,50 @@
ram block $__NX_RAM_ {
option "STD_MODE" "NOECC_48kx1" {
# only 32k used
abits 15;
widths 1 per_port;
}
option "STD_MODE" "NOECC_24kx2" {
# only 16k used
abits 14;
widths 2 per_port;
}
ifndef IS_NG_MEDIUM {
option "STD_MODE" "NOECC_16kx3" {
abits 14;
widths 3 per_port;
}
}
option "STD_MODE" "NOECC_12kx4" {
# only 8k used
abits 13;
widths 4 per_port;
}
ifndef IS_NG_MEDIUM {
option "STD_MODE" "NOECC_8kx6" {
abits 13;
widths 6 per_port;
}
}
option "STD_MODE" "NOECC_6kx8" {
# only 4k used
abits 12;
widths 8 per_port;
}
option "STD_MODE" "NOECC_4kx12" {
abits 12;
widths 12 per_port;
}
option "STD_MODE" "NOECC_2kx24" {
abits 11;
widths 24 per_port;
}
cost 64;
init no_undef;
port srsw "A" "B" {
clock anyedge;
clken;
rdwr no_change;
rdinit none;
}
}

View file

@ -0,0 +1,23 @@
function [409600-1:0] bram_init_to_string;
input [49152-1:0] array;
input integer blocks;
input integer width;
reg [409600-1:0] temp; // (49152+2048)*8 48K bit data + 2k commas
reg [24-1:0] temp2;
integer i;
integer j;
begin
temp = "";
for (i = 0; i < 2048; i = i + 1) begin
if (i != 0) begin
temp = {temp, ","};
end
temp2 = 24'b0;
for (j = 0; j < blocks; j = j + 1) begin
temp2[j*width +: width] = array[{j, i[10:0]}*width +: width];
end
temp = {temp, $sformatf("%b",temp2[23:0])};
end
bram_init_to_string = temp;
end
endfunction

View file

@ -0,0 +1,84 @@
module $__NX_RAM_ (...);
parameter INIT = 0;
parameter OPTION_STD_MODE = "NOECC_24kx2";
parameter PORT_A_WIDTH = 24;
parameter PORT_B_WIDTH = 24;
parameter PORT_A_CLK_POL = 1;
input PORT_A_CLK;
input PORT_A_CLK_EN;
input PORT_A_WR_EN;
input [15:0] PORT_A_ADDR;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
wire [24-1:0] A_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
parameter PORT_B_CLK_POL = 1;
input PORT_B_CLK;
input PORT_B_CLK_EN;
input PORT_B_WR_EN;
input [15:0] PORT_B_ADDR;
input [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;
wire [24-1:0] B_DATA;
output [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;
`include "brams_init.vh"
localparam raw_config1_val = OPTION_STD_MODE == "NOECC_48kx1" ? 16'b0000000000000000:
OPTION_STD_MODE == "NOECC_24kx2" ? 16'b0000001001001001:
OPTION_STD_MODE == "NOECC_16kx3" ? 16'b0000110110110110:
OPTION_STD_MODE == "NOECC_12kx4" ? 16'b0000010010010010:
OPTION_STD_MODE == "NOECC_8kx6" ? 16'b0000111111111111:
OPTION_STD_MODE == "NOECC_6kx8" ? 16'b0000011011011011:
OPTION_STD_MODE == "NOECC_4kx12" ? 16'b0000100100100100:
OPTION_STD_MODE == "NOECC_2kx24" ? 16'b0000101101101101:
16'bx;
localparam A_REPEAT = 24 / PORT_A_WIDTH;
localparam B_REPEAT = 24 / PORT_B_WIDTH;
assign A_DATA = {A_REPEAT{PORT_A_WR_DATA[PORT_A_WIDTH-1:0]}};
assign B_DATA = {B_REPEAT{PORT_B_WR_DATA[PORT_B_WIDTH-1:0]}};
NX_RAM_WRAP #(
.std_mode(OPTION_STD_MODE),
.mcka_edge(PORT_A_CLK_POL == 1 ? 1'b0 : 1'b1),
.mckb_edge(PORT_B_CLK_POL == 1 ? 1'b0 : 1'b1),
.pcka_edge(PORT_A_CLK_POL == 1 ? 1'b0 : 1'b1),
.pckb_edge(PORT_B_CLK_POL == 1 ? 1'b0 : 1'b1),
.raw_config0(4'b0000),
.raw_config1(raw_config1_val[15:0]),
.mem_ctxt($sformatf("%s",bram_init_to_string(INIT,A_REPEAT,PORT_A_WIDTH))),
) _TECHMAP_REPLACE_ (
.ACK(PORT_A_CLK),
//.ACKS(PORT_A_CLK),
//.ACKD(), // Not used in Non-ECC modes
//.ACKR(),
//.AR(),
//.ACOR(),
//.AERR(),
.ACS(PORT_A_CLK_EN),
.AWE(PORT_A_WR_EN),
.AA(PORT_A_ADDR),
.AI(A_DATA),
.AO(PORT_A_RD_DATA),
.BCK(PORT_B_CLK),
//.BCKC(PORT_B_CLK),
//.BCKD(), // Not used in Non-ECC modes
//.BCKR()
//.BR(),
//.BCOR(),
//.BERR(),
.BCS(PORT_B_CLK_EN),
.BWE(PORT_B_WR_EN),
.BA(PORT_B_ADDR),
.BI(B_DATA),
.BO(PORT_B_RD_DATA)
);
endmodule

View file

@ -0,0 +1,127 @@
// NX_RAM related
(* blackbox *)
module NX_ECC(CKD, CHK, COR, ERR);
input CHK;
input CKD;
output COR;
output ERR;
endmodule
//TODO
(* blackbox *)
module NX_IOM_BIN2GRP(GS, DS, GVON, GVIN, GVDN, PA, LA);
input [1:0] DS;
input GS;
output [2:0] GVDN;
output [2:0] GVIN;
output [2:0] GVON;
input [5:0] LA;
output [3:0] PA;
endmodule
//TODO
(* blackbox *)
module NX_SER(FCK, SCK, R, IO, DCK, DRL, I, DS, DRA, DRI, DRO, DID);
input DCK;
output [5:0] DID;
input [5:0] DRA;
input [5:0] DRI;
input DRL;
output [5:0] DRO;
input [1:0] DS;
input FCK;
input [4:0] I;
output IO;
input R;
input SCK;
parameter data_size = 5;
parameter differential = "";
parameter drive = "";
parameter location = "";
parameter locked = 1'b0;
parameter outputCapacity = "";
parameter outputDelayLine = "";
parameter slewRate = "";
parameter spath_dynamic = 1'b0;
parameter standard = "";
endmodule
//TODO
(* blackbox *)
module NX_DES(FCK, SCK, R, IO, DCK, DRL, DIG, FZ, FLD, FLG, O, DS, DRA, DRI, DRO, DID);
input DCK;
output [5:0] DID;
input DIG;
input [5:0] DRA;
input [5:0] DRI;
input DRL;
output [5:0] DRO;
input [1:0] DS;
input FCK;
output FLD;
output FLG;
input FZ;
input IO;
output [4:0] O;
input R;
input SCK;
parameter data_size = 5;
parameter differential = "";
parameter dpath_dynamic = 1'b0;
parameter drive = "";
parameter inputDelayLine = "";
parameter inputSignalSlope = "";
parameter location = "";
parameter locked = 1'b0;
parameter standard = "";
parameter termination = "";
parameter terminationReference = "";
parameter turbo = "";
parameter weakTermination = "";
endmodule
//TODO
(* blackbox *)
module NX_SERDES(FCK, SCK, RTX, RRX, CI, CCK, CL, CR, IO, DCK, DRL, DIG, FZ, FLD, FLG, I, O, DS, DRA, DRI, DRO
, DID);
input CCK;
input CI;
input CL;
input CR;
input DCK;
output [5:0] DID;
input DIG;
input [5:0] DRA;
input [5:0] DRI;
input DRL;
output [5:0] DRO;
input [1:0] DS;
input FCK;
output FLD;
output FLG;
input FZ;
input [4:0] I;
inout IO;
output [4:0] O;
input RRX;
input RTX;
input SCK;
parameter cpath_registered = 1'b0;
parameter data_size = 5;
parameter differential = "";
parameter dpath_dynamic = 1'b0;
parameter drive = "";
parameter inputDelayLine = "";
parameter inputSignalSlope = "";
parameter location = "";
parameter locked = 1'b0;
parameter outputCapacity = "";
parameter outputDelayLine = "";
parameter slewRate = "";
parameter spath_dynamic = 1'b0;
parameter standard = "";
parameter termination = "";
parameter terminationReference = "";
parameter turbo = "";
parameter weakTermination = "";
endmodule

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,95 @@
`default_nettype none
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 = {{2{LUT[1:0]}}, {2{LUT[1:0]}}, {2{LUT[1:0]}}, {2{LUT[1:0]}},
{2{LUT[1:0]}}, {2{LUT[1:0]}}, {2{LUT[1:0]}}, {2{LUT[1:0]}}};
NX_LUT #(.lut_table(INIT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(A[0]), .I2(1'b0), .I3(1'b0), .I4(1'b0));
end else
if (WIDTH == 2) begin
localparam [15:0] INIT = {{4{LUT[3:0]}}, {4{LUT[3:0]}}, {4{LUT[3:0]}}, {4{LUT[3:0]}}};
NX_LUT #(.lut_table(INIT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(A[0]), .I2(A[1]), .I3(1'b0), .I4(1'b0), );
end else
if (WIDTH == 3) begin
localparam [15:0] INIT = {{8{LUT[7:0]}}, {8{LUT[7:0]}}};
NX_LUT #(.lut_table(INIT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(A[0]), .I2(A[1]), .I3(A[2]), .I4(1'b0));
end else
if (WIDTH == 4) begin
NX_LUT #(.lut_table(LUT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(A[0]), .I2(A[1]), .I3(A[2]), .I4(A[3]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
endgenerate
endmodule
(* techmap_celltype = "$_DFF_[NP]P[01]_" *)
module \$_DFF_xxxx_ (input D, C, R, output Q);
parameter _TECHMAP_CELLTYPE_ = "";
localparam dff_edge = _TECHMAP_CELLTYPE_[3*8 +: 8] == "N";
localparam dff_type = _TECHMAP_CELLTYPE_[1*8 +: 8] == "1";
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(dff_type), .dff_edge(dff_edge), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b0), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b1), .R(R), .O(Q));
endmodule
(* techmap_celltype = "$_SDFF_[NP]P[01]_" *)
module \$_SDFF_xxxx_ (input D, C, R, output Q);
parameter _TECHMAP_CELLTYPE_ = "";
localparam dff_edge = _TECHMAP_CELLTYPE_[3*8 +: 8] == "N";
localparam dff_type = _TECHMAP_CELLTYPE_[1*8 +: 8] == "1";
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(dff_type), .dff_edge(dff_edge), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b1), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b1), .R(R), .O(Q));
endmodule
(* techmap_celltype = "$_DFFE_[NP]P[01]P_" *)
module \$_DFFE_xxxx_ (input D, C, R, E, output Q);
parameter _TECHMAP_CELLTYPE_ = "";
localparam dff_edge = _TECHMAP_CELLTYPE_[4*8 +: 8] == "N";
localparam dff_type = _TECHMAP_CELLTYPE_[2*8 +: 8] == "1";
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(dff_type), .dff_edge(dff_edge), .dff_init(1'b1), .dff_load(1'b1), .dff_sync(1'b0), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(E), .R(R), .O(Q));
endmodule
(* techmap_celltype = "$_SDFFE_[NP]P[01]P_" *)
module \$_SDFFE_xxxx_ (input D, C, R, E, output Q);
parameter _TECHMAP_CELLTYPE_ = "";
localparam dff_edge = _TECHMAP_CELLTYPE_[4*8 +: 8] == "N";
localparam dff_type = _TECHMAP_CELLTYPE_[2*8 +: 8] == "1";
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(dff_type), .dff_edge(dff_edge), .dff_init(1'b1), .dff_load(1'b1), .dff_sync(1'b1), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(E), .R(R), .O(Q));
endmodule
module \$_DFF_P_ (input D, C, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(_TECHMAP_WIREINIT_Q_), .dff_edge(1'b0), .dff_init(1'b0), .dff_load(1'b0), .dff_sync(1'b0), .dff_type(1'b0)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b1), .R(1'b0), .O(Q));
endmodule
module \$_DFF_N_ (input D, C, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(_TECHMAP_WIREINIT_Q_), .dff_edge(1'b1), .dff_init(1'b0), .dff_load(1'b0), .dff_sync(1'b0), .dff_type(1'b0)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b1), .R(1'b0), .O(Q));
endmodule
module \$_DFFE_PP_ (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(_TECHMAP_WIREINIT_Q_), .dff_edge(1'b0), .dff_init(1'b0), .dff_load(1'b1), .dff_sync(1'b0), .dff_type(1'b0)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(E), .R(1'b0), .O(Q));
endmodule
module \$_DFFE_NP_ (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'b0;
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(_TECHMAP_WIREINIT_Q_), .dff_edge(1'b1), .dff_init(1'b0), .dff_load(1'b1), .dff_sync(1'b0), .dff_type(1'b0)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(E), .R(1'b0), .O(Q));
endmodule

View file

@ -0,0 +1,421 @@
(* abc9_lut=1 *)
module NX_LUT(input I1, I2, I3, I4, output O);
parameter lut_table = 16'h0000;
wire [7:0] s1 = I4 ? lut_table[15:8] : lut_table[7:0];
wire [3:0] s2 = I3 ? s1[7:4] : s1[3:0];
wire [1:0] s3 = I2 ? s2[3:2] : s2[1:0];
assign O = I1 ? s3[1] : s3[0];
endmodule
(* abc9_box, lib_whitebox *)
module NX_DFF(input I, CK, L, R, output reg O);
parameter dff_ctxt = 1'bx;
parameter dff_edge = 1'b0;
parameter dff_init = 1'b0;
parameter dff_load = 1'b0;
parameter dff_sync = 1'b0;
parameter dff_type = 1'b0;
initial begin
O = dff_ctxt;
end
wire clock = CK ^ dff_edge;
wire load = dff_load ? L : 1'b1;
wire async_reset = !dff_sync && dff_init && R;
wire sync_reset = dff_sync && dff_init && R;
always @(posedge clock, posedge async_reset)
if (async_reset) O <= dff_type;
else if (sync_reset) O <= dff_type;
else if (load) O <= I;
endmodule
(* abc9_box, lib_whitebox *)
module NX_DFR(input I, CK, L, R, output O);
parameter data_inv = 1'b0;
parameter dff_edge = 1'b0;
parameter dff_init = 1'b0;
parameter dff_load = 1'b0;
parameter dff_sync = 1'b0;
parameter dff_type = 1'b0;
parameter iobname = "";
parameter location = "";
parameter mode = 0;
parameter path = 0;
parameter ring = 0;
wire clock = CK ^ dff_edge;
wire load = dff_load ? L : 1'b1;
wire async_reset = !dff_sync && dff_init && R;
wire sync_reset = dff_sync && dff_init && R;
reg O_reg;
always @(posedge clock, posedge async_reset)
if (async_reset) O_reg <= dff_type;
else if (sync_reset) O_reg <= dff_type;
else if (load) O_reg <= I;
assign O = data_inv ? O_reg : ~O_reg;
endmodule
(* abc9_box, lib_whitebox *)
module NX_CY(input A1, A2, A3, A4, B1, B2, B3, B4, (* abc9_carry *) input CI, output S1, S2, S3, S4, (* abc9_carry *) output CO);
parameter add_carry = 0;
wire CI_1;
wire CO1, CO2, CO3;
assign CI_1 = (add_carry==2) ? CI : ((add_carry==1) ? 1'b1 : 1'b0);
assign { CO1, S1 } = A1 + B1 + CI_1;
assign { CO2, S2 } = A2 + B2 + CO1;
assign { CO3, S3 } = A3 + B3 + CO2;
assign { CO, S4 } = A4 + B4 + CO3;
endmodule
module NX_IOB(I, C, T, O, IO);
input C;
input I;
(* iopad_external_pin *)
inout IO;
output O;
input T;
parameter differential = "";
parameter drive = "";
parameter dynDrive = "";
parameter dynInput = "";
parameter dynTerm = "";
parameter extra = 3;
parameter inputDelayLine = "";
parameter inputDelayOn = "";
parameter inputSignalSlope = "";
parameter location = "";
parameter locked = 1'b0;
parameter outputCapacity = "";
parameter outputDelayLine = "";
parameter outputDelayOn = "";
parameter slewRate = "";
parameter standard = "";
parameter termination = "";
parameter terminationReference = "";
parameter turbo = "";
parameter weakTermination = "";
assign O = IO;
assign IO = C ? I : 1'bz;
endmodule
module NX_IOB_I(C, T, IO, O);
input C;
(* iopad_external_pin *)
input IO;
output O;
input T;
parameter differential = "";
parameter drive = "";
parameter dynDrive = "";
parameter dynInput = "";
parameter dynTerm = "";
parameter extra = 1;
parameter inputDelayLine = "";
parameter inputDelayOn = "";
parameter inputSignalSlope = "";
parameter location = "";
parameter locked = 1'b0;
parameter outputCapacity = "";
parameter outputDelayLine = "";
parameter outputDelayOn = "";
parameter slewRate = "";
parameter standard = "";
parameter termination = "";
parameter terminationReference = "";
parameter turbo = "";
parameter weakTermination = "";
assign O = IO;
endmodule
module NX_IOB_O(I, C, T, IO);
input C;
input I;
(* iopad_external_pin *)
output IO;
input T;
parameter differential = "";
parameter drive = "";
parameter dynDrive = "";
parameter dynInput = "";
parameter dynTerm = "";
parameter extra = 2;
parameter inputDelayLine = "";
parameter inputDelayOn = "";
parameter inputSignalSlope = "";
parameter location = "";
parameter locked = 1'b0;
parameter outputCapacity = "";
parameter outputDelayLine = "";
parameter outputDelayOn = "";
parameter slewRate = "";
parameter standard = "";
parameter termination = "";
parameter terminationReference = "";
parameter turbo = "";
parameter weakTermination = "";
assign IO = C ? I : 1'bz;
endmodule
(* abc9_box, lib_whitebox *)
module NX_CY_1BIT(CI, A, B, S, CO);
(* abc9_carry *)
input CI;
input A;
input B;
output S;
(* abc9_carry *)
output CO;
parameter first = 1'b0;
assign {CO, S} = A + B + CI;
endmodule
module NX_BD(I, O);
input I;
output O;
parameter mode = "global_lowskew";
assign O = I;
endmodule
module NX_BFF(I, O);
input I;
output O;
assign O = I;
endmodule
module NX_BFR(I, O);
input I;
output O;
parameter data_inv = 1'b0;
parameter iobname = "";
parameter location = "";
parameter mode = 0;
parameter path = 0;
parameter ring = 0;
assign O = data_inv ? ~I : I;
endmodule
(* abc9_box, lib_whitebox *)
module NX_RAM(ACK, ACKC, ACKD, ACKR, BCK, BCKC, BCKD, BCKR, AI1, AI2, AI3, AI4, AI5, AI6, AI7, AI8, AI9, AI10, AI11, AI12, AI13
, AI14, AI15, AI16, AI17, AI18, AI19, AI20, AI21, AI22, AI23, AI24, BI1, BI2, BI3, BI4, BI5, BI6, BI7, BI8, BI9, BI10
, BI11, BI12, BI13, BI14, BI15, BI16, BI17, BI18, BI19, BI20, BI21, BI22, BI23, BI24, ACOR, AERR, BCOR, BERR, AO1, AO2, AO3
, AO4, AO5, AO6, AO7, AO8, AO9, AO10, AO11, AO12, AO13, AO14, AO15, AO16, AO17, AO18, AO19, AO20, AO21, AO22, AO23, AO24
, BO1, BO2, BO3, BO4, BO5, BO6, BO7, BO8, BO9, BO10, BO11, BO12, BO13, BO14, BO15, BO16, BO17, BO18, BO19, BO20, BO21
, BO22, BO23, BO24, AA1, AA2, AA3, AA4, AA5, AA6, AA7, AA8, AA9, AA10, AA11, AA12, AA13, AA14, AA15, AA16, ACS, AWE
, AR, BA1, BA2, BA3, BA4, BA5, BA6, BA7, BA8, BA9, BA10, BA11, BA12, BA13, BA14, BA15, BA16, BCS, BWE, BR);
input AA1;
input AA10;
input AA11;
input AA12;
input AA13;
input AA14;
input AA15;
input AA16;
input AA2;
input AA3;
input AA4;
input AA5;
input AA6;
input AA7;
input AA8;
input AA9;
input ACK;
input ACKC;
input ACKD;
input ACKR;
output ACOR;
input ACS;
output AERR;
input AI1;
input AI10;
input AI11;
input AI12;
input AI13;
input AI14;
input AI15;
input AI16;
input AI17;
input AI18;
input AI19;
input AI2;
input AI20;
input AI21;
input AI22;
input AI23;
input AI24;
input AI3;
input AI4;
input AI5;
input AI6;
input AI7;
input AI8;
input AI9;
output reg AO1;
output reg AO10;
output reg AO11;
output reg AO12;
output reg AO13;
output reg AO14;
output reg AO15;
output reg AO16;
output reg AO17;
output reg AO18;
output reg AO19;
output reg AO2;
output reg AO20;
output reg AO21;
output reg AO22;
output reg AO23;
output reg AO24;
output reg AO3;
output reg AO4;
output reg AO5;
output reg AO6;
output reg AO7;
output reg AO8;
output reg AO9;
input AR;
input AWE;
input BA1;
input BA10;
input BA11;
input BA12;
input BA13;
input BA14;
input BA15;
input BA16;
input BA2;
input BA3;
input BA4;
input BA5;
input BA6;
input BA7;
input BA8;
input BA9;
input BCK;
input BCKC;
input BCKD;
input BCKR;
output BCOR;
input BCS;
output BERR;
input BI1;
input BI10;
input BI11;
input BI12;
input BI13;
input BI14;
input BI15;
input BI16;
input BI17;
input BI18;
input BI19;
input BI2;
input BI20;
input BI21;
input BI22;
input BI23;
input BI24;
input BI3;
input BI4;
input BI5;
input BI6;
input BI7;
input BI8;
input BI9;
output reg BO1;
output reg BO10;
output reg BO11;
output reg BO12;
output reg BO13;
output reg BO14;
output reg BO15;
output reg BO16;
output reg BO17;
output reg BO18;
output reg BO19;
output reg BO2;
output reg BO20;
output reg BO21;
output reg BO22;
output reg BO23;
output reg BO24;
output reg BO3;
output reg BO4;
output reg BO5;
output reg BO6;
output reg BO7;
output reg BO8;
output reg BO9;
input BR;
input BWE;
parameter mcka_edge = 1'b0;
parameter mckb_edge = 1'b0;
parameter mem_ctxt = "";
parameter pcka_edge = 1'b0;
parameter pckb_edge = 1'b0;
parameter pipe_ia = 1'b0;
parameter pipe_ib = 1'b0;
parameter pipe_oa = 1'b0;
parameter pipe_ob = 1'b0;
parameter raw_config0 = 4'b0000;
parameter raw_config1 = 16'b0000000000000000;
//parameter raw_l_enable = 1'b0;
//parameter raw_l_extend = 4'b0000;
//parameter raw_u_enable = 1'b0;
//parameter raw_u_extend = 8'b00000000;
parameter std_mode = "";
reg [24-1:0] mem [2048-1:0]; // 48 Kbit of memory
/*integer i;
initial begin
for (i = 0; i < 2048; i = i + 1)
mem[i] = 24'b0;
end*/
wire [15:0] AA = { AA16, AA15, AA14, AA13, AA12, AA11, AA10, AA9, AA8, AA7, AA6, AA5, AA4, AA3, AA2, AA1 };
wire [23:0] AI = { AI24, AI23, AI22, AI21, AI20, AI19, AI18, AI17, AI16, AI15, AI14, AI13, AI12, AI11, AI10, AI9, AI8, AI7, AI6, AI5, AI4, AI3, AI2, AI1 };
wire [23:0] AO = { AO24, AO23, AO22, AO21, AO20, AO19, AO18, AO17, AO16, AO15, AO14, AO13, AO12, AO11, AO10, AO9, AO8, AO7, AO6, AO5, AO4, AO3, AO2, AO1 };
wire [15:0] BA = { BA16, BA15, BA14, BA13, BA12, BA11, BA10, BA9, BA8, BA7, BA6, BA5, BA4, BA3, BA2, BA1 };
wire [23:0] BI = { BI24, BI23, BI22, BI21, BI20, BI19, BI18, BI17, BI16, BI15, BI14, BI13, BI12, BI11, BI10, BI9, BI8, BI7, BI6, BI5, BI4, BI3, BI2, BI1 };
wire [23:0] BO = { BO24, BO23, BO22, BO21, BO20, BO19, BO18, BO17, BO16, BO15, BO14, BO13, BO12, BO11, BO10, BO9, BO8, BO7, BO6, BO5, BO4, BO3, BO2, BO1 };
always @(posedge ACK)
if (AWE)
mem[AA[10:0]] <= AI;
else
{ AO24, AO23, AO22, AO21, AO20, AO19, AO18, AO17, AO16, AO15, AO14, AO13, AO12, AO11, AO10, AO9, AO8, AO7, AO6, AO5, AO4, AO3, AO2, AO1 } <= mem[AA[10:0]];
assign ACOR = 1'b0;
assign AERR = 1'b0;
always @(posedge BCK)
if (BWE)
mem[BA[10:0]] <= BI;
else
{ BO24, BO23, BO22, BO21, BO20, BO19, BO18, BO17, BO16, BO15, BO14, BO13, BO12, BO11, BO10, BO9, BO8, BO7, BO6, BO5, BO4, BO3, BO2, BO1 } <= mem[BA[10:0]];
assign BCOR = 1'b0;
assign BERR = 1'b0;
endmodule

View file

View file

View file

@ -0,0 +1,306 @@
(* abc9_box, lib_whitebox *)
module NX_GCK_U(SI1, SI2, CMD, SO);
input CMD;
input SI1;
input SI2;
output SO;
parameter inv_in = 1'b0;
parameter inv_out = 1'b0;
parameter std_mode = "BYPASS";
wire SI1_int = inv_in ? ~SI1 : SI1;
wire SI2_int = inv_in ? ~SI2 : SI2;
wire SO_int;
generate
if (std_mode == "BYPASS") begin
assign SO_int = SI1_int;
end
else if (std_mode == "MUX") begin
assign SO_int = CMD ? SI1_int : SI2_int;
end
else if (std_mode == "CKS") begin
assign SO_int = CMD ? SI1_int : 1'b0;
end
else if (std_mode == "CSC") begin
assign SO_int = CMD;
end
else
$error("Unrecognised std_mode");
endgenerate
assign SO = inv_out ? ~SO_int : SO_int;
endmodule
(* abc9_box, lib_whitebox *)
module NX_RFB_U(WCK, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15, I16, I17, I18, I19, I20
, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31, I32, I33, I34, I35, I36, O1, O2, O3, O4, O5
, O6, O7, O8, O9, O10, O11, O12, O13, O14, O15, O16, O17, O18, O19, O20, O21, O22, O23, O24, O25, O26
, O27, O28, O29, O30, O31, O32, O33, O34, O35, O36, RA1, RA2, RA3, RA4, RA5, RA6, RA7, RA8, RA9, RA10, WA1
, WA2, WA3, WA4, WA5, WA6, WE, WEA);
input I1;
input I10;
input I11;
input I12;
input I13;
input I14;
input I15;
input I16;
input I17;
input I18;
input I19;
input I2;
input I20;
input I21;
input I22;
input I23;
input I24;
input I25;
input I26;
input I27;
input I28;
input I29;
input I3;
input I30;
input I31;
input I32;
input I33;
input I34;
input I35;
input I36;
input I4;
input I5;
input I6;
input I7;
input I8;
input I9;
output O1;
output O10;
output O11;
output O12;
output O13;
output O14;
output O15;
output O16;
output O17;
output O18;
output O19;
output O2;
output O20;
output O21;
output O22;
output O23;
output O24;
output O25;
output O26;
output O27;
output O28;
output O29;
output O3;
output O30;
output O31;
output O32;
output O33;
output O34;
output O35;
output O36;
output O4;
output O5;
output O6;
output O7;
output O8;
output O9;
input RA1;
input RA10;
input RA2;
input RA3;
input RA4;
input RA5;
input RA6;
input RA7;
input RA8;
input RA9;
input WA1;
input WA2;
input WA3;
input WA4;
input WA5;
input WA6;
input WCK;
input WE;
input WEA;
parameter mem_ctxt = "";
parameter mode = 0;
parameter wck_edge = 1'b0;
wire clock = WCK ^ wck_edge;
localparam MEM_SIZE = mode == 2 ? 64 : 32;
localparam MEM_WIDTH = mode == 3 ? 36 : 18;
localparam ADDR_WIDTH = mode == 2 ? 6 : 5;
localparam DATA_SIZE = MEM_SIZE * MEM_WIDTH;
localparam MAX_SIZE = DATA_SIZE + MEM_SIZE + 1;
reg [MEM_WIDTH-1:0] mem [MEM_SIZE-1:0];
function [DATA_SIZE-1:0] convert_initval;
input [8*MAX_SIZE-1:0] hex_initval;
reg done;
reg [DATA_SIZE-1:0] temp;
reg [7:0] char;
integer i,j;
begin
done = 1'b0;
temp = 0;
j = 0;
for (i = 0; i < MAX_SIZE; i = i + 1) begin
char = hex_initval[8*i +: 8];
if (char >= "0" && char <= "1") begin
temp[j] = char - "0";
j = j + 1;
end
end
convert_initval = temp;
end
endfunction
integer i;
reg [DATA_SIZE-1:0] mem_data;
initial begin
mem_data = convert_initval(mem_ctxt);
for (i = 0; i < MEM_SIZE; i = i + 1)
mem[i] = mem_data[MEM_WIDTH*(MEM_SIZE-i-1) +: MEM_WIDTH];
end
wire [ADDR_WIDTH-1:0] WA = (mode==2) ? { WA6, WA5, WA4, WA3, WA2, WA1 } : { WA5, WA4, WA3, WA2, WA1 };
wire [36-1:0] O = { O36, O35, O34, O33, O32, O31, O30, O29, O28,
O27, O26, O25, O24, O23, O22, O21, O20, O19,
O18, O17, O16, O15, O14, O13, O12, O11, O10,
O9, O8, O7, O6, O5, O4, O3, O2, O1 };
wire [36-1:0] I = { I36, I35, I34, I33, I32, I31, I30, I29, I28,
I27, I26, I25, I24, I23, I22, I21, I20, I19,
I18, I17, I16, I15, I14, I13, I12, I11, I10,
I9, I8, I7, I6, I5, I4, I3, I2, I1 };
generate
if (mode==0) begin
assign O = mem[{ RA5, RA4, RA3, RA2, RA1 }];
end
else if (mode==1) begin
assign O = mem[{ WA5, WA4, WA3, WA2, WA1 }];
end
else if (mode==2) begin
assign O = mem[{ RA6, RA5, RA4, RA3, RA2, RA1 }];
end
else if (mode==3) begin
assign O = mem[{ RA5, RA4, RA3, RA2, RA1 }];
end
else if (mode==4) begin
assign O = { mem[{ RA10, RA9, RA8, RA7, RA6 }], mem[{ RA5, RA4, RA3, RA2, RA1 }] };
end
else
$error("Unknown NX_RFB_U mode");
endgenerate
always @(posedge clock)
if (WE)
mem[WA] <= I[MEM_WIDTH-1:0];
endmodule
(* abc9_box, lib_whitebox *)
module NX_WFG_U(R, SI, ZI, SO, ZO);
input R;
input SI;
output SO;
input ZI;
output ZO;
parameter delay = 0;
parameter delay_on = 1'b0;
parameter div_phase = 1'b0;
parameter div_ratio = 0;
parameter location = "";
parameter mode = 0;
parameter pattern = 16'b0000000000000000;
parameter pattern_end = 0;
parameter reset_on_cal_lock_n = 1'b0;
parameter reset_on_pll_lock_n = 1'b0;
parameter reset_on_pll_locka_n = 1'b0;
parameter wfg_edge = 1'b0;
generate
if (mode==0) begin
assign SO = SI;
end
else if (mode==1) begin
wire clock = ZI ^ wfg_edge;
wire reset = R || SI;
reg [3:0] counter = 0;
reg [15:0] rom = pattern;
always @(posedge clock)
begin
if (reset)
counter <= 4'b0;
else
counter <= counter + 1;
end
assign SO = counter == pattern_end;
assign ZO = rom[counter];
end
else if (mode==2) begin
end
else
$error("Unknown NX_WFG_U mode");
endgenerate
endmodule
module NX_DDFR_U(CK,CKF,R,I,I2,L,O,O2);
input CK;
input CKF;
input R;
input I;
input I2;
input L;
output O;
output O2;
parameter location = "";
parameter path = 0;
parameter dff_type = 1'b0;
parameter dff_sync = 1'b0;
parameter dff_load = 1'b0;
wire load = dff_load ? 1'b1 : L; // reversed when compared to DFF
wire async_reset = !dff_sync && R;
wire sync_reset = dff_sync && R;
generate
if (path==1) begin
// IDDFR
always @(posedge CK, posedge async_reset)
if (async_reset) O <= dff_type;
else if (sync_reset) O <= dff_type;
else if (load) O <= I;
always @(posedge CKF, posedge async_reset)
if (async_reset) O2 <= dff_type;
else if (sync_reset) O2 <= dff_type;
else if (load) O2 <= I;
end
else if (path==0 || path==2) begin
reg q1, q2;
// ODDFR
always @(posedge CK, posedge async_reset)
if (async_reset) q1 <= dff_type;
else if (sync_reset) q1 <= dff_type;
else if (load) q1 <= I;
always @(posedge CKF, posedge async_reset)
if (async_reset) q2 <= dff_type;
else if (sync_reset) q2 <= dff_type;
else if (load) q2 <= I2;
assign O = CK ? q1 : q2;
end
else
$error("Unknown NX_DDFR_U path");
endgenerate
endmodule

View file

@ -0,0 +1,201 @@
module NX_RAM_WRAP(ACK, ACKD, ACKR, BCK, BCKD, BCKR, ACOR, AERR, BCOR, BERR, ACS, AWE, AR, BCS, BWE, BR, BI, AO, BO, AI, AA
, BA);
input [15:0] AA;
input ACK;
input ACKD;
input ACKR;
output ACOR;
input ACS;
output AERR;
input [23:0] AI;
output [23:0] AO;
input AR;
input AWE;
input [15:0] BA;
input BCK;
input BCKD;
input BCKR;
output BCOR;
input BCS;
output BERR;
input [23:0] BI;
output [23:0] BO;
input BR;
input BWE;
parameter mcka_edge = 1'b0;
parameter mckb_edge = 1'b0;
parameter mem_ctxt = "";
parameter pcka_edge = 1'b0;
parameter pckb_edge = 1'b0;
parameter pipe_ia = 1'b0;
parameter pipe_ib = 1'b0;
parameter pipe_oa = 1'b0;
parameter pipe_ob = 1'b0;
parameter raw_config0 = 4'b0000;
parameter raw_config1 = 16'b0000000000000000;
parameter std_mode = "";
NX_RAM #(
.mcka_edge(mcka_edge),
.mckb_edge(mckb_edge),
.mem_ctxt(mem_ctxt),
.pcka_edge(pcka_edge),
.pckb_edge(pckb_edge),
.pipe_ia(pipe_ia),
.pipe_ib(pipe_ib),
.pipe_oa(pipe_oa),
.pipe_ob(pipe_ob),
.raw_config0(raw_config0),
.raw_config1(raw_config1),
.std_mode(std_mode)
) ram (
.AA1(AA[0]),
.AA10(AA[9]),
.AA11(AA[10]),
.AA12(AA[11]),
.AA13(AA[12]),
.AA14(AA[13]),
.AA15(AA[14]),
.AA16(AA[15]),
.AA2(AA[1]),
.AA3(AA[2]),
.AA4(AA[3]),
.AA5(AA[4]),
.AA6(AA[5]),
.AA7(AA[6]),
.AA8(AA[7]),
.AA9(AA[8]),
.ACK(ACK),
.ACKC(ACK),
.ACKD(ACKD),
.ACKR(ACKR),
.ACOR(ACOR),
.ACS(ACS),
.AERR(AERR),
.AI1(AI[0]),
.AI10(AI[9]),
.AI11(AI[10]),
.AI12(AI[11]),
.AI13(AI[12]),
.AI14(AI[13]),
.AI15(AI[14]),
.AI16(AI[15]),
.AI17(AI[16]),
.AI18(AI[17]),
.AI19(AI[18]),
.AI2(AI[1]),
.AI20(AI[19]),
.AI21(AI[20]),
.AI22(AI[21]),
.AI23(AI[22]),
.AI24(AI[23]),
.AI3(AI[2]),
.AI4(AI[3]),
.AI5(AI[4]),
.AI6(AI[5]),
.AI7(AI[6]),
.AI8(AI[7]),
.AI9(AI[8]),
.AO1(AO[0]),
.AO10(AO[9]),
.AO11(AO[10]),
.AO12(AO[11]),
.AO13(AO[12]),
.AO14(AO[13]),
.AO15(AO[14]),
.AO16(AO[15]),
.AO17(AO[16]),
.AO18(AO[17]),
.AO19(AO[18]),
.AO2(AO[1]),
.AO20(AO[19]),
.AO21(AO[20]),
.AO22(AO[21]),
.AO23(AO[22]),
.AO24(AO[23]),
.AO3(AO[2]),
.AO4(AO[3]),
.AO5(AO[4]),
.AO6(AO[5]),
.AO7(AO[6]),
.AO8(AO[7]),
.AO9(AO[8]),
.AR(AR),
.AWE(AWE),
.BA1(BA[0]),
.BA10(BA[9]),
.BA11(BA[10]),
.BA12(BA[11]),
.BA13(BA[12]),
.BA14(BA[13]),
.BA15(BA[14]),
.BA16(BA[15]),
.BA2(BA[1]),
.BA3(BA[2]),
.BA4(BA[3]),
.BA5(BA[4]),
.BA6(BA[5]),
.BA7(BA[6]),
.BA8(BA[7]),
.BA9(BA[8]),
.BCK(BCK),
.BCKC(BCK),
.BCKD(BCKD),
.BCKR(BCKR),
.BCOR(BCOR),
.BCS(BCS),
.BERR(BERR),
.BI1(BI[0]),
.BI10(BI[9]),
.BI11(BI[10]),
.BI12(BI[11]),
.BI13(BI[12]),
.BI14(BI[13]),
.BI15(BI[14]),
.BI16(BI[15]),
.BI17(BI[16]),
.BI18(BI[17]),
.BI19(BI[18]),
.BI2(BI[1]),
.BI20(BI[19]),
.BI21(BI[20]),
.BI22(BI[21]),
.BI23(BI[22]),
.BI24(BI[23]),
.BI3(BI[2]),
.BI4(BI[3]),
.BI5(BI[4]),
.BI6(BI[5]),
.BI7(BI[6]),
.BI8(BI[7]),
.BI9(BI[8]),
.BO1(BO[0]),
.BO10(BO[9]),
.BO11(BO[10]),
.BO12(BO[11]),
.BO13(BO[12]),
.BO14(BO[13]),
.BO15(BO[14]),
.BO16(BO[15]),
.BO17(BO[16]),
.BO18(BO[17]),
.BO19(BO[18]),
.BO2(BO[1]),
.BO20(BO[19]),
.BO21(BO[20]),
.BO22(BO[21]),
.BO23(BO[22]),
.BO24(BO[23]),
.BO3(BO[2]),
.BO4(BO[3]),
.BO5(BO[4]),
.BO6(BO[5]),
.BO7(BO[6]),
.BO8(BO[7]),
.BO9(BO[8]),
.BR(BR),
.BWE(BWE)
);
endmodule

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,15 @@
module \$__BEYOND_IBUF (input PAD, output O);
NX_IOB_I _TECHMAP_REPLACE_ (.IO(PAD), .O(O), .C(1'b0));
endmodule
module \$__BEYOND_OBUF (output PAD, input I);
NX_IOB_O _TECHMAP_REPLACE_ (.IO(PAD), .I(I), .C(1'b1));
endmodule
module \$__BEYOND_TOBUF (output PAD, input I, input C);
NX_IOB _TECHMAP_REPLACE_ (.IO(PAD), .I(I), .C(C));
endmodule
module \$__BEYOND_IOBUF (output PAD, input I, output O, output C);
NX_IOB _TECHMAP_REPLACE_ (.IO(PAD), .I(I), .O(O), .C(C));
endmodule

View file

@ -0,0 +1,11 @@
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

@ -0,0 +1,164 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2024 Miodrag Milanovic <micko@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static SigBit get_bit_or_zero(const SigSpec &sig)
{
if (GetSize(sig) == 0)
return State::S0;
return sig[0];
}
static void nx_carry_chain(Module *module)
{
SigMap sigmap(module);
dict<SigBit,Cell*> carry;
for (auto cell : module->cells())
{
if (cell->type == ID(NX_CY_1BIT)) {
if (cell->getParam(ID(first)).as_int() == 1) continue;
if (!cell->hasPort(ID(CI)))
log_error("Not able to find connected carry.\n");
SigBit ci = sigmap(cell->getPort(ID(CI)).as_bit());
carry[ci] = cell;
}
}
dict<Cell*,vector<Cell*>> carry_chains;
log("Detecting carry chains\n");
for (auto cell : module->cells())
{
if (cell->type == ID(NX_CY_1BIT)) {
if (cell->getParam(ID(first)).as_int() == 0) continue;
vector<Cell*> chain;
Cell *current = cell;
chain.push_back(current);
SigBit co = sigmap(cell->getPort(ID(CO)).as_bit());
while (co.is_wire())
{
if (carry.count(co)==0)
break;
//log_error("Not able to find connected carry.\n");
current = carry[co];
chain.push_back(current);
if (!current->hasPort(ID(CO))) break;
co = sigmap(current->getPort(ID(CO)).as_bit());
}
carry_chains[cell] = chain;
}
}
log("Creating NX_CY cells.\n");
for(auto& c : carry_chains) {
Cell *cell = nullptr;
int j = 0;
int cnt = 0;
IdString names_A[] = { ID(A1), ID(A2), ID(A3), ID(A4) };
IdString names_B[] = { ID(B1), ID(B2), ID(B3), ID(B4) };
IdString names_S[] = { ID(S1), ID(S2), ID(S3), ID(S4) };
if (!c.second.at(0)->getPort(ID(CI)).is_fully_const()) {
cell = module->addCell(NEW_ID, ID(NX_CY));
cell->setParam(ID(add_carry), Const(1,2));
cell->setPort(ID(CI), State::S1);
cell->setPort(names_A[0], c.second.at(0)->getPort(ID(CI)).as_bit());
cell->setPort(names_B[0], State::S0);
j++;
}
for (size_t i=0 ; i<c.second.size(); i++) {
if (j==0) {
cell = module->addCell(NEW_ID, ID(NX_CY));
SigBit ci = c.second.at(i)->getPort(ID(CI)).as_bit();
cell->setPort(ID(CI), ci);
if (ci.is_wire()) {
cell->setParam(ID(add_carry), Const(2,2));
} else {
if (ci == State::S0)
cell->setParam(ID(add_carry), Const(0,2));
else
cell->setParam(ID(add_carry), Const(1,2));
}
}
if (j==3) {
if (cnt !=0 && (cnt % 24 == 0)) {
SigBit new_co = module->addWire(NEW_ID);
cell->setPort(ID(A4), State::S0);
cell->setPort(ID(B4), State::S0);
cell->setPort(ID(S4), new_co);
cell = module->addCell(NEW_ID, ID(NX_CY));
cell->setParam(ID(add_carry), Const(1,2));
cell->setPort(ID(CI), State::S1);
cell->setPort(ID(A1), new_co);
cell->setPort(ID(B1), State::S0);
j = 1;
} else {
if (c.second.at(i)->hasPort(ID(CO)))
cell->setPort(ID(CO), c.second.at(i)->getPort(ID(CO)));
}
cnt++;
}
cell->setPort(names_A[j], get_bit_or_zero(c.second.at(i)->getPort(ID(A))));
cell->setPort(names_B[j], get_bit_or_zero(c.second.at(i)->getPort(ID(B))));
if (c.second.at(i)->hasPort(ID(S)))
cell->setPort(names_S[j], c.second.at(i)->getPort(ID(S)));
j = (j + 1) % 4;
module->remove(c.second.at(i));
}
}
}
struct NXCarryPass : public Pass {
NXCarryPass() : Pass("nx_carry", "NanoXplore: create carry cells") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" nx_carry [options] [selection]\n");
log("\n");
log("Fixes carry chain if needed, break it on 24 elements and group by 4 into NX_CY.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing NX_CARRY pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
break;
}
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
nx_carry_chain(module);
}
} NXCarryPass;
PRIVATE_NAMESPACE_END

View file

@ -0,0 +1,17 @@
function [9728-1:0] rf_init_to_string;
input [1152-1:0] array;
input integer blocks;
input integer width;
reg [9728-1:0] temp; // (1152+1152/18)*8
integer i;
begin
temp = "";
for (i = 0; i < blocks; i = i + 1) begin
if (i != 0) begin
temp = {temp, ","};
end
temp = {temp, $sformatf("%b",array[(i+1)*width-1: i*width])};
end
rf_init_to_string = temp;
end
endfunction

View file

@ -0,0 +1,15 @@
ram distributed $__NX_RFB_L_ {
abits 6;
width 16;
cost 10;
init no_undef;
prune_rom;
port sw "W" {
clock anyedge;
}
port sr "R" {
clock anyedge;
rden;
}
}

View file

@ -0,0 +1,15 @@
ram distributed $__NX_RFB_M_ {
abits 6;
width 16;
cost 10;
init no_undef;
prune_rom;
port sw "W" {
clock anyedge;
}
port sr "R" {
clock anyedge;
rden;
}
}

View file

@ -0,0 +1,30 @@
module $__NX_RFB_L_ (
input PORT_W_CLK,
input PORT_W_WR_EN,
input [5:0] PORT_W_ADDR,
input [15:0] PORT_W_WR_DATA,
input PORT_R_CLK,
input PORT_R_RD_EN,
input [5:0] PORT_R_ADDR,
output [15:0] PORT_R_RD_DATA,
);
parameter INIT = 1152'bx;
parameter PORT_W_CLK_POL = 1'b1;
parameter PORT_R_CLK_POL = 1'b1;
NX_RFB_L_WRAP #(
.mode(0),
.mem_ctxt(INIT),
.rck_edge(~PORT_R_CLK_POL),
.wck_edge(~PORT_W_CLK_POL)
) _TECHMAP_REPLACE_ (
.RCK(PORT_R_CLK),
.WCK(PORT_W_CLK),
.I(PORT_W_WR_DATA),
.RA(PORT_R_ADDR),
.WA(PORT_W_ADDR),
.RE(PORT_R_RD_EN),
.WE(PORT_W_WR_EN),
.O(PORT_R_RD_DATA)
);
endmodule

View file

@ -0,0 +1,30 @@
module $__NX_RFB_M_ (
input PORT_W_CLK,
input PORT_W_WR_EN,
input [5:0] PORT_W_ADDR,
input [15:0] PORT_W_WR_DATA,
input PORT_R_CLK,
input PORT_R_RD_EN,
input [5:0] PORT_R_ADDR,
output [15:0] PORT_R_RD_DATA,
);
parameter INIT = 1152'bx;
parameter PORT_W_CLK_POL = 1'b1;
parameter PORT_R_CLK_POL = 1'b1;
NX_RFB_M_WRAP #(
.mode(0),
.mem_ctxt(INIT),
.rck_edge(~PORT_R_CLK_POL),
.wck_edge(~PORT_W_CLK_POL)
) _TECHMAP_REPLACE_ (
.RCK(PORT_R_CLK),
.WCK(PORT_W_CLK),
.I(PORT_W_WR_DATA),
.RA(PORT_R_ADDR),
.WA(PORT_W_ADDR),
.RE(PORT_R_RD_EN),
.WE(PORT_W_WR_EN),
.O(PORT_R_RD_DATA)
);
endmodule

View file

@ -0,0 +1,345 @@
module $__NX_RFB_U_DPREG_ (
input PORT_W_CLK,
input [6-1:0] PORT_W_ADDR,
input [6-1:0] PORT_R_ADDR,
input [36-1:0] PORT_W_WR_DATA,
input PORT_W_WR_EN,
output [36-1:0] PORT_R_RD_DATA
);
parameter INIT = 1152'bx;
parameter PORT_W_CLK_POL = 1'b1;
parameter OPTION_MODE = 0;
parameter WIDTH = 18;
parameter BITS_USED = 0;
localparam BLOCK_NUM = OPTION_MODE == 2 ? 64 : 32;
localparam BLOCK_SIZE = OPTION_MODE == 3 ? 36 : 18;
`include "rf_init.vh"
// mode 0 - DPREG
// mode 2 - NX_XRFB_64x18
// mode 3 - NX_XRFB_32x36
NX_RFB_U #(
.mode(OPTION_MODE),
.mem_ctxt($sformatf("%s",rf_init_to_string(INIT, BLOCK_NUM, BLOCK_SIZE))),
.wck_edge(PORT_W_CLK_POL == 1 ? 1'b0 : 1'b1)
) _TECHMAP_REPLACE_ (
.WCK(PORT_W_CLK),
.I1(PORT_W_WR_DATA[0]),
.I2(PORT_W_WR_DATA[1]),
.I3(PORT_W_WR_DATA[2]),
.I4(PORT_W_WR_DATA[3]),
.I5(PORT_W_WR_DATA[4]),
.I6(PORT_W_WR_DATA[5]),
.I7(PORT_W_WR_DATA[6]),
.I8(PORT_W_WR_DATA[7]),
.I9(PORT_W_WR_DATA[8]),
.I10(PORT_W_WR_DATA[9]),
.I11(PORT_W_WR_DATA[10]),
.I12(PORT_W_WR_DATA[11]),
.I13(PORT_W_WR_DATA[12]),
.I14(PORT_W_WR_DATA[13]),
.I15(PORT_W_WR_DATA[14]),
.I16(PORT_W_WR_DATA[15]),
.I17(PORT_W_WR_DATA[16]),
.I18(PORT_W_WR_DATA[17]),
.I19(PORT_W_WR_DATA[18]),
.I20(PORT_W_WR_DATA[19]),
.I21(PORT_W_WR_DATA[20]),
.I22(PORT_W_WR_DATA[21]),
.I23(PORT_W_WR_DATA[22]),
.I24(PORT_W_WR_DATA[23]),
.I25(PORT_W_WR_DATA[24]),
.I26(PORT_W_WR_DATA[25]),
.I27(PORT_W_WR_DATA[26]),
.I28(PORT_W_WR_DATA[27]),
.I29(PORT_W_WR_DATA[28]),
.I30(PORT_W_WR_DATA[29]),
.I31(PORT_W_WR_DATA[30]),
.I32(PORT_W_WR_DATA[31]),
.I33(PORT_W_WR_DATA[32]),
.I34(PORT_W_WR_DATA[33]),
.I35(PORT_W_WR_DATA[34]),
.I36(PORT_W_WR_DATA[35]),
.O1(PORT_R_RD_DATA[0]),
.O2(PORT_R_RD_DATA[1]),
.O3(PORT_R_RD_DATA[2]),
.O4(PORT_R_RD_DATA[3]),
.O5(PORT_R_RD_DATA[4]),
.O6(PORT_R_RD_DATA[5]),
.O7(PORT_R_RD_DATA[6]),
.O8(PORT_R_RD_DATA[7]),
.O9(PORT_R_RD_DATA[8]),
.O10(PORT_R_RD_DATA[9]),
.O11(PORT_R_RD_DATA[10]),
.O12(PORT_R_RD_DATA[11]),
.O13(PORT_R_RD_DATA[12]),
.O14(PORT_R_RD_DATA[13]),
.O15(PORT_R_RD_DATA[14]),
.O16(PORT_R_RD_DATA[15]),
.O17(PORT_R_RD_DATA[16]),
.O18(PORT_R_RD_DATA[17]),
.O19(PORT_R_RD_DATA[18]),
.O20(PORT_R_RD_DATA[19]),
.O21(PORT_R_RD_DATA[20]),
.O22(PORT_R_RD_DATA[21]),
.O23(PORT_R_RD_DATA[22]),
.O24(PORT_R_RD_DATA[23]),
.O25(PORT_R_RD_DATA[24]),
.O26(PORT_R_RD_DATA[25]),
.O27(PORT_R_RD_DATA[26]),
.O28(PORT_R_RD_DATA[27]),
.O29(PORT_R_RD_DATA[28]),
.O30(PORT_R_RD_DATA[29]),
.O31(PORT_R_RD_DATA[30]),
.O32(PORT_R_RD_DATA[31]),
.O33(PORT_R_RD_DATA[32]),
.O34(PORT_R_RD_DATA[33]),
.O35(PORT_R_RD_DATA[34]),
.O36(PORT_R_RD_DATA[35]),
.RA1(PORT_R_ADDR[0]),
.RA2(PORT_R_ADDR[1]),
.RA3(PORT_R_ADDR[2]),
.RA4(PORT_R_ADDR[3]),
.RA5(PORT_R_ADDR[4]),
.RA6(PORT_R_ADDR[5]),
.RA7(),
.RA8(),
.RA9(),
.RA10(),
.WA1(PORT_W_ADDR[0]),
.WA2(PORT_W_ADDR[1]),
.WA3(PORT_W_ADDR[2]),
.WA4(PORT_W_ADDR[3]),
.WA5(PORT_W_ADDR[4]),
.WA6(PORT_W_ADDR[5]),
.WE(PORT_W_WR_EN),
.WEA(1'b0)
);
endmodule
module $__NX_RFB_U_SPREG_ (
input PORT_RW_CLK,
input [4:0] PORT_RW_ADDR,
input [17:0] PORT_RW_WR_DATA,
input PORT_RW_WR_EN,
output [17:0] PORT_RW_RD_DATA
);
parameter INIT = 576'bx;
parameter PORT_RW_CLK_POL = 1'b1;
parameter BITS_USED = 0;
`include "rf_init.vh"
NX_RFB_U #(
.mode(1),
.mem_ctxt($sformatf("%s",rf_init_to_string(INIT, 32, 18))),
.wck_edge(PORT_RW_CLK_POL == 1 ? 1'b0 : 1'b1)
) _TECHMAP_REPLACE_ (
.WCK(PORT_RW_CLK),
.I1(PORT_RW_WR_DATA[0]),
.I2(PORT_RW_WR_DATA[1]),
.I3(PORT_RW_WR_DATA[2]),
.I4(PORT_RW_WR_DATA[3]),
.I5(PORT_RW_WR_DATA[4]),
.I6(PORT_RW_WR_DATA[5]),
.I7(PORT_RW_WR_DATA[6]),
.I8(PORT_RW_WR_DATA[7]),
.I9(PORT_RW_WR_DATA[8]),
.I10(PORT_RW_WR_DATA[9]),
.I11(PORT_RW_WR_DATA[10]),
.I12(PORT_RW_WR_DATA[11]),
.I13(PORT_RW_WR_DATA[12]),
.I14(PORT_RW_WR_DATA[13]),
.I15(PORT_RW_WR_DATA[14]),
.I16(PORT_RW_WR_DATA[15]),
.I17(PORT_RW_WR_DATA[16]),
.I18(PORT_RW_WR_DATA[17]),
.I19(),
.I20(),
.I21(),
.I22(),
.I23(),
.I24(),
.I25(),
.I26(),
.I27(),
.I28(),
.I29(),
.I30(),
.I31(),
.I32(),
.I33(),
.I34(),
.I35(),
.I36(),
.O1(PORT_RW_RD_DATA[0]),
.O2(PORT_RW_RD_DATA[1]),
.O3(PORT_RW_RD_DATA[2]),
.O4(PORT_RW_RD_DATA[3]),
.O5(PORT_RW_RD_DATA[4]),
.O6(PORT_RW_RD_DATA[5]),
.O7(PORT_RW_RD_DATA[6]),
.O8(PORT_RW_RD_DATA[7]),
.O9(PORT_RW_RD_DATA[8]),
.O10(PORT_RW_RD_DATA[9]),
.O11(PORT_RW_RD_DATA[10]),
.O12(PORT_RW_RD_DATA[11]),
.O13(PORT_RW_RD_DATA[12]),
.O14(PORT_RW_RD_DATA[13]),
.O15(PORT_RW_RD_DATA[14]),
.O16(PORT_RW_RD_DATA[15]),
.O17(PORT_RW_RD_DATA[16]),
.O18(PORT_RW_RD_DATA[17]),
.O19(),
.O20(),
.O21(),
.O22(),
.O23(),
.O24(),
.O25(),
.O26(),
.O27(),
.O28(),
.O29(),
.O30(),
.O31(),
.O32(),
.O33(),
.O34(),
.O35(),
.O36(),
.RA1(),
.RA2(),
.RA3(),
.RA4(),
.RA5(),
.RA6(),
.RA7(),
.RA8(),
.RA9(),
.RA10(),
.WA1(PORT_RW_ADDR[0]),
.WA2(PORT_RW_ADDR[1]),
.WA3(PORT_RW_ADDR[2]),
.WA4(PORT_RW_ADDR[3]),
.WA5(PORT_RW_ADDR[4]),
.WA6(),
.WE(PORT_RW_WR_EN),
.WEA(1'b0)
);
endmodule
module $__NX_XRFB_2R_1W_ (
input PORT_W_CLK,
input [4:0] PORT_W_ADDR,
input [4:0] PORT_A_ADDR,
input [4:0] PORT_B_ADDR,
input [17:0] PORT_W_WR_DATA,
input PORT_W_WR_EN,
output [17:0] PORT_A_RD_DATA,
output [17:0] PORT_B_RD_DATA
);
parameter INIT = 576'bx;
parameter PORT_W_CLK_POL = 1'b1;
parameter BITS_USED = 0;
`include "rf_init.vh"
NX_RFB_U #(
.mode(4),
.mem_ctxt($sformatf("%s",rf_init_to_string(INIT, 32, 18))),
.wck_edge(PORT_W_CLK_POL == 1 ? 1'b0 : 1'b1)
) _TECHMAP_REPLACE_ (
.WCK(PORT_W_CLK),
.I1(PORT_W_WR_DATA[0]),
.I2(PORT_W_WR_DATA[1]),
.I3(PORT_W_WR_DATA[2]),
.I4(PORT_W_WR_DATA[3]),
.I5(PORT_W_WR_DATA[4]),
.I6(PORT_W_WR_DATA[5]),
.I7(PORT_W_WR_DATA[6]),
.I8(PORT_W_WR_DATA[7]),
.I9(PORT_W_WR_DATA[8]),
.I10(PORT_W_WR_DATA[9]),
.I11(PORT_W_WR_DATA[10]),
.I12(PORT_W_WR_DATA[11]),
.I13(PORT_W_WR_DATA[12]),
.I14(PORT_W_WR_DATA[13]),
.I15(PORT_W_WR_DATA[14]),
.I16(PORT_W_WR_DATA[15]),
.I17(PORT_W_WR_DATA[16]),
.I18(PORT_W_WR_DATA[17]),
.I19(),
.I20(),
.I21(),
.I22(),
.I23(),
.I24(),
.I25(),
.I26(),
.I27(),
.I28(),
.I29(),
.I30(),
.I31(),
.I32(),
.I33(),
.I34(),
.I35(),
.I36(),
.O1(PORT_A_RD_DATA[0]),
.O2(PORT_A_RD_DATA[1]),
.O3(PORT_A_RD_DATA[2]),
.O4(PORT_A_RD_DATA[3]),
.O5(PORT_A_RD_DATA[4]),
.O6(PORT_A_RD_DATA[5]),
.O7(PORT_A_RD_DATA[6]),
.O8(PORT_A_RD_DATA[7]),
.O9(PORT_A_RD_DATA[8]),
.O10(PORT_A_RD_DATA[9]),
.O11(PORT_A_RD_DATA[10]),
.O12(PORT_A_RD_DATA[11]),
.O13(PORT_A_RD_DATA[12]),
.O14(PORT_A_RD_DATA[13]),
.O15(PORT_A_RD_DATA[14]),
.O16(PORT_A_RD_DATA[15]),
.O17(PORT_A_RD_DATA[16]),
.O18(PORT_A_RD_DATA[17]),
.O19(PORT_B_RD_DATA[0]),
.O20(PORT_B_RD_DATA[1]),
.O21(PORT_B_RD_DATA[2]),
.O22(PORT_B_RD_DATA[3]),
.O23(PORT_B_RD_DATA[4]),
.O24(PORT_B_RD_DATA[5]),
.O25(PORT_B_RD_DATA[6]),
.O26(PORT_B_RD_DATA[7]),
.O27(PORT_B_RD_DATA[8]),
.O28(PORT_B_RD_DATA[9]),
.O29(PORT_B_RD_DATA[10]),
.O30(PORT_B_RD_DATA[11]),
.O31(PORT_B_RD_DATA[12]),
.O32(PORT_B_RD_DATA[13]),
.O33(PORT_B_RD_DATA[14]),
.O34(PORT_B_RD_DATA[15]),
.O35(PORT_B_RD_DATA[16]),
.O36(PORT_B_RD_DATA[17]),
.RA1(PORT_A_ADDR[0]),
.RA2(PORT_A_ADDR[1]),
.RA3(PORT_A_ADDR[2]),
.RA4(PORT_A_ADDR[3]),
.RA5(PORT_A_ADDR[4]),
.RA6(PORT_B_ADDR[0]),
.RA7(PORT_B_ADDR[1]),
.RA8(PORT_B_ADDR[2]),
.RA9(PORT_B_ADDR[3]),
.RA10(PORT_B_ADDR[4]),
.WA1(PORT_W_ADDR[0]),
.WA2(PORT_W_ADDR[1]),
.WA3(PORT_W_ADDR[2]),
.WA4(PORT_W_ADDR[3]),
.WA5(PORT_W_ADDR[4]),
.WA6(),
.WE(PORT_W_WR_EN),
.WEA(1'b0)
);
endmodule

View file

@ -0,0 +1,66 @@
# Register-File RAMs for NanoXplore NG-ULTRA
# Dual-port RAMs.
# NX_RFB_U in mode 0 (DPREG)
# NX_RFB_U in mode 2 (NX_XRFB_64x18)
# NX_RFB_U in mode 3 (NX_XRFB_32x36)
ram distributed $__NX_RFB_U_DPREG_ {
option "MODE" 0 {
cost 30;
widthscale 30;
abits 5;
widths 18 global;
}
option "MODE" 2 {
cost 50;
widthscale 30;
abits 6;
widths 18 global;
}
option "MODE" 3 {
cost 50;
widthscale 30;
abits 5;
widths 36 global;
}
init no_undef;
port sw "W" {
clock anyedge;
}
port ar "R" {
}
}
# Single-port RAMs.
# NX_RFB_U in mode 1 (SPREG)
ram distributed $__NX_RFB_U_SPREG_ {
cost 30;
widthscale;
abits 5;
width 18;
init no_undef;
port arsw "RW" {
clock anyedge;
}
}
# Single write dual read RAMs.
# NX_RFB_U in mode 4 (NX_XRFB_2R_1W)
ram distributed $__NX_XRFB_2R_1W_ {
cost 40;
widthscale 30;
abits 5;
width 18;
init no_undef;
port sw "W" {
clock anyedge;
}
port ar "A" {
}
port ar "B" {
}
}

View file

@ -0,0 +1,370 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2024 Hannah Ravensloft <lofty@yosyshq.com>
* Copyright (C) 2024 Miodrag Milanovic <micko@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SynthNanoXplorePass : public ScriptPass
{
SynthNanoXplorePass() : ScriptPass("synth_nanoxplore", "synthesis for NanoXplore FPGAs") { }
void on_register() override
{
RTLIL::constpad["synth_nanoxplore.abc9.W"] = "300";
}
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_nanoxplore [options]\n");
log("\n");
log("This command runs synthesis for NanoXplore FPGAs.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
log(" -family <family>\n");
log(" run synthesis for the specified NanoXplore architecture\n");
log(" generate the synthesis netlist for the specified family.\n");
log(" supported values:\n");
log(" - medium: NG-Medium\n");
log(" - large: NG-Large\n");
log(" - ultra: NG-Ultra\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(" -abc9\n");
log(" use new ABC9 flow (EXPERIMENTAL)\n");
log("\n");
log(" -nocy\n");
log(" do not map adders to CY cells\n");
log("\n");
log(" -nodffe\n");
log(" do not use flipflops with L in output netlist\n");
log("\n");
log(" -min_ce_use <min_ce_use>\n");
log(" do not use flip-flops with load signal if the resulting count is less\n");
log(" than min_ce_use in output netlist\n");
log("\n");
log(" -min_srst_use <min_srst_use>\n");
log(" do not use flip-flops with async reset signal if the resulting count is less\n");
log(" than min_srst_use in output netlist\n");
log("\n");
log(" -norfram\n");
log(" do not use Register File RAM cells in output netlist\n");
log("\n");
log(" -nobram\n");
log(" do not use block NX_RAM cells in output netlist\n");
log("\n");
log(" -noiopad\n");
log(" do not insert IO buffers\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, json_file, family;
bool flatten, abc9, nocy, nodffe, norfram, nobram, noiopad, no_rw_check;
std::string postfix;
int min_ce_use, min_srst_use;
void clear_flags() override
{
top_opt = "-auto-top";
json_file = "";
family = "";
flatten = true;
abc9 = false;
nocy = false;
nodffe = false;
norfram = false;
nobram = false;
noiopad = false;
no_rw_check = false;
postfix = "";
min_ce_use = 8;
min_srst_use = 8;
}
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] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) {
family = 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] == "-abc9") {
abc9 = true;
continue;
}
if (args[argidx] == "-nocy") {
nocy = true;
continue;
}
if (args[argidx] == "-nodffe") {
nodffe = true;
continue;
}
if (args[argidx] == "-min_ce_use" && argidx+1 < args.size()) {
min_ce_use = atoi(args[++argidx].c_str());
continue;
}
if (args[argidx] == "-min_srst_use" && argidx+1 < args.size()) {
min_srst_use = atoi(args[++argidx].c_str());
continue;
}
if (args[argidx] == "-norfram") {
norfram = true;
continue;
}
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
if (args[argidx] == "-iopad") {
noiopad = false;
continue;
}
if (args[argidx] == "-noiopad") {
noiopad = true;
continue;
}
if (args[argidx] == "-no-rw-check") {
no_rw_check = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if (family.empty()) {
//log_warning("NanoXplore family not set, setting it to NG-ULTRA.\n");
family = "ultra";
}
if (family == "ultra") {
postfix = "_u";
} else if (family == "medium") {
postfix = "_m";
} else if (family == "large") {
postfix = "_l";
} else
log_cmd_error("Invalid NanoXplore -family setting: '%s'.\n", family.c_str());
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
log_header(design, "Executing SYNTH_NANOXPLORE 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 +/nanoxplore/cells_sim.v +/nanoxplore/cells_sim" + postfix + ".v +/nanoxplore/cells_bb.v +/nanoxplore/cells_bb" + postfix + ".v");
run("techmap -map +/nanoxplore/cells_wrap.v");
run("techmap -map +/nanoxplore/cells_wrap" + postfix + ".v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
if (check_label("coarse"))
{
run("proc");
if (flatten || help_mode)
run("flatten", "(skip if -noflatten)");
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");
run("alumacc");
run("opt");
run("memory -nomap" + no_rw_check_opt);
run("opt_clean");
}
if (check_label("map_ram"))
{
std::string args = "";
if (family == "medium")
args += " -D IS_NG_MEDIUM";
if (nobram)
args += " -no-auto-block";
if (norfram)
args += " -no-auto-distributed";
if (help_mode)
args += " [-no-auto-block] [-no-auto-distributed]";
run("memory_libmap -lib +/nanoxplore/rf_rams"+ postfix + ".txt -lib +/nanoxplore/brams.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -norfram)");
run("techmap -map +/nanoxplore/rf_rams_map"+ postfix + ".v -map +/nanoxplore/brams_map.v");
run("techmap -map +/nanoxplore/cells_wrap.v t:NX_RAM*");
run("techmap -map +/nanoxplore/cells_wrap" + postfix + ".v t:NX_XRFB* t:NX_RFB*");
}
if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map");
run("opt -undriven -fine -mux_undef");
}
if (check_label("map_gates"))
{
if (nocy)
run("techmap");
else {
run("techmap -map +/techmap.v -map +/nanoxplore/arith_map.v");
run("nx_carry");
}
if (help_mode || !noiopad) {
run("iopadmap -bits -outpad $__BEYOND_OBUF I:PAD -toutpad $__BEYOND_TOBUF C:I:PAD -inpad $__BEYOND_IBUF O:PAD -tinoutpad $__BEYOND_IOBUF C:O:I:PAD A:top", "(skip if '-noiopad')");
run("techmap -map +/nanoxplore/io_map.v");
}
run("opt -fast");
}
if (check_label("map_ffs"))
{
std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_?P_ 01 -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_?P_ 01 -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r";
}
dfflegalize_args += stringf(" -cell $_DLATCH_?_ x -mince %d -minsrst %d", min_ce_use, min_srst_use);
run("dfflegalize" + dfflegalize_args,"($_*DFFE_* only if not -nodffe)");
run("opt_merge");
run("techmap -map +/nanoxplore/latches_map.v");
run("techmap -map +/nanoxplore/cells_map.v");
run("opt_expr -undriven -mux_undef");
run("clean -purge");
}
if (check_label("map_luts"))
{
if (abc9) {
std::string abc9_opts = " -maxlut 4";
std::string k = "synth_nanoxplore.abc9.W";
if (active_design && active_design->scratchpad.count(k))
abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str());
else
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
run("abc9" + abc9_opts);
} else {
std::string abc_args = " -dress";
abc_args += " -lut 4";
run("abc" + abc_args);
}
run("techmap -map +/nanoxplore/cells_map.v t:$lut");
run("opt -fast");
run("clean");
}
if (check_label("check"))
{
run("autoname");
run("hierarchy -check");
run("stat");
run("check -noinit");
run("blackbox =A:whitebox");
run("setundef -zero -undriven");
}
if (check_label("json"))
{
if (!json_file.empty() || help_mode)
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
}
}
} SynthNanoXplorePass;
PRIVATE_NAMESPACE_END

2
tests/arch/nanoxplore/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.log
/run-test.mk

View file

@ -0,0 +1,71 @@
read_verilog ../common/add_sub.v
hierarchy -top top
proc
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 2 t:NX_CY
select -assert-count 4 t:NX_LUT
select -assert-none t:NX_CY t:NX_LUT %% t:* %D
design -reset
read_verilog <<EOT
module top
(
input [5:0] x,
input [5:0] y,
output [5:0] A,
input CI,
output CO
);
assign {CO, A} = x + y + CI;
endmodule
EOT
hierarchy -top top
proc
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd top
stat
select -assert-count 2 t:NX_CY
select -assert-none t:NX_CY %% t:* %D
design -reset
read_verilog <<EOT
module top
(
input [189:0] x,
input [189:0] y,
output [189:0] A
);
assign A = x + y;
endmodule
EOT
hierarchy -top top
proc
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd top
stat
select -assert-count 48 t:NX_CY
select -assert-none t:NX_CY %% t:* %D

View file

@ -0,0 +1,47 @@
read_verilog ../common/adffs.v
design -save read
hierarchy -top adff
proc
equiv_opt -async2sync -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adff # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_DFF
select -assert-none t:NX_DFF %% t:* %D
design -load read
hierarchy -top adffn
proc
equiv_opt -async2sync -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adffn # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_DFF
select -assert-count 1 t:NX_LUT
select -assert-none t:NX_DFF t:NX_LUT %% t:* %D
design -load read
hierarchy -top dffs
proc
equiv_opt -async2sync -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffs # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_DFF
select -assert-count 1 t:NX_LUT
select -assert-none t:NX_DFF t:NX_LUT %% t:* %D
design -load read
hierarchy -top ndffnr
proc
equiv_opt -async2sync -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd ndffnr # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_DFF
select -assert-count 1 t:NX_LUT
select -assert-none t:NX_DFF t:NX_LUT %% t:* %D

View file

@ -0,0 +1,22 @@
read_verilog ../common/dffs.v
design -save read
hierarchy -top dff
proc
equiv_opt -assert -async2sync -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dff # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_DFF
select -assert-none t:NX_DFF %% t:* %D
design -load read
hierarchy -top dffe
proc
equiv_opt -assert -async2sync -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad -min_ce_use 0 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffe # Constrain all select calls below inside the top module
stat
select -assert-count 1 t:NX_DFF
select -assert-none t:NX_DFF %% t:* %D

View file

@ -0,0 +1,16 @@
read_verilog ../common/fsm.v
hierarchy -top fsm
proc
flatten
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad
async2sync
miter -equiv -make_assert -flatten gold gate miter
sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd fsm # Constrain all select calls below inside the top module
select -assert-count 6 t:NX_DFF
select -assert-min 13 t:NX_LUT
select -assert-none t:NX_DFF t:NX_LUT %% t:* %D

View file

@ -0,0 +1,33 @@
read_verilog ../common/latches.v
design -save read
hierarchy -top latchp
proc
# Can't run any sort of equivalence check because latches are blown to LUTs
synth_nanoxplore -noiopad
cd latchp # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D
design -load read
hierarchy -top latchn
proc
# Can't run any sort of equivalence check because latches are blown to LUTs
synth_nanoxplore -noiopad
cd latchn # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D
design -load read
hierarchy -top latchsr
proc
# Can't run any sort of equivalence check because latches are blown to LUTs
synth_nanoxplore -noiopad
cd latchsr # Constrain all select calls below inside the top module
select -assert-count 2 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D

View file

@ -0,0 +1,9 @@
read_verilog ../common/logic.v
hierarchy -top top
proc
equiv_opt -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 9 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D

View file

@ -0,0 +1,145 @@
# Dual-port RAMs.
# NX_RFB_U in mode 0 (DPREG)
read_verilog <<EOT
module lutram_dpreg
#(parameter D_WIDTH=18, A_WIDTH=5)
(
input [D_WIDTH-1:0] data,
input [A_WIDTH:1] addr_w, addr_r,
input we, clk,
output reg [D_WIDTH-1:0] q
);
// Declare the RAM variable
reg [D_WIDTH-1:0] ram[(2**A_WIDTH)-1:0];
// Port A
always @ (posedge clk)
begin
if (we)
ram[addr_w] <= data;
q <= ram[addr_r];
end
endmodule
EOT
hierarchy -top lutram_dpreg
proc
memory -nomap
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_dpreg
stat
select -assert-count 1 t:NX_RFB_U r:mode=0 %i
select -assert-count 18 t:NX_DFF
select -assert-none t:NX_RFB_U t:NX_DFF %% t:* %D
# Single-port RAMs.
# NX_RFB_U in mode 1 (SPREG)
design -reset
read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r -chparam A_WIDTH 5 -chparam D_WIDTH 18
proc
memory -nomap
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
select -assert-count 1 t:NX_RFB_U r:mode=1 %i
select -assert-count 18 t:NX_DFF
select -assert-none t:NX_RFB_U t:NX_DFF %% t:* %D
# Dual-port RAMs.
# NX_RFB_U in mode 2 (NX_XRFB_64x18)
design -reset
read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r -chparam A_WIDTH 6 -chparam D_WIDTH 18
proc
memory -nomap
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
select -assert-count 1 t:NX_RFB_U r:mode=2 %i
select -assert-count 18 t:NX_DFF
select -assert-none t:NX_RFB_U t:NX_DFF %% t:* %D
# Dual-port RAMs.
# NX_RFB_U in mode 3 (NX_XRFB_32x36)
design -reset
read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r -chparam A_WIDTH 5 -chparam D_WIDTH 36
proc
memory -nomap
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
select -assert-count 1 t:NX_RFB_U r:mode=3 %i
select -assert-count 36 t:NX_DFF
select -assert-none t:NX_RFB_U t:NX_DFF %% t:* %D
# Single write dual read RAMs.
# NX_RFB_U in mode 4 (NX_XRFB_2R_1W)
design -reset
read_verilog <<EOT
module lutram_1w2r
#(parameter D_WIDTH=8, A_WIDTH=5)
(
input [D_WIDTH-1:0] data_a, data_b,
input [A_WIDTH:1] addr_a, addr_b,
input we_a, clk,
output reg [D_WIDTH-1:0] q_a, q_b
);
// Declare the RAM variable
reg [D_WIDTH-1:0] ram[(2**A_WIDTH)-1:0];
// Port A
always @ (posedge clk)
begin
if (we_a)
ram[addr_a] <= data_a;
q_a <= ram[addr_a];
q_b <= ram[addr_b];
end
endmodule
EOT
hierarchy -top lutram_1w2r -chparam A_WIDTH 5 -chparam D_WIDTH 18
proc
memory -nomap
equiv_opt -run :prove -map +/nanoxplore/cells_sim.v -map +/nanoxplore/cells_sim_u.v synth_nanoxplore -noiopad
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w2r
select -assert-count 1 t:NX_RFB_U r:mode=4 %i
select -assert-count 36 t:NX_DFF
select -assert-none t:NX_RFB_U t:NX_DFF %% t:* %D

View file

@ -0,0 +1,50 @@
module top(clk);
parameter DEPTH_LOG2 = 10;
parameter WIDTH = 36;
parameter PRIME = 237481091;
localparam DEPTH = 2**DEPTH_LOG2;
input wire clk;
(* syn_ramstyle = "distributed" *)
reg [WIDTH-1:0] mem [DEPTH-1:0];
integer i;
initial begin
for (i = 0; i < DEPTH; i = i + 1) begin
// Make up data by multiplying a large prime with the address,
// then cropping and retaining the lower bits
mem[i] = PRIME * (i*2+1);
end
end
reg [DEPTH_LOG2-1:0] counter = 0;
reg done = 1'b0;
reg did_read = 1'b0;
reg [DEPTH_LOG2-1:0] read_addr;
reg [WIDTH-1:0] read_val;
always @(posedge clk) begin
if (!done) begin
did_read <= 1'b1;
read_addr <= counter;
read_val <= mem[counter];
end else begin
did_read <= 1'b0;
end
if (!done)
counter = counter + 1;
if (counter == 0)
done = 1;
end
wire [WIDTH-1:0] expect_val = PRIME * (read_addr*2+1);
always @(posedge clk) begin
if (did_read) begin
$display("addr %x expected %x actual %x", read_addr, expect_val, read_val);
assert(read_val == expect_val);
end
end
endmodule

View file

@ -0,0 +1,44 @@
read_verilog -sv meminit.v
chparam -set DEPTH_LOG2 5 -set WIDTH 36
prep
opt_dff
prep -rdff
synth_nanoxplore
clean_zerowidth
select -assert-none t:$mem_v2 t:$mem
read_verilog +/nanoxplore/cells_sim.v +/nanoxplore/cells_sim_u.v
prep
async2sync
hierarchy -top top
sim -assert -q -n 66 -clock clk
design -reset
read_verilog -sv meminit.v
chparam -set DEPTH_LOG2 6 -set WIDTH 18
prep
opt_dff
prep -rdff
synth_nanoxplore
clean_zerowidth
select -assert-none t:$mem_v2 t:$mem
read_verilog +/nanoxplore/cells_sim.v +/nanoxplore/cells_sim_u.v
prep
async2sync
hierarchy -top top
sim -assert -q -n 34 -clock clk
design -reset
read_verilog -sv meminit.v
chparam -set DEPTH_LOG2 8 -set WIDTH 18
prep
opt_dff
prep -rdff
synth_nanoxplore
clean_zerowidth
select -assert-none t:$mem_v2 t:$mem
read_verilog +/nanoxplore/cells_sim.v +/nanoxplore/cells_sim_u.v
prep
async2sync
hierarchy -top top
sim -assert -q -n 258 -clock clk

View file

@ -0,0 +1,41 @@
read_verilog ../common/mux.v
design -save read
hierarchy -top mux2
proc
equiv_opt -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux2 # Constrain all select calls below inside the top module
select -assert-count 1 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D
design -load read
hierarchy -top mux4
proc
equiv_opt -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux4 # Constrain all select calls below inside the top module
#select -assert-count 2 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D
design -load read
hierarchy -top mux8
proc
equiv_opt -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
#select -assert-count 5 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D
design -load read
hierarchy -top mux16
proc
equiv_opt -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
select -assert-max 13 t:NX_LUT
select -assert-none t:NX_LUT %% t:* %D

View file

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -eu
source ../../gen-tests-makefile.sh
run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'"

View file

@ -0,0 +1,10 @@
read_verilog ../common/shifter.v
hierarchy -top top
proc
flatten
equiv_opt -async2sync -assert -map +/nanoxplore/cells_sim.v synth_nanoxplore -noiopad # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 8 t:NX_DFF
select -assert-none t:NX_DFF %% t:* %D

View file

@ -0,0 +1,13 @@
read_verilog ../common/tribuf.v
hierarchy -top tristate
proc
tribuf
flatten
synth
equiv_opt -assert -map +/nanoxplore/cells_sim.v -map +/simcells.v synth_nanoxplore # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd tristate # Constrain all select calls below inside the top module
#Internal cell type used. Need support it.
select -assert-count 1 t:NX_IOB
select -assert-count 2 t:NX_IOB_I
select -assert-none t:NX_IOB t:NX_IOB_I %% t:* %D

View file

@ -1,2 +1,4 @@
*.log
test.ys
*.filtered
*.verilogsim

View file

@ -0,0 +1,15 @@
library(ls05_stdcells) {
cell(XNOR2X1) {
area : 206080.0 ;
pin(B) {
direction : input ;
}
pin(A) {
direction : input ;
}
pin(Y) {
direction : output ;
function : !(B&!A|!B&A) ;
}
}
}

View file

@ -0,0 +1,6 @@
module XNOR2X1 (B, A, Y);
input B;
input A;
output Y;
assign Y = !(B&!A|!B&A); // !(B&!A|!B&A)
endmodule

View file

@ -0,0 +1,8 @@
library(supergate) {
cell(SRAM) {
area : 1 ;
pin(CE1) {
direction : input ;
}
}
}

View file

@ -0,0 +1,3 @@
module SRAM (CE1);
input CE1;
endmodule

View file

@ -0,0 +1,4 @@
library(fake) {
cell(bugbad) {
}
}

View file

@ -0,0 +1,2 @@
module bugbad ();
endmodule

View file

@ -0,0 +1,211 @@
library(supergate) {
cell(inv) {
area : 1 ;
pin(A) {
direction : input ;
}
pin(Y) {
direction : output ;
function : A' ;
}
}
cell(tri_inv) {
area : 4 ;
pin(A) {
direction : input ;
}
pin(S) {
direction : input ;
}
pin(Z) {
direction : output ;
function : A' ;
}
}
cell(buffer) {
area : 5 ;
pin(A) {
direction : input ;
}
pin(Y) {
direction : output ;
function : A ;
}
}
cell(nand2) {
area : 3 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(Y) {
direction : output ;
function : (A * B)' ;
}
}
cell(nor2) {
area : 3 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(Y) {
direction : output ;
function : (A + B)' ;
}
}
cell(xor2) {
area : 6 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(Y) {
direction : output ;
function : (A *B') + (A' * B) ;
}
}
cell(imux2) {
area : 5 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(S) {
direction : input ;
}
pin(Y) {
direction : output ;
function : ( (A * S) + (B * S') )' ;
}
}
cell(dff) {
area : 6 ;
ff(IQ, IQN) {
next_state : D ;
clocked_on : CLK ;
clear : RESET ;
preset : PRESET ;
clear_preset_var1 : L ;
clear_preset_var2 : L ;
}
pin(D) {
direction : input ;
}
pin(CLK) {
direction : input ;
}
pin(RESET) {
direction : input ;
}
pin(PRESET) {
direction : input ;
}
pin(Q) {
direction : output ;
function : IQ ;
}
pin(QN) {
direction : output ;
function : IQN ;
}
}
cell(latch) {
area : 5 ;
latch(IQ, IQN) {
enable : G ;
data_in : D ;
}
pin(D) {
direction : input ;
}
pin(G) {
direction : input ;
}
pin(Q) {
direction : output ;
function : IQ ;
}
pin(QN) {
direction : output ;
function : IQN ;
}
}
cell(aoi211) {
area : 3 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(C) {
direction : input ;
}
pin(Y) {
direction : output ;
function : ((A * B) + C)' ;
}
}
cell(oai211) {
area : 3 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(C) {
direction : input ;
}
pin(Y) {
direction : output ;
function : ((A + B) * C)' ;
}
}
cell(halfadder) {
area : 5 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(C) {
direction : output ;
function : (A * B) ;
}
pin(Y) {
direction : output ;
function : (A *B') + (A' * B) ;
}
}
cell(fulladder) {
area : 8 ;
pin(A) {
direction : input ;
}
pin(B) {
direction : input ;
}
pin(CI) {
direction : input ;
}
pin(CO) {
direction : output ;
function : (((A * B)+(B * CI))+(CI * A)) ;
}
pin(Y) {
direction : output ;
function : ((A^B)^CI) ;
}
}
}

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