mirror of
https://github.com/YosysHQ/yosys
synced 2025-05-11 09:44:44 +00:00
Merge branch 'YosysHQ:main' into abc-custom-flow
This commit is contained in:
commit
3f2b391036
291 changed files with 18481 additions and 11714 deletions
|
@ -10,3 +10,7 @@ insert_final_newline = true
|
|||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
3
.github/actions/setup-build-env/action.yml
vendored
3
.github/actions/setup-build-env/action.yml
vendored
|
@ -14,7 +14,8 @@ runs:
|
|||
if: runner.os == 'macOS'
|
||||
shell: bash
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install bison flex gawk libffi pkg-config bash autoconf llvm
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew update
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install bison flex gawk libffi pkg-config bash autoconf llvm lld || true
|
||||
|
||||
- name: Linux runtime environment
|
||||
if: runner.os == 'Linux'
|
||||
|
|
37
.github/workflows/prepare-docs.yml
vendored
37
.github/workflows/prepare-docs.yml
vendored
|
@ -1,12 +1,32 @@
|
|||
name: Build docs artifact with Verific
|
||||
|
||||
on: push
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
check_docs_rebuild:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
skip_check: ${{ steps.skip_check.outputs.should_skip }}
|
||||
docs_export: ${{ steps.docs_var.outputs.docs_export }}
|
||||
env:
|
||||
docs_export: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/docs-preview') || startsWith(github.ref, 'refs/tags/') }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
paths_ignore: '["**/README.md"]'
|
||||
# don't cancel in case we're updating docs
|
||||
cancel_others: 'false'
|
||||
# only run on push *or* pull_request, not both
|
||||
concurrent_skipping: ${{ env.docs_export && 'never' || 'same_content_newer'}}
|
||||
- id: docs_var
|
||||
run: echo "docs_export=${{ env.docs_export }}" >> $GITHUB_OUTPUT
|
||||
|
||||
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/') }}
|
||||
needs: check_docs_rebuild
|
||||
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' }}
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
|
@ -32,7 +52,7 @@ jobs:
|
|||
- name: Prepare docs
|
||||
shell: bash
|
||||
run:
|
||||
make docs/prep TARGETS= EXTRA_TARGETS=
|
||||
make docs/prep -j${{ env.procs }} TARGETS= EXTRA_TARGETS=
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
@ -44,7 +64,18 @@ jobs:
|
|||
docs/source/_images
|
||||
docs/source/code_examples
|
||||
|
||||
- name: Install doc prereqs
|
||||
shell: bash
|
||||
run: |
|
||||
make docs/reqs
|
||||
|
||||
- name: Test build docs
|
||||
shell: bash
|
||||
run: |
|
||||
make -C docs html -j${{ env.procs }} TARGETS= EXTRA_TARGETS=
|
||||
|
||||
- name: Trigger RTDs build
|
||||
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' }}
|
||||
uses: dfm/rtds-action@v1.1.0
|
||||
with:
|
||||
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
|
||||
|
|
33
.github/workflows/source-vendor.yml
vendored
Normal file
33
.github/workflows/source-vendor.yml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
name: Create source archive with vendored dependencies
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
vendor-sources:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository with submodules
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Create clean tarball
|
||||
run: |
|
||||
git archive --format=tar HEAD -o yosys-src-vendored.tar
|
||||
git submodule foreach '
|
||||
git archive --format=tar --prefix="${sm_path}/" HEAD --output=${toplevel}/vendor-${name}.tar
|
||||
'
|
||||
|
||||
# 2008 bug https://lists.gnu.org/archive/html/bug-tar/2008-08/msg00002.html
|
||||
for file in vendor-*.tar; do
|
||||
tar --concatenate --file=yosys-src-vendored.tar "$file"
|
||||
done
|
||||
|
||||
gzip yosys-src-vendored.tar
|
||||
|
||||
- name: Store tarball artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vendored-sources
|
||||
path: yosys-src-vendored.tar.gz
|
||||
retention-days: 1
|
52
.github/workflows/test-build.yml
vendored
52
.github/workflows/test-build.yml
vendored
|
@ -100,6 +100,16 @@ jobs:
|
|||
cd iverilog
|
||||
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||
|
||||
- name: Get vcd2fst
|
||||
shell: bash
|
||||
run: |
|
||||
git clone https://github.com/mmicko/libwave.git
|
||||
mkdir -p ${{ github.workspace }}/.local/
|
||||
cd libwave
|
||||
cmake . -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/.local
|
||||
make -j$procs
|
||||
make install
|
||||
|
||||
- name: Cache iverilog
|
||||
id: cache-iverilog
|
||||
uses: actions/cache@v4
|
||||
|
@ -179,3 +189,45 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
make -C docs test -j${{ env.procs }}
|
||||
|
||||
test-docs-build:
|
||||
name: Try build docs
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
needs: [pre_docs_job]
|
||||
if: needs.pre_docs_job.outputs.should_skip != 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
docs-target: [html, latexpdf]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Runtime environment
|
||||
run: |
|
||||
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||
|
||||
- name: Build Yosys
|
||||
run: |
|
||||
make config-clang
|
||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||
make -j${{ env.procs }}
|
||||
|
||||
- name: Install doc prereqs
|
||||
shell: bash
|
||||
run: |
|
||||
make docs/reqs
|
||||
|
||||
- name: Build docs
|
||||
shell: bash
|
||||
run: |
|
||||
make docs DOC_TARGET=${{ matrix.docs-target }} -j${{ env.procs }}
|
||||
|
||||
- name: Store docs build artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: docs-build-${{ matrix.docs-target }}
|
||||
path: docs/build/
|
||||
retention-days: 7
|
||||
|
|
136
.github/workflows/wheels.yml
vendored
Normal file
136
.github/workflows/wheels.yml
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
name: Build Wheels for PyPI
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_wheels:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [
|
||||
{
|
||||
name: "Ubuntu 22.04",
|
||||
family: "linux",
|
||||
runner: "ubuntu-22.04",
|
||||
archs: "x86_64",
|
||||
},
|
||||
## Aarch64 is disabled for now: GitHub is committing to EOY
|
||||
## for free aarch64 runners for open-source projects and
|
||||
## emulation times out:
|
||||
## https://github.com/orgs/community/discussions/19197#discussioncomment-10550689
|
||||
# {
|
||||
# name: "Ubuntu 22.04",
|
||||
# family: "linux",
|
||||
# runner: "ubuntu-22.04",
|
||||
# archs: "aarch64",
|
||||
# },
|
||||
{
|
||||
name: "macOS 13",
|
||||
family: "macos",
|
||||
runner: "macos-13",
|
||||
archs: "x86_64",
|
||||
},
|
||||
{
|
||||
name: "macOS 14",
|
||||
family: "macos",
|
||||
runner: "macos-14",
|
||||
archs: "arm64",
|
||||
},
|
||||
## Windows is disabled because of an issue with compiling FFI as
|
||||
## under MinGW in the GitHub Actions environment (SHELL variable has
|
||||
## whitespace.)
|
||||
# {
|
||||
# name: "Windows Server 2019",
|
||||
# family: "windows",
|
||||
# runner: "windows-2019",
|
||||
# archs: "AMD64",
|
||||
# },
|
||||
]
|
||||
name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }}
|
||||
runs-on: ${{ matrix.os.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- if: ${{ matrix.os.family == 'linux' }}
|
||||
name: "[Linux] Set up QEMU"
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- uses: actions/setup-python@v5
|
||||
- name: Get Boost Source
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p boost
|
||||
curl -L https://github.com/boostorg/boost/releases/download/boost-1.86.0/boost-1.86.0-b2-nodocs.tar.gz | tar --strip-components=1 -xzC boost
|
||||
- name: Get FFI
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ffi
|
||||
curl -L https://github.com/libffi/libffi/releases/download/v3.4.6/libffi-3.4.6.tar.gz | tar --strip-components=1 -xzC ffi
|
||||
## Software installed by default in GitHub Action Runner VMs:
|
||||
## https://github.com/actions/runner-images
|
||||
- if: ${{ matrix.os.family == 'macos' }}
|
||||
name: "[macOS] Flex/Bison"
|
||||
run: |
|
||||
brew install flex bison
|
||||
echo "PATH=$(brew --prefix flex)/bin:$PATH" >> $GITHUB_ENV
|
||||
echo "PATH=$(brew --prefix bison)/bin:$PATH" >> $GITHUB_ENV
|
||||
- if: ${{ matrix.os.family == 'windows' }}
|
||||
name: "[Windows] Flex/Bison"
|
||||
run: |
|
||||
choco install winflexbison3
|
||||
- if: ${{ matrix.os.family == 'macos' && matrix.os.archs == 'arm64' }}
|
||||
name: "[macOS/arm64] Install Python 3.8 (see: https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64)"
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v2.21.1
|
||||
env:
|
||||
# * APIs not supported by PyPy
|
||||
# * Musllinux disabled because it increases build time from 48m to ~3h
|
||||
CIBW_SKIP: >
|
||||
pp*
|
||||
*musllinux*
|
||||
CIBW_ARCHS: ${{ matrix.os.archs }}
|
||||
CIBW_BUILD_VERBOSITY: "1"
|
||||
# manylinux2014 (default) does not have a modern enough C++ compiler for Yosys
|
||||
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
|
||||
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
|
||||
CIBW_BEFORE_ALL: bash ./.github/workflows/wheels/cibw_before_all.sh
|
||||
CIBW_ENVIRONMENT: >
|
||||
CXXFLAGS=-I./boost/pfx/include
|
||||
LINKFLAGS=-L./boost/pfx/lib
|
||||
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
|
||||
makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a'
|
||||
CIBW_ENVIRONMENT_MACOS: >
|
||||
CXXFLAGS=-I./boost/pfx/include
|
||||
LINKFLAGS=-L./boost/pfx/lib
|
||||
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
|
||||
MACOSX_DEPLOYMENT_TARGET=11
|
||||
makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang'
|
||||
CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh
|
||||
CIBW_TEST_COMMAND: python3 {project}/tests/arch/ecp5/add_sub.py
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: python-wheels-${{ matrix.os.runner }}
|
||||
path: ./wheelhouse/*.whl
|
||||
upload_wheels:
|
||||
name: Upload Wheels
|
||||
runs-on: ubuntu-latest
|
||||
needs: build_wheels
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: "."
|
||||
pattern: python-wheels-*
|
||||
merge-multiple: true
|
||||
- run: |
|
||||
ls
|
||||
mkdir -p ./dist
|
||||
mv *.whl ./dist
|
||||
- name: Publish
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
repository-url: ${{ vars.PYPI_INDEX || 'https://upload.pypi.org/legacy/' }}
|
44
.github/workflows/wheels/_run_cibw_linux.py
vendored
Normal file
44
.github/workflows/wheels/_run_cibw_linux.py
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2024 Efabless Corporation
|
||||
#
|
||||
# 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.
|
||||
"""
|
||||
This runs the cibuildwheel step from the wheels workflow locally.
|
||||
"""
|
||||
|
||||
import os
|
||||
import yaml
|
||||
import platform
|
||||
import subprocess
|
||||
|
||||
__dir__ = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
workflow = yaml.safe_load(open(os.path.join(os.path.dirname(__dir__), "wheels.yml")))
|
||||
|
||||
env = os.environ.copy()
|
||||
|
||||
steps = workflow["jobs"]["build_wheels"]["steps"]
|
||||
cibw_step = None
|
||||
for step in steps:
|
||||
if (step.get("uses") or "").startswith("pypa/cibuildwheel"):
|
||||
cibw_step = step
|
||||
break
|
||||
|
||||
for key, value in cibw_step["env"].items():
|
||||
if key.endswith("WIN") or key.endswith("MAC"):
|
||||
continue
|
||||
env[key] = value
|
||||
|
||||
env["CIBW_ARCHS"] = os.getenv("CIBW_ARCHS") or platform.machine()
|
||||
subprocess.check_call(["cibuildwheel"], env=env)
|
23
.github/workflows/wheels/cibw_before_all.sh
vendored
Normal file
23
.github/workflows/wheels/cibw_before_all.sh
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
set -e
|
||||
set -x
|
||||
|
||||
# Build-time dependencies
|
||||
## Linux Docker Images
|
||||
if command -v yum &> /dev/null; then
|
||||
yum install -y flex bison
|
||||
fi
|
||||
|
||||
if command -v apk &> /dev/null; then
|
||||
apk add flex bison
|
||||
fi
|
||||
|
||||
## macOS/Windows -- installed in GitHub Action itself, not container
|
||||
|
||||
# Build Static FFI (platform-dependent but not Python version dependent)
|
||||
cd ffi
|
||||
## Ultimate libyosys.so will be shared, so we need fPIC for the static libraries
|
||||
CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --prefix=$PWD/pfx
|
||||
## Without this, SHELL has a space in its path which breaks the makefile
|
||||
make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu)
|
||||
## Forces static library to be used in all situations
|
||||
sed -i.bak 's@-L${toolexeclibdir} -lffi@${toolexeclibdir}/libffi.a@' ./pfx/lib/pkgconfig/libffi.pc
|
34
.github/workflows/wheels/cibw_before_build.sh
vendored
Normal file
34
.github/workflows/wheels/cibw_before_build.sh
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
set -e
|
||||
set -x
|
||||
|
||||
# Don't use objects from previous compiles on Windows/macOS
|
||||
make clean
|
||||
|
||||
# DEBUG: show python3 and python3-config outputs
|
||||
if [ "$(uname)" != "Linux" ]; then
|
||||
# https://github.com/pypa/cibuildwheel/issues/2021
|
||||
ln -s $(dirname $(readlink -f $(which python3)))/python3-config $(dirname $(which python3))/python3-config
|
||||
fi
|
||||
python3 --version
|
||||
python3-config --includes
|
||||
|
||||
# Build boost
|
||||
cd ./boost
|
||||
## Delete the artefacts from previous builds (if any)
|
||||
rm -rf ./pfx
|
||||
## Bootstrap bjam
|
||||
./bootstrap.sh --prefix=./pfx
|
||||
## Build Boost against current version of Python, only for
|
||||
## static linkage (Boost is statically linked because system boost packages
|
||||
## wildly vary in versions, including the libboost_python3 version)
|
||||
./b2\
|
||||
-j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu)\
|
||||
--prefix=./pfx\
|
||||
--with-filesystem\
|
||||
--with-system\
|
||||
--with-python\
|
||||
cxxflags="$(python3-config --includes) -std=c++17 -fPIC"\
|
||||
cflags="$(python3-config --includes) -fPIC"\
|
||||
link=static\
|
||||
variant=release\
|
||||
install
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -45,4 +45,10 @@ __pycache__
|
|||
/tests/unit/bintest/
|
||||
/tests/unit/objtest/
|
||||
/tests/ystests
|
||||
/result
|
||||
/result
|
||||
/dist
|
||||
/*.egg-info
|
||||
/build
|
||||
/venv
|
||||
/boost
|
||||
/ffi
|
||||
|
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -1,3 +1,7 @@
|
|||
[submodule "abc"]
|
||||
path = abc
|
||||
url = https://github.com/YosysHQ/abc
|
||||
# Don't use paths as names to avoid git archive problems
|
||||
[submodule "cxxopts"]
|
||||
path = libs/cxxopts
|
||||
url = https://github.com/jarro2783/cxxopts
|
||||
|
|
1
Brewfile
1
Brewfile
|
@ -11,3 +11,4 @@ brew "xdot"
|
|||
brew "bash"
|
||||
brew "boost-python3"
|
||||
brew "llvm"
|
||||
brew "lld"
|
||||
|
|
41
CHANGELOG
41
CHANGELOG
|
@ -2,9 +2,48 @@
|
|||
List of major changes and improvements between releases
|
||||
=======================================================
|
||||
|
||||
Yosys 0.45 .. Yosys 0.46-dev
|
||||
Yosys 0.47 .. Yosys 0.48-dev
|
||||
--------------------------
|
||||
|
||||
Yosys 0.46 .. Yosys 0.47
|
||||
--------------------------
|
||||
* Various
|
||||
- Added cxxopts library for handling command line arguments.
|
||||
- Added docs generation from cells help output.
|
||||
|
||||
* New commands and options
|
||||
- Added "-json" option to "synth_xilinx" pass.
|
||||
- Added "-derive_luts" option to "cellmatch" pass.
|
||||
- Added "t:@<name>" syntax to "select" pass.
|
||||
- Added "-list-mod" option to "select" pass.
|
||||
- Removed deprecated "qwp" pass.
|
||||
|
||||
* Verific support
|
||||
- Initial state handling for VHDL assertions.
|
||||
|
||||
Yosys 0.45 .. Yosys 0.46
|
||||
--------------------------
|
||||
* Various
|
||||
- Added new "functional backend" infrastructure with three example
|
||||
backends (C++, SMTLIB and Rosette).
|
||||
- Added new coarse-grain buffer cell type "$buf" to RTLIL.
|
||||
- Added "-y" command line option to execute a Python script with
|
||||
libyosys available as a built-in module.
|
||||
- Added support for casting to type in Verilog frontend.
|
||||
|
||||
* New commands and options
|
||||
- Added "clockgate" pass for automatic clock gating cell insertion.
|
||||
- Added "bufnorm" experimental pass to convert design into
|
||||
buffered-normalized form.
|
||||
- Added experimental "aiger2" and "xaiger2" backends, and an
|
||||
experimental "abc_new" command
|
||||
- Added "-force-detailed-loop-check" option to "check" pass.
|
||||
- Added "-unit_delay" option to "read_liberty" pass.
|
||||
|
||||
* Verific support
|
||||
- Added left and right bound properties to wires when using
|
||||
specific VHDL types.
|
||||
|
||||
Yosys 0.44 .. Yosys 0.45
|
||||
--------------------------
|
||||
* Various
|
||||
|
|
48
Makefile
48
Makefile
|
@ -118,6 +118,7 @@ AWK ?= awk
|
|||
|
||||
ifeq ($(OS), Darwin)
|
||||
PLUGIN_LINKFLAGS += -undefined dynamic_lookup
|
||||
LINKFLAGS += -rdynamic
|
||||
|
||||
# homebrew search paths
|
||||
ifneq ($(shell :; command -v brew),)
|
||||
|
@ -154,7 +155,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.45+139
|
||||
YOSYS_VER := 0.47+22
|
||||
|
||||
# Note: We arrange for .gitcommit to contain the (short) commit hash in
|
||||
# tarballs generated with git-archive(1) using .gitattributes. The git repo
|
||||
|
@ -170,7 +171,7 @@ endif
|
|||
OBJS = kernel/version_$(GIT_REV).o
|
||||
|
||||
bumpversion:
|
||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 9ed031d.. | wc -l`/;" Makefile
|
||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 647d61d.. | wc -l`/;" Makefile
|
||||
|
||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
|
||||
|
||||
|
@ -737,12 +738,18 @@ compile-only: $(OBJS) $(GENFILES) $(EXTRA_TARGETS)
|
|||
@echo " Compile successful."
|
||||
@echo ""
|
||||
|
||||
.PHONY: share
|
||||
share: $(EXTRA_TARGETS)
|
||||
@echo ""
|
||||
@echo " Share directory created."
|
||||
@echo ""
|
||||
|
||||
$(PROGRAM_PREFIX)yosys$(EXE): $(OBJS)
|
||||
$(P) $(CXX) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LINKFLAGS) $(LINKFLAGS) $(OBJS) $(LIBS) $(LIBS_VERIFIC)
|
||||
|
||||
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
|
||||
ifeq ($(OS), Darwin)
|
||||
$(P) $(CXX) -o libyosys.so -shared -Wl,-install_name,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC)
|
||||
$(P) $(CXX) -o libyosys.so -shared -undefined dynamic_lookup -Wl,-install_name,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC)
|
||||
else
|
||||
$(P) $(CXX) -o libyosys.so -shared -Wl,-soname,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC)
|
||||
endif
|
||||
|
@ -924,8 +931,8 @@ ystests: $(TARGETS) $(EXTRA_TARGETS)
|
|||
|
||||
# Unit test
|
||||
unit-test: libyosys.so
|
||||
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" \
|
||||
CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)"
|
||||
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" \
|
||||
CXXFLAGS="$(CXXFLAGS)" LINKFLAGS="$(LINKFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)"
|
||||
|
||||
clean-unit-test:
|
||||
@$(MAKE) -C $(UNITESTPATH) clean
|
||||
|
@ -975,20 +982,30 @@ endif
|
|||
|
||||
# also others, but so long as it doesn't fail this is enough to know we tried
|
||||
docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS)
|
||||
mkdir -p docs/source/cmd
|
||||
./$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual'
|
||||
$(Q) mkdir -p docs/source/cmd
|
||||
$(Q) mkdir -p temp/docs/source/cmd
|
||||
$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual'
|
||||
$(Q) rsync -rc temp/docs/source/cmd docs/source
|
||||
$(Q) rm -rf temp
|
||||
docs/source/cell/word_add.rst: $(TARGETS) $(EXTRA_TARGETS)
|
||||
$(Q) mkdir -p docs/source/cell
|
||||
$(Q) mkdir -p temp/docs/source/cell
|
||||
$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-cells-manual'
|
||||
$(Q) rsync -rc temp/docs/source/cell docs/source
|
||||
$(Q) rm -rf temp
|
||||
|
||||
PHONY: docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs
|
||||
docs/gen_examples:
|
||||
$(Q) $(MAKE) -C docs examples
|
||||
docs/source/generated/cells.json: docs/source/generated $(TARGETS) $(EXTRA_TARGETS)
|
||||
$(Q) ./$(PROGRAM_PREFIX)yosys -p 'help -dump-cells-json $@'
|
||||
|
||||
docs/gen_images:
|
||||
$(Q) $(MAKE) -C docs images
|
||||
PHONY: docs/gen docs/guidelines docs/usage docs/reqs
|
||||
docs/gen: $(TARGETS)
|
||||
$(Q) $(MAKE) -C docs gen
|
||||
|
||||
DOCS_GUIDELINE_FILES := GettingStarted CodingStyle
|
||||
docs/guidelines docs/source/generated:
|
||||
DOCS_GUIDELINE_SOURCE := $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES))
|
||||
docs/guidelines docs/source/generated: $(DOCS_GUIDELINE_SOURCE)
|
||||
$(Q) mkdir -p docs/source/generated
|
||||
$(Q) cp -f $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES)) docs/source/generated
|
||||
$(Q) cp -f $(DOCS_GUIDELINE_SOURCE) docs/source/generated
|
||||
|
||||
# some commands return an error and print the usage text to stderr
|
||||
define DOC_USAGE_STDERR
|
||||
|
@ -1018,7 +1035,7 @@ 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
|
||||
docs/prep: docs/source/cmd/abc.rst docs/source/generated/cells.json docs/gen docs/guidelines docs/usage
|
||||
|
||||
DOC_TARGET ?= html
|
||||
docs: docs/prep
|
||||
|
@ -1078,6 +1095,7 @@ vcxsrc: $(GENFILES) $(EXTRA_TARGETS)
|
|||
rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip}
|
||||
set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \
|
||||
echo "Analyse: $$f" >&2; cpp -std=c++17 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt
|
||||
echo "libs/fst/fst_win_unistd.h" >> srcfiles.txt
|
||||
bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV)
|
||||
echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc
|
||||
zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc
|
||||
|
|
11
README.md
11
README.md
|
@ -33,6 +33,9 @@ Yosys is free software licensed under the ISC license (a GPL
|
|||
compatible license that is similar in terms to the MIT license
|
||||
or the 2-clause BSD license).
|
||||
|
||||
Third-party software distributed alongside this software
|
||||
is licensed under compatible licenses.
|
||||
Please refer to `abc` and `libs` subdirectories for their license terms.
|
||||
|
||||
Web Site and Other Resources
|
||||
============================
|
||||
|
@ -127,9 +130,15 @@ lld by enabling LTO:
|
|||
|
||||
$ make ENABLE_LTO=1
|
||||
|
||||
On macOS, LTO requires using clang from homebrew which isn't in PATH
|
||||
rather than xcode clang.
|
||||
|
||||
$ make ENABLE_LTO=1 CXX=$(brew --prefix)/opt/llvm/bin/clang++
|
||||
|
||||
For other compilers and build configurations it might be
|
||||
necessary to make some changes to the config section of the
|
||||
Makefile.
|
||||
Makefile. It's also an alternative way to set the make variables
|
||||
mentioned above.
|
||||
|
||||
$ vi Makefile # ..or..
|
||||
$ vi Makefile.conf
|
||||
|
|
2
abc
2
abc
|
@ -1 +1 @@
|
|||
Subproject commit 2188bc71228b0788569d83ad2b7e7b91ca5dcc09
|
||||
Subproject commit cac8f99eaa220a5e3db5caeb87cef0a975c953a2
|
1
backends/aiger2/Makefile.inc
Normal file
1
backends/aiger2/Makefile.inc
Normal file
|
@ -0,0 +1 @@
|
|||
OBJS += backends/aiger2/aiger.o
|
1471
backends/aiger2/aiger.cc
Normal file
1471
backends/aiger2/aiger.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -387,7 +387,7 @@ struct BlifDumper
|
|||
auto &inputs = cell->getPort(ID::A);
|
||||
auto width = cell->parameters.at(ID::WIDTH).as_int();
|
||||
auto depth = cell->parameters.at(ID::DEPTH).as_int();
|
||||
vector<State> table = cell->parameters.at(ID::TABLE).bits;
|
||||
vector<State> table = cell->parameters.at(ID::TABLE).to_bits();
|
||||
while (GetSize(table) < 2*width*depth)
|
||||
table.push_back(State::S0);
|
||||
log_assert(inputs.size() == width);
|
||||
|
|
|
@ -711,9 +711,9 @@ struct BtorWorker
|
|||
Const initval;
|
||||
for (int i = 0; i < GetSize(sig_q); i++)
|
||||
if (initbits.count(sig_q[i]))
|
||||
initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
|
||||
initval.bits().push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
|
||||
else
|
||||
initval.bits.push_back(State::Sx);
|
||||
initval.bits().push_back(State::Sx);
|
||||
|
||||
int nid_init_val = -1;
|
||||
|
||||
|
@ -832,7 +832,10 @@ struct BtorWorker
|
|||
}
|
||||
}
|
||||
|
||||
if (constword)
|
||||
// If not fully defined, undef bits should be able to take a
|
||||
// different value for each address so we can't initialise from
|
||||
// one value (and btor2parser doesn't like it)
|
||||
if (constword && firstword.is_fully_def())
|
||||
{
|
||||
if (verbose)
|
||||
btorf("; initval = %s\n", log_signal(firstword));
|
||||
|
@ -1042,7 +1045,7 @@ struct BtorWorker
|
|||
Const c(bit.data);
|
||||
|
||||
while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr)
|
||||
c.bits.push_back(sig[i+GetSize(c)].data);
|
||||
c.bits().push_back(sig[i+GetSize(c)].data);
|
||||
|
||||
if (consts.count(c) == 0) {
|
||||
int sid = get_bv_sid(GetSize(c));
|
||||
|
@ -1077,6 +1080,7 @@ struct BtorWorker
|
|||
btorf("%d input %d\n", nid, sid);
|
||||
ywmap_input(s);
|
||||
nid_width[nid] = GetSize(s);
|
||||
add_nid_sig(nid, s);
|
||||
|
||||
for (int j = 0; j < GetSize(s); j++)
|
||||
nidbits.push_back(make_pair(nid, j));
|
||||
|
|
|
@ -10,11 +10,11 @@ cd test_cells.tmp
|
|||
|
||||
for fn in test_*.il; do
|
||||
../../../yosys -p "
|
||||
read_ilang $fn
|
||||
read_rtlil $fn
|
||||
rename gold gate
|
||||
synth
|
||||
|
||||
read_ilang $fn
|
||||
read_rtlil $fn
|
||||
miter -equiv -make_assert -flatten gold gate main
|
||||
hierarchy -top main
|
||||
write_btor ${fn%.il}.btor
|
||||
|
|
|
@ -328,7 +328,7 @@ struct FlowGraph {
|
|||
node_comb_defs[node].insert(chunk.wire);
|
||||
}
|
||||
}
|
||||
for (auto bit : sig.bits())
|
||||
for (auto bit : sig)
|
||||
bit_has_state[bit] |= is_ff;
|
||||
// Only comb defs of an entire wire in the right order can be inlined.
|
||||
if (!is_ff && sig.is_wire()) {
|
||||
|
@ -612,7 +612,7 @@ std::string escape_c_string(const std::string &input)
|
|||
output.push_back('"');
|
||||
for (auto c : input) {
|
||||
if (::isprint(c)) {
|
||||
if (c == '\\')
|
||||
if (c == '\\' || c == '"')
|
||||
output.push_back('\\');
|
||||
output.push_back(c);
|
||||
} else {
|
||||
|
@ -864,7 +864,7 @@ struct CxxrtlWorker {
|
|||
if (!module->has_attribute(ID(cxxrtl_template)))
|
||||
return {};
|
||||
|
||||
if (module->attributes.at(ID(cxxrtl_template)).flags != RTLIL::CONST_FLAG_STRING)
|
||||
if (!(module->attributes.at(ID(cxxrtl_template)).flags & RTLIL::CONST_FLAG_STRING))
|
||||
log_cmd_error("Attribute `cxxrtl_template' of module `%s' is not a string.\n", log_id(module));
|
||||
|
||||
std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
|
||||
|
@ -1665,15 +1665,15 @@ struct CxxrtlWorker {
|
|||
switch (bit) {
|
||||
case RTLIL::S0:
|
||||
case RTLIL::S1:
|
||||
compare_mask.bits.push_back(RTLIL::S1);
|
||||
compare_value.bits.push_back(bit);
|
||||
compare_mask.bits().push_back(RTLIL::S1);
|
||||
compare_value.bits().push_back(bit);
|
||||
break;
|
||||
|
||||
case RTLIL::Sx:
|
||||
case RTLIL::Sz:
|
||||
case RTLIL::Sa:
|
||||
compare_mask.bits.push_back(RTLIL::S0);
|
||||
compare_value.bits.push_back(RTLIL::S0);
|
||||
compare_mask.bits().push_back(RTLIL::S0);
|
||||
compare_value.bits().push_back(RTLIL::S0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -3028,7 +3028,7 @@ struct CxxrtlWorker {
|
|||
if (init == RTLIL::Const()) {
|
||||
init = RTLIL::Const(State::Sx, GetSize(bit.wire));
|
||||
}
|
||||
init[bit.offset] = port.init_value[i];
|
||||
init.bits()[bit.offset] = port.init_value[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1127,7 +1127,7 @@ struct fmt_part {
|
|||
}
|
||||
|
||||
case UNICHAR: {
|
||||
uint32_t codepoint = val.template get<uint32_t>();
|
||||
uint32_t codepoint = val.template zcast<32>().template get<uint32_t>();
|
||||
if (codepoint >= 0x10000)
|
||||
buf += (char)(0xf0 | (codepoint >> 18));
|
||||
else if (codepoint >= 0x800)
|
||||
|
|
|
@ -50,9 +50,13 @@ class vcd_writer {
|
|||
|
||||
void emit_scope(const std::vector<std::string> &scope) {
|
||||
assert(!streaming);
|
||||
while (current_scope.size() > scope.size() ||
|
||||
(current_scope.size() > 0 &&
|
||||
current_scope[current_scope.size() - 1] != scope[current_scope.size() - 1])) {
|
||||
size_t same_scope_count = 0;
|
||||
while ((same_scope_count < current_scope.size()) &&
|
||||
(same_scope_count < scope.size()) &&
|
||||
(current_scope[same_scope_count] == scope[same_scope_count])) {
|
||||
same_scope_count++;
|
||||
}
|
||||
while (current_scope.size() > same_scope_count) {
|
||||
buffer += "$upscope $end\n";
|
||||
current_scope.pop_back();
|
||||
}
|
||||
|
@ -123,6 +127,8 @@ class vcd_writer {
|
|||
bool bit_curr = var.curr[bit / (8 * sizeof(chunk_t))] & (1 << (bit % (8 * sizeof(chunk_t))));
|
||||
buffer += (bit_curr ? '1' : '0');
|
||||
}
|
||||
if (var.width == 0)
|
||||
buffer += '0';
|
||||
buffer += ' ';
|
||||
emit_ident(var.ident);
|
||||
buffer += '\n';
|
||||
|
|
|
@ -334,20 +334,20 @@ struct EdifBackend : public Backend {
|
|||
auto add_prop = [&](IdString name, Const val) {
|
||||
if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
|
||||
*f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str());
|
||||
else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def())
|
||||
else if (val.size() <= 32 && RTLIL::SigSpec(val).is_fully_def())
|
||||
*f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
|
||||
else {
|
||||
std::string hex_string = "";
|
||||
for (size_t i = 0; i < val.bits.size(); i += 4) {
|
||||
for (size_t i = 0; i < val.size(); i += 4) {
|
||||
int digit_value = 0;
|
||||
if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1;
|
||||
if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2;
|
||||
if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4;
|
||||
if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8;
|
||||
if (i+0 < val.size() && val.at(i+0) == RTLIL::State::S1) digit_value |= 1;
|
||||
if (i+1 < val.size() && val.at(i+1) == RTLIL::State::S1) digit_value |= 2;
|
||||
if (i+2 < val.size() && val.at(i+2) == RTLIL::State::S1) digit_value |= 4;
|
||||
if (i+3 < val.size() && val.at(i+3) == RTLIL::State::S1) digit_value |= 8;
|
||||
char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
|
||||
hex_string = std::string(digit_str) + hex_string;
|
||||
}
|
||||
*f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str());
|
||||
*f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val), hex_string.c_str());
|
||||
}
|
||||
};
|
||||
for (auto module : sorted_modules)
|
||||
|
|
|
@ -149,7 +149,7 @@ std::string dump_const(const RTLIL::Const &data)
|
|||
// Numeric (non-real) parameter.
|
||||
else
|
||||
{
|
||||
int width = data.bits.size();
|
||||
int width = data.size();
|
||||
|
||||
// If a standard 32-bit int, then emit standard int value like "56" or
|
||||
// "-56". Firrtl supports negative-valued int literals.
|
||||
|
@ -163,7 +163,7 @@ std::string dump_const(const RTLIL::Const &data)
|
|||
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
switch (data.bits[i])
|
||||
switch (data[i])
|
||||
{
|
||||
case State::S0: break;
|
||||
case State::S1: int_val |= (1 << i); break;
|
||||
|
@ -205,7 +205,7 @@ std::string dump_const(const RTLIL::Const &data)
|
|||
for (int i = width - 1; i >= 0; i--)
|
||||
{
|
||||
log_assert(i < width);
|
||||
switch (data.bits[i])
|
||||
switch (data[i])
|
||||
{
|
||||
case State::S0: res_str += "0"; break;
|
||||
case State::S1: res_str += "1"; break;
|
||||
|
|
|
@ -246,6 +246,8 @@ struct FunctionalCxxBackend : public Backend
|
|||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log("TODO: add help message\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void printCxx(std::ostream &stream, std::string, Module *module)
|
||||
|
|
|
@ -105,7 +105,7 @@ struct MemContentsTest {
|
|||
RTLIL::Const values;
|
||||
for(addr_t addr = low; addr <= high; addr++) {
|
||||
RTLIL::Const word(data_dist(rnd), data_width);
|
||||
values.bits.insert(values.bits.end(), word.bits.begin(), word.bits.end());
|
||||
values.bits().insert(values.bits().end(), word.begin(), word.end());
|
||||
}
|
||||
insert_concatenated(low, values);
|
||||
}
|
||||
|
@ -122,6 +122,8 @@ struct FunctionalTestGeneric : public Pass
|
|||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log("TODO: add help message\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
|
|
|
@ -176,11 +176,11 @@ struct IntersynthBackend : public Backend {
|
|||
}
|
||||
}
|
||||
for (auto ¶m : cell->parameters) {
|
||||
celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), log_id(param.first));
|
||||
if (param.second.bits.size() != 32) {
|
||||
celltype_code += stringf(" cfg:%d %s", int(param.second.size()), log_id(param.first));
|
||||
if (param.second.size() != 32) {
|
||||
node_code += stringf(" %s '", log_id(param.first));
|
||||
for (int i = param.second.bits.size()-1; i >= 0; i--)
|
||||
node_code += param.second.bits[i] == State::S1 ? "1" : "0";
|
||||
for (int i = param.second.size()-1; i >= 0; i--)
|
||||
node_code += param.second[i] == State::S1 ? "1" : "0";
|
||||
} else
|
||||
node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int());
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ YOSYS_NAMESPACE_BEGIN
|
|||
void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
|
||||
{
|
||||
if (width < 0)
|
||||
width = data.bits.size() - offset;
|
||||
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
|
||||
width = data.size() - offset;
|
||||
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.size()) {
|
||||
if (width == 32 && autoint) {
|
||||
int32_t val = 0;
|
||||
for (int i = 0; i < width; i++) {
|
||||
log_assert(offset+i < (int)data.bits.size());
|
||||
switch (data.bits[offset+i]) {
|
||||
log_assert(offset+i < (int)data.size());
|
||||
switch (data[offset+i]) {
|
||||
case State::S0: break;
|
||||
case State::S1: val |= 1 << i; break;
|
||||
default: val = -1; break;
|
||||
|
@ -58,8 +58,8 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
|
|||
f << "x";
|
||||
} else {
|
||||
for (int i = offset+width-1; i >= offset; i--) {
|
||||
log_assert(i < (int)data.bits.size());
|
||||
switch (data.bits[i]) {
|
||||
log_assert(i < (int)data.size());
|
||||
switch (data[i]) {
|
||||
case State::S0: f << stringf("0"); break;
|
||||
case State::S1: f << stringf("1"); break;
|
||||
case RTLIL::Sx: f << stringf("x"); break;
|
||||
|
@ -464,21 +464,6 @@ struct RTLILBackend : public Backend {
|
|||
}
|
||||
} RTLILBackend;
|
||||
|
||||
struct IlangBackend : public Backend {
|
||||
IlangBackend() : Backend("ilang", "(deprecated) alias of write_rtlil") { }
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log("See `help write_rtlil`.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
RTLILBackend.execute(f, filename, args, design);
|
||||
}
|
||||
} IlangBackend;
|
||||
|
||||
struct DumpPass : public Pass {
|
||||
DumpPass() : Pass("dump", "print parts of the design in RTLIL format") { }
|
||||
void help() override
|
||||
|
|
|
@ -657,7 +657,7 @@ struct SimplecWorker
|
|||
{
|
||||
SigSpec sig = sigmaps.at(module)(w);
|
||||
Const val = w->attributes.at(ID::init);
|
||||
val.bits.resize(GetSize(sig), State::Sx);
|
||||
val.bits().resize(GetSize(sig), State::Sx);
|
||||
|
||||
for (int i = 0; i < GetSize(sig); i++)
|
||||
if (val[i] == State::S0 || val[i] == State::S1) {
|
||||
|
|
|
@ -329,13 +329,14 @@ struct Smt2Worker
|
|||
{
|
||||
sigmap.apply(bit);
|
||||
|
||||
if (bit_driver.count(bit)) {
|
||||
export_cell(bit_driver.at(bit));
|
||||
sigmap.apply(bit);
|
||||
}
|
||||
|
||||
if (bit.wire == nullptr)
|
||||
return bit == RTLIL::State::S1 ? "true" : "false";
|
||||
|
||||
if (bit_driver.count(bit))
|
||||
export_cell(bit_driver.at(bit));
|
||||
sigmap.apply(bit);
|
||||
|
||||
if (fcache.count(bit) == 0) {
|
||||
if (verbose) log("%*s-> external bool: %s\n", 2+2*GetSize(recursive_cells), "",
|
||||
log_signal(bit));
|
||||
|
@ -1077,14 +1078,14 @@ struct Smt2Worker
|
|||
|
||||
RTLIL::SigSpec sig = sigmap(wire);
|
||||
Const val = wire->attributes.at(ID::init);
|
||||
val.bits.resize(GetSize(sig), State::Sx);
|
||||
val.bits().resize(GetSize(sig), State::Sx);
|
||||
if (bvmode && GetSize(sig) > 1) {
|
||||
Const mask(State::S1, GetSize(sig));
|
||||
bool use_mask = false;
|
||||
for (int i = 0; i < GetSize(sig); i++)
|
||||
if (val[i] != State::S0 && val[i] != State::S1) {
|
||||
val[i] = State::S0;
|
||||
mask[i] = State::S0;
|
||||
val.bits()[i] = State::S0;
|
||||
mask.bits()[i] = State::S0;
|
||||
use_mask = true;
|
||||
}
|
||||
if (use_mask)
|
||||
|
@ -1359,10 +1360,10 @@ struct Smt2Worker
|
|||
for (int k = 0; k < GetSize(initword); k++) {
|
||||
if (initword[k] == State::S0 || initword[k] == State::S1) {
|
||||
gen_init_constr = true;
|
||||
initmask[k] = State::S1;
|
||||
initmask.bits()[k] = State::S1;
|
||||
} else {
|
||||
initmask[k] = State::S0;
|
||||
initword[k] = State::S0;
|
||||
initmask.bits()[k] = State::S0;
|
||||
initword.bits()[k] = State::S0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1454,6 +1454,10 @@ def write_trace(steps_start, steps_stop, index, allregs=False):
|
|||
if outywfile is not None:
|
||||
write_yw_trace(steps, index, allregs)
|
||||
|
||||
def escape_path_segment(segment):
|
||||
if "." in segment:
|
||||
return f"\\{segment} "
|
||||
return segment
|
||||
|
||||
def print_failed_asserts_worker(mod, state, path, extrainfo, infomap, infokey=()):
|
||||
assert mod in smt.modinfo
|
||||
|
@ -1464,7 +1468,8 @@ def print_failed_asserts_worker(mod, state, path, extrainfo, infomap, infokey=()
|
|||
|
||||
for cellname, celltype in smt.modinfo[mod].cells.items():
|
||||
cell_infokey = (mod, cellname, infokey)
|
||||
if print_failed_asserts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), path + "." + cellname, extrainfo, infomap, cell_infokey):
|
||||
cell_path = path + "." + escape_path_segment(cellname)
|
||||
if print_failed_asserts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), cell_path, extrainfo, infomap, cell_infokey):
|
||||
found_failed_assert = True
|
||||
|
||||
for assertfun, assertinfo in smt.modinfo[mod].asserts.items():
|
||||
|
@ -1497,7 +1502,7 @@ def print_anyconsts_worker(mod, state, path):
|
|||
assert mod in smt.modinfo
|
||||
|
||||
for cellname, celltype in smt.modinfo[mod].cells.items():
|
||||
print_anyconsts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), path + "." + cellname)
|
||||
print_anyconsts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), path + "." + escape_path_segment(cellname))
|
||||
|
||||
for fun, info in smt.modinfo[mod].anyconsts.items():
|
||||
if info[1] is None:
|
||||
|
@ -1517,18 +1522,21 @@ def print_anyconsts(state):
|
|||
print_anyconsts_worker(topmod, "s%d" % state, topmod)
|
||||
|
||||
|
||||
def get_cover_list(mod, base):
|
||||
def get_cover_list(mod, base, path=None):
|
||||
path = path or mod
|
||||
assert mod in smt.modinfo
|
||||
|
||||
cover_expr = list()
|
||||
# A tuple of path and cell name
|
||||
cover_desc = list()
|
||||
|
||||
for expr, desc in smt.modinfo[mod].covers.items():
|
||||
cover_expr.append("(ite (|%s| %s) #b1 #b0)" % (expr, base))
|
||||
cover_desc.append(desc)
|
||||
cover_desc.append((path, desc))
|
||||
|
||||
for cell, submod in smt.modinfo[mod].cells.items():
|
||||
e, d = get_cover_list(submod, "(|%s_h %s| %s)" % (mod, cell, base))
|
||||
cell_path = path + "." + escape_path_segment(cell)
|
||||
e, d = get_cover_list(submod, "(|%s_h %s| %s)" % (mod, cell, base), cell_path)
|
||||
cover_expr += e
|
||||
cover_desc += d
|
||||
|
||||
|
@ -1544,7 +1552,8 @@ def get_assert_map(mod, base, path, key_base=()):
|
|||
assert_map[(expr, key_base)] = ("(|%s| %s)" % (expr, base), path, desc)
|
||||
|
||||
for cell, submod in smt.modinfo[mod].cells.items():
|
||||
assert_map.update(get_assert_map(submod, "(|%s_h %s| %s)" % (mod, cell, base), path + "." + cell, (mod, cell, key_base)))
|
||||
cell_path = path + "." + escape_path_segment(cell)
|
||||
assert_map.update(get_assert_map(submod, "(|%s_h %s| %s)" % (mod, cell, base), cell_path, (mod, cell, key_base)))
|
||||
|
||||
return assert_map
|
||||
|
||||
|
@ -1903,7 +1912,9 @@ elif covermode:
|
|||
new_cover_mask.append(cover_mask[i])
|
||||
continue
|
||||
|
||||
print_msg("Reached cover statement at %s in step %d." % (cover_desc[i], step))
|
||||
path = cover_desc[i][0]
|
||||
name = cover_desc[i][1]
|
||||
print_msg("Reached cover statement in step %d at %s: %s" % (step, path, name))
|
||||
new_cover_mask.append("0")
|
||||
|
||||
cover_mask = "".join(new_cover_mask)
|
||||
|
@ -1933,7 +1944,7 @@ elif covermode:
|
|||
if "1" in cover_mask:
|
||||
for i in range(len(cover_mask)):
|
||||
if cover_mask[i] == "1":
|
||||
print_msg("Unreached cover statement at %s." % cover_desc[i])
|
||||
print_msg("Unreached cover statement at %s: %s" % (cover_desc[i][0], cover_desc[i][1]))
|
||||
|
||||
else: # not tempind, covermode
|
||||
active_assert_keys = get_assert_keys()
|
||||
|
|
|
@ -21,7 +21,7 @@ EOT
|
|||
for x in $(set +x; ls test_*.il | sort -R); do
|
||||
x=${x%.il}
|
||||
cat > $x.ys <<- EOT
|
||||
read_ilang $x.il
|
||||
read_rtlil $x.il
|
||||
copy gold gate
|
||||
|
||||
cd gate
|
||||
|
|
|
@ -17,11 +17,11 @@ EOT
|
|||
|
||||
for fn in test_*.il; do
|
||||
../../../yosys -p "
|
||||
read_ilang $fn
|
||||
read_rtlil $fn
|
||||
rename gold gate
|
||||
synth
|
||||
|
||||
read_ilang $fn
|
||||
read_rtlil $fn
|
||||
miter -equiv -flatten gold gate main
|
||||
hierarchy -top main
|
||||
write_smv -tpl template.txt ${fn#.il}.smv
|
||||
|
|
|
@ -191,7 +191,7 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
|||
{
|
||||
bool set_signed = (data.flags & RTLIL::CONST_FLAG_SIGNED) != 0;
|
||||
if (width < 0)
|
||||
width = data.bits.size() - offset;
|
||||
width = data.size() - offset;
|
||||
if (width == 0) {
|
||||
// See IEEE 1364-2005 Clause 5.1.14.
|
||||
f << "{0{1'b0}}";
|
||||
|
@ -199,14 +199,14 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
|||
}
|
||||
if (nostr)
|
||||
goto dump_hex;
|
||||
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
|
||||
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.size()) {
|
||||
if (width == 32 && !no_decimal && !nodec) {
|
||||
int32_t val = 0;
|
||||
for (int i = offset+width-1; i >= offset; i--) {
|
||||
log_assert(i < (int)data.bits.size());
|
||||
if (data.bits[i] != State::S0 && data.bits[i] != State::S1)
|
||||
log_assert(i < (int)data.size());
|
||||
if (data[i] != State::S0 && data[i] != State::S1)
|
||||
goto dump_hex;
|
||||
if (data.bits[i] == State::S1)
|
||||
if (data[i] == State::S1)
|
||||
val |= 1 << (i - offset);
|
||||
}
|
||||
if (decimal)
|
||||
|
@ -221,8 +221,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
|||
goto dump_bin;
|
||||
vector<char> bin_digits, hex_digits;
|
||||
for (int i = offset; i < offset+width; i++) {
|
||||
log_assert(i < (int)data.bits.size());
|
||||
switch (data.bits[i]) {
|
||||
log_assert(i < (int)data.size());
|
||||
switch (data[i]) {
|
||||
case State::S0: bin_digits.push_back('0'); break;
|
||||
case State::S1: bin_digits.push_back('1'); break;
|
||||
case RTLIL::Sx: bin_digits.push_back('x'); break;
|
||||
|
@ -275,8 +275,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
|||
if (width == 0)
|
||||
f << stringf("0");
|
||||
for (int i = offset+width-1; i >= offset; i--) {
|
||||
log_assert(i < (int)data.bits.size());
|
||||
switch (data.bits[i]) {
|
||||
log_assert(i < (int)data.size());
|
||||
switch (data[i]) {
|
||||
case State::S0: f << stringf("0"); break;
|
||||
case State::S1: f << stringf("1"); break;
|
||||
case RTLIL::Sx: f << stringf("x"); break;
|
||||
|
@ -318,10 +318,10 @@ void dump_reg_init(std::ostream &f, SigSpec sig)
|
|||
|
||||
for (auto bit : active_sigmap(sig)) {
|
||||
if (active_initdata.count(bit)) {
|
||||
initval.bits.push_back(active_initdata.at(bit));
|
||||
initval.bits().push_back(active_initdata.at(bit));
|
||||
gotinit = true;
|
||||
} else {
|
||||
initval.bits.push_back(State::Sx);
|
||||
initval.bits().push_back(State::Sx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -751,7 +751,7 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
|
|||
if (port.wide_log2) {
|
||||
Const addr_lo;
|
||||
for (int i = 0; i < port.wide_log2; i++)
|
||||
addr_lo.bits.push_back(State(sub >> i & 1));
|
||||
addr_lo.bits().push_back(State(sub >> i & 1));
|
||||
os << "{";
|
||||
os << temp_id;
|
||||
os << ", ";
|
||||
|
|
|
@ -238,7 +238,7 @@ Makefile-%: FORCE
|
|||
$(MAKE) -C $(@D) $(*F)
|
||||
|
||||
CODE_EXAMPLES := $(wildcard source/code_examples/*/Makefile)
|
||||
TEST_EXAMPLES := $(addsuffix -all,$(CODE_EXAMPLES))
|
||||
TEST_EXAMPLES := $(addsuffix -examples,$(CODE_EXAMPLES))
|
||||
CLEAN_EXAMPLES := $(addsuffix -clean,$(CODE_EXAMPLES))
|
||||
test-examples: $(TEST_EXAMPLES)
|
||||
clean-examples: $(CLEAN_EXAMPLES)
|
||||
|
@ -252,6 +252,11 @@ images:
|
|||
$(MAKE) -C source/_images
|
||||
$(MAKE) -C source/_images convert
|
||||
|
||||
.PHONY: gen
|
||||
gen:
|
||||
$(MAKE) examples
|
||||
$(MAKE) images
|
||||
|
||||
.PHONY: reqs
|
||||
reqs:
|
||||
$(PYTHON) -m pip install -r source/requirements.txt
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
all: examples all_tex tidy
|
||||
all: examples all_tex
|
||||
|
||||
# set a fake time in pdf generation to prevent unnecessary differences in output
|
||||
FAKETIME := TZ='Z' faketime -f '2022-01-01 00:00:00 x0,001'
|
||||
|
|
|
@ -15,23 +15,23 @@
|
|||
\tikzstyle{data} = [draw, fill=blue!10, ellipse, minimum height=3em, minimum width=7em, node distance=15em]
|
||||
\node[process] (vlog) {Verilog Frontend};
|
||||
\node[process, dashed, fill=green!5] (vhdl) [right of=vlog] {VHDL Frontend};
|
||||
\node[process] (ilang) [right of=vhdl] {RTLIL Frontend};
|
||||
\node[process] (rtlilfe) [right of=vhdl] {RTLIL Frontend};
|
||||
\node[data] (ast) [below of=vlog, node distance=5em, xshift=7.5em] {AST};
|
||||
\node[process] (astfe) [below of=ast, node distance=5em] {AST Frontend};
|
||||
\node[data] (rtlil) [below of=astfe, node distance=5em, xshift=7.5em] {RTLIL};
|
||||
\node[process] (pass) [right of=rtlil, node distance=5em, xshift=7.5em] {Passes};
|
||||
\node[process] (vlbe) [below of=rtlil, node distance=7em, xshift=-13em] {Verilog Backend};
|
||||
\node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {RTLIL Backend};
|
||||
\node[process] (rtlilbe) [below of=rtlil, node distance=7em, xshift=0em] {RTLIL Backend};
|
||||
\node[process, dashed, fill=green!5] (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] {Other Backends};
|
||||
|
||||
\draw[-latex] (vlog) -- (ast);
|
||||
\draw[-latex] (vhdl) -- (ast);
|
||||
\draw[-latex] (ast) -- (astfe);
|
||||
\draw[-latex] (astfe) -- (rtlil);
|
||||
\draw[-latex] (ilang) -- (rtlil);
|
||||
\draw[-latex] (rtlilfe) -- (rtlil);
|
||||
\draw[latex-latex] (rtlil) -- (pass);
|
||||
\draw[-latex] (rtlil) -- (vlbe);
|
||||
\draw[-latex] (rtlil) -- (ilangbe);
|
||||
\draw[-latex] (rtlil) -- (rtlilbe);
|
||||
\draw[-latex] (rtlil) -- (otherbe);
|
||||
\end{tikzpicture}
|
||||
\end{document}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
|
@ -1,40 +0,0 @@
|
|||
/* Don't hide the right sidebar as we're placing our fixed links there */
|
||||
aside.no-toc {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Colorful headings */
|
||||
h1 {
|
||||
color: var(--color-brand-primary);
|
||||
}
|
||||
|
||||
h2, h3, h4, h5, h6 {
|
||||
color: var(--color-brand-content);
|
||||
}
|
||||
|
||||
/* Use a different color for external links */
|
||||
a.external {
|
||||
color: var(--color-brand-primary) !important;
|
||||
}
|
||||
|
||||
.wy-table-responsive table td {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
body[data-theme="dark"] {
|
||||
.invert-helper {
|
||||
filter: url("data:image/svg+xml,<svg xmlns='http%3A//www.w3.org/2000/svg'><filter id='f'><feColorMatrix color-interpolation-filters='sRGB' type='matrix' values='1.47 -1.73 -0.467 0 0.867 -0.733 0.467 -0.467 0 0.867 -0.667 -1.07 1.07 0 0.867 0 0 0 1.0 0'></feColorMatrix></filter></svg>#f");
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body:not([data-theme="light"]) {
|
||||
.invert-helper {
|
||||
filter: url("data:image/svg+xml,<svg xmlns='http%3A//www.w3.org/2000/svg'><filter id='f'><feColorMatrix color-interpolation-filters='sRGB' type='matrix' values='1.47 -1.73 -0.467 0 0.867 -0.733 0.467 -0.467 0 0.867 -0.667 -1.07 1.07 0 0.867 0 0 0 1.0 0'></feColorMatrix></filter></svg>#f");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
{#
|
||||
|
||||
See https://github.com/pradyunsg/furo/blob/main/src/furo/theme/furo/page.html for the original
|
||||
block this is overwriting.
|
||||
|
||||
The part that is customized is between the "begin of custom part" and "end of custom part"
|
||||
comments below. It uses the same styles as the existing right sidebar code.
|
||||
|
||||
#}
|
||||
{% extends "furo/page.html" %}
|
||||
{% block right_sidebar %}
|
||||
<div class="toc-sticky toc-scroll">
|
||||
{# begin of custom part #}
|
||||
<div class="toc-title-container">
|
||||
<span class="toc-title">
|
||||
YosysHQ
|
||||
</span>
|
||||
</div>
|
||||
<div class="toc-tree-container yosyshq-links" style="padding-bottom: 0">
|
||||
<div class="toc-tree">
|
||||
<ul>
|
||||
<li></li>
|
||||
<li><a class="reference external" href="https://yosyshq.readthedocs.io">Docs</a></li>
|
||||
<li><a class="reference external" href="https://blog.yosyshq.com">Blog</a></li>
|
||||
<li><a class="reference external" href="https://www.yosyshq.com">Website</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{# end of custom part #}
|
||||
{% if not furo_hide_toc %}
|
||||
<div class="toc-title-container">
|
||||
<span class="toc-title">
|
||||
{{ _("On this page") }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="toc-tree-container">
|
||||
<div class="toc-tree">
|
||||
{{ toc }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
Appendix
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:includehidden:
|
||||
|
||||
appendix/primer
|
||||
appendix/auxlibs
|
||||
appendix/auxprogs
|
||||
|
||||
bib
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:includehidden:
|
||||
|
||||
cmd_ref
|
|
@ -29,7 +29,7 @@ ezSAT
|
|||
|
||||
The files in ``libs/ezsat`` provide a library for simplifying generating CNF
|
||||
formulas for SAT solvers. It also contains bindings of MiniSAT. The ezSAT
|
||||
library is written by C. Wolf. It is used by the :cmd:ref:`sat` pass (see
|
||||
library is written by C. Wolf. It is used by the `sat` pass (see
|
||||
:doc:`/cmd/sat`).
|
||||
|
||||
fst
|
||||
|
@ -37,22 +37,22 @@ fst
|
|||
|
||||
``libfst`` files from `gtkwave`_ are included in ``libs/fst`` to support
|
||||
reading/writing signal traces from/to the GTKWave developed FST format. This is
|
||||
primarily used in the :cmd:ref:`sim` command.
|
||||
primarily used in the `sim` command.
|
||||
|
||||
.. _gtkwave: https://github.com/gtkwave/gtkwave
|
||||
|
||||
json11
|
||||
------
|
||||
|
||||
For reading/writing designs from/to JSON, :cmd:ref:`read_json` and
|
||||
:cmd:ref:`write_json` should be used. For everything else there is the `json11
|
||||
For reading/writing designs from/to JSON, `read_json` and
|
||||
`write_json` should be used. For everything else there is the `json11
|
||||
library`_:
|
||||
|
||||
json11 is a tiny JSON library for C++11, providing JSON parsing and
|
||||
serialization.
|
||||
|
||||
This library is used for outputting machine-readable statistics (:cmd:ref:`stat`
|
||||
with ``-json`` flag), using the RPC frontend (:cmd:ref:`connect_rpc`), and the
|
||||
This library is used for outputting machine-readable statistics (`stat`
|
||||
with ``-json`` flag), using the RPC frontend (`connect_rpc`), and the
|
||||
yosys-witness ``yw`` format.
|
||||
|
||||
.. _json11 library: https://github.com/dropbox/json11
|
||||
|
@ -61,7 +61,7 @@ MiniSAT
|
|||
-------
|
||||
|
||||
The files in ``libs/minisat`` provide a high-performance SAT solver, used by the
|
||||
:cmd:ref:`sat` command.
|
||||
`sat` command.
|
||||
|
||||
SHA1
|
||||
----
|
||||
|
|
|
@ -3,7 +3,7 @@ Yosys environment variables
|
|||
|
||||
``HOME``
|
||||
Yosys command history is stored in :file:`$HOME/.yosys_history`. Graphics
|
||||
(from :cmd:ref:`show` and :cmd:ref:`viz` commands) will output to this
|
||||
(from `show` and `viz` commands) will output to this
|
||||
directory by default. This environment variable is also used in some cases
|
||||
for resolving filenames with :file:`~`.
|
||||
|
||||
|
|
|
@ -223,8 +223,8 @@ Cells
|
|||
Declares a cell, with zero or more attributes, with the given identifier and
|
||||
type in the enclosing module.
|
||||
|
||||
Cells perform functions on input signals. See
|
||||
:doc:`/yosys_internals/formats/cell_library` for a detailed list of cell types.
|
||||
Cells perform functions on input signals. See :doc:`/cell_index` for a detailed
|
||||
list of cell types.
|
||||
|
||||
.. code:: BNF
|
||||
|
53
docs/source/cell/gate_comb_combined.rst
Normal file
53
docs/source/cell/gate_comb_combined.rst
Normal file
|
@ -0,0 +1,53 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Combinatorial cells (combined)
|
||||
------------------------------
|
||||
|
||||
These cells combine two or more combinatorial cells (simple) into a single cell.
|
||||
|
||||
.. table:: Cell types for gate level combinatorial cells (combined)
|
||||
|
||||
======================================= =============
|
||||
Verilog Cell Type
|
||||
======================================= =============
|
||||
:verilog:`Y = A & ~B` `$_ANDNOT_`
|
||||
:verilog:`Y = A | ~B` `$_ORNOT_`
|
||||
:verilog:`Y = ~((A & B) | C)` `$_AOI3_`
|
||||
:verilog:`Y = ~((A | B) & C)` `$_OAI3_`
|
||||
:verilog:`Y = ~((A & B) | (C & D))` `$_AOI4_`
|
||||
:verilog:`Y = ~((A | B) & (C | D))` `$_OAI4_`
|
||||
:verilog:`Y = ~(S ? B : A)` `$_NMUX_`
|
||||
(see below) `$_MUX4_`
|
||||
(see below) `$_MUX8_`
|
||||
(see below) `$_MUX16_`
|
||||
======================================= =============
|
||||
|
||||
The `$_MUX4_`, `$_MUX8_` and `$_MUX16_` cells are used to model wide muxes, and
|
||||
correspond to the following Verilog code:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
// $_MUX4_
|
||||
assign Y = T ? (S ? D : C) :
|
||||
(S ? B : A);
|
||||
// $_MUX8_
|
||||
assign Y = U ? T ? (S ? H : G) :
|
||||
(S ? F : E) :
|
||||
T ? (S ? D : C) :
|
||||
(S ? B : A);
|
||||
// $_MUX16_
|
||||
assign Y = V ? U ? T ? (S ? P : O) :
|
||||
(S ? N : M) :
|
||||
T ? (S ? L : K) :
|
||||
(S ? J : I) :
|
||||
U ? T ? (S ? H : G) :
|
||||
(S ? F : E) :
|
||||
T ? (S ? D : C) :
|
||||
(S ? B : A);
|
||||
|
||||
.. autocellgroup:: comb_combined
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
26
docs/source/cell/gate_comb_simple.rst
Normal file
26
docs/source/cell/gate_comb_simple.rst
Normal file
|
@ -0,0 +1,26 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Combinatorial cells (simple)
|
||||
----------------------------
|
||||
|
||||
.. table:: Cell types for gate level combinatorial cells (simple)
|
||||
|
||||
======================================= =============
|
||||
Verilog Cell Type
|
||||
======================================= =============
|
||||
:verilog:`Y = A` `$_BUF_`
|
||||
:verilog:`Y = ~A` `$_NOT_`
|
||||
:verilog:`Y = A & B` `$_AND_`
|
||||
:verilog:`Y = ~(A & B)` `$_NAND_`
|
||||
:verilog:`Y = A | B` `$_OR_`
|
||||
:verilog:`Y = ~(A | B)` `$_NOR_`
|
||||
:verilog:`Y = A ^ B` `$_XOR_`
|
||||
:verilog:`Y = ~(A ^ B)` `$_XNOR_`
|
||||
:verilog:`Y = S ? B : A` `$_MUX_`
|
||||
======================================= =============
|
||||
|
||||
.. autocellgroup:: comb_simple
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
8
docs/source/cell/gate_other.rst
Normal file
8
docs/source/cell/gate_other.rst
Normal file
|
@ -0,0 +1,8 @@
|
|||
Other gate-level cells
|
||||
----------------------
|
||||
|
||||
.. autocellgroup:: gate_other
|
||||
:caption: Other gate-level cells
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
231
docs/source/cell/gate_reg_ff.rst
Normal file
231
docs/source/cell/gate_reg_ff.rst
Normal file
|
@ -0,0 +1,231 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Flip-flop cells
|
||||
---------------
|
||||
|
||||
The cell types `$_DFF_N_` and `$_DFF_P_` represent d-type flip-flops.
|
||||
|
||||
.. table:: Cell types for basic flip-flops
|
||||
|
||||
======================================= =============
|
||||
Verilog Cell Type
|
||||
======================================= =============
|
||||
:verilog:`always @(negedge C) Q <= D` `$_DFF_N_`
|
||||
:verilog:`always @(posedge C) Q <= D` `$_DFF_P_`
|
||||
======================================= =============
|
||||
|
||||
The cell types ``$_DFFE_[NP][NP]_`` implement d-type flip-flops with enable. The
|
||||
values in the table for these cell types relate to the following Verilog code
|
||||
template.
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C)
|
||||
if (EN == EN_LVL)
|
||||
Q <= D;
|
||||
|
||||
|
||||
.. table:: Cell types for gate level logic networks (FFs with enable)
|
||||
:name: tab:CellLib_gates_dffe
|
||||
|
||||
================== ============= ============
|
||||
:math:`ClkEdge` :math:`EnLvl` Cell Type
|
||||
================== ============= ============
|
||||
:verilog:`negedge` ``0`` `$_DFFE_NN_`
|
||||
:verilog:`negedge` ``1`` `$_DFFE_NP_`
|
||||
:verilog:`posedge` ``0`` `$_DFFE_PN_`
|
||||
:verilog:`posedge` ``1`` `$_DFFE_PP_`
|
||||
================== ============= ============
|
||||
|
||||
The cell types ``$_DFF_[NP][NP][01]_`` implement d-type flip-flops with
|
||||
asynchronous reset. The values in the table for these cell types relate to the
|
||||
following Verilog code template, where ``RST_EDGE`` is ``posedge`` if
|
||||
``RST_LVL`` if ``1``, and ``negedge`` otherwise.
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C, RST_EDGE R)
|
||||
if (R == RST_LVL)
|
||||
Q <= RST_VAL;
|
||||
else
|
||||
Q <= D;
|
||||
|
||||
The cell types ``$_SDFF_[NP][NP][01]_`` implement d-type flip-flops with
|
||||
synchronous reset. The values in the table for these cell types relate to the
|
||||
following Verilog code template:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C)
|
||||
if (R == RST_LVL)
|
||||
Q <= RST_VAL;
|
||||
else
|
||||
Q <= D;
|
||||
|
||||
.. table:: Cell types for gate level logic networks (FFs with reset)
|
||||
:name: tab:CellLib_gates_adff
|
||||
|
||||
================== ============== ============== ===========================
|
||||
:math:`ClkEdge` :math:`RstLvl` :math:`RstVal` Cell Type
|
||||
================== ============== ============== ===========================
|
||||
:verilog:`negedge` ``0`` ``0`` `$_DFF_NN0_`, `$_SDFF_NN0_`
|
||||
:verilog:`negedge` ``0`` ``1`` `$_DFF_NN1_`, `$_SDFF_NN1_`
|
||||
:verilog:`negedge` ``1`` ``0`` `$_DFF_NP0_`, `$_SDFF_NP0_`
|
||||
:verilog:`negedge` ``1`` ``1`` `$_DFF_NP1_`, `$_SDFF_NP1_`
|
||||
:verilog:`posedge` ``0`` ``0`` `$_DFF_PN0_`, `$_SDFF_PN0_`
|
||||
:verilog:`posedge` ``0`` ``1`` `$_DFF_PN1_`, `$_SDFF_PN1_`
|
||||
:verilog:`posedge` ``1`` ``0`` `$_DFF_PP0_`, `$_SDFF_PP0_`
|
||||
:verilog:`posedge` ``1`` ``1`` `$_DFF_PP1_`, `$_SDFF_PP1_`
|
||||
================== ============== ============== ===========================
|
||||
|
||||
The cell types ``$_DFFE_[NP][NP][01][NP]_`` implement d-type flip-flops with
|
||||
asynchronous reset and enable. The values in the table for these cell types
|
||||
relate to the following Verilog code template, where ``RST_EDGE`` is ``posedge``
|
||||
if ``RST_LVL`` if ``1``, and ``negedge`` otherwise.
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C, RST_EDGE R)
|
||||
if (R == RST_LVL)
|
||||
Q <= RST_VAL;
|
||||
else if (EN == EN_LVL)
|
||||
Q <= D;
|
||||
|
||||
The cell types ``$_SDFFE_[NP][NP][01][NP]_`` implement d-type flip-flops with
|
||||
synchronous reset and enable, with reset having priority over enable. The values
|
||||
in the table for these cell types relate to the following Verilog code template:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C)
|
||||
if (R == RST_LVL)
|
||||
Q <= RST_VAL;
|
||||
else if (EN == EN_LVL)
|
||||
Q <= D;
|
||||
|
||||
The cell types ``$_SDFFCE_[NP][NP][01][NP]_`` implement d-type flip-flops with
|
||||
synchronous reset and enable, with enable having priority over reset. The values
|
||||
in the table for these cell types relate to the following Verilog code template:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C)
|
||||
if (EN == EN_LVL)
|
||||
if (R == RST_LVL)
|
||||
Q <= RST_VAL;
|
||||
else
|
||||
Q <= D;
|
||||
|
||||
|
||||
.. table:: Cell types for gate level logic networks (FFs with reset and enable)
|
||||
:name: tab:CellLib_gates_adffe
|
||||
|
||||
================== ============== ============== ============= =================================================
|
||||
:math:`ClkEdge` :math:`RstLvl` :math:`RstVal` :math:`EnLvl` Cell Type
|
||||
================== ============== ============== ============= =================================================
|
||||
:verilog:`negedge` ``0`` ``0`` ``0`` `$_DFFE_NN0N_`, `$_SDFFE_NN0N_`, `$_SDFFCE_NN0N_`
|
||||
:verilog:`negedge` ``0`` ``0`` ``1`` `$_DFFE_NN0P_`, `$_SDFFE_NN0P_`, `$_SDFFCE_NN0P_`
|
||||
:verilog:`negedge` ``0`` ``1`` ``0`` `$_DFFE_NN1N_`, `$_SDFFE_NN1N_`, `$_SDFFCE_NN1N_`
|
||||
:verilog:`negedge` ``0`` ``1`` ``1`` `$_DFFE_NN1P_`, `$_SDFFE_NN1P_`, `$_SDFFCE_NN1P_`
|
||||
:verilog:`negedge` ``1`` ``0`` ``0`` `$_DFFE_NP0N_`, `$_SDFFE_NP0N_`, `$_SDFFCE_NP0N_`
|
||||
:verilog:`negedge` ``1`` ``0`` ``1`` `$_DFFE_NP0P_`, `$_SDFFE_NP0P_`, `$_SDFFCE_NP0P_`
|
||||
:verilog:`negedge` ``1`` ``1`` ``0`` `$_DFFE_NP1N_`, `$_SDFFE_NP1N_`, `$_SDFFCE_NP1N_`
|
||||
:verilog:`negedge` ``1`` ``1`` ``1`` `$_DFFE_NP1P_`, `$_SDFFE_NP1P_`, `$_SDFFCE_NP1P_`
|
||||
:verilog:`posedge` ``0`` ``0`` ``0`` `$_DFFE_PN0N_`, `$_SDFFE_PN0N_`, `$_SDFFCE_PN0N_`
|
||||
:verilog:`posedge` ``0`` ``0`` ``1`` `$_DFFE_PN0P_`, `$_SDFFE_PN0P_`, `$_SDFFCE_PN0P_`
|
||||
:verilog:`posedge` ``0`` ``1`` ``0`` `$_DFFE_PN1N_`, `$_SDFFE_PN1N_`, `$_SDFFCE_PN1N_`
|
||||
:verilog:`posedge` ``0`` ``1`` ``1`` `$_DFFE_PN1P_`, `$_SDFFE_PN1P_`, `$_SDFFCE_PN1P_`
|
||||
:verilog:`posedge` ``1`` ``0`` ``0`` `$_DFFE_PP0N_`, `$_SDFFE_PP0N_`, `$_SDFFCE_PP0N_`
|
||||
:verilog:`posedge` ``1`` ``0`` ``1`` `$_DFFE_PP0P_`, `$_SDFFE_PP0P_`, `$_SDFFCE_PP0P_`
|
||||
:verilog:`posedge` ``1`` ``1`` ``0`` `$_DFFE_PP1N_`, `$_SDFFE_PP1N_`, `$_SDFFCE_PP1N_`
|
||||
:verilog:`posedge` ``1`` ``1`` ``1`` `$_DFFE_PP1P_`, `$_SDFFE_PP1P_`, `$_SDFFCE_PP1P_`
|
||||
================== ============== ============== ============= =================================================
|
||||
|
||||
The cell types ``$_DFFSR_[NP][NP][NP]_`` implement d-type flip-flops with
|
||||
asynchronous set and reset. The values in the table for these cell types relate
|
||||
to the following Verilog code template, where ``RST_EDGE`` is ``posedge`` if
|
||||
``RST_LVL`` if ``1``, ``negedge`` otherwise, and ``SET_EDGE`` is ``posedge`` if
|
||||
``SET_LVL`` if ``1``, ``negedge`` otherwise.
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C, RST_EDGE R, SET_EDGE S)
|
||||
if (R == RST_LVL)
|
||||
Q <= 0;
|
||||
else if (S == SET_LVL)
|
||||
Q <= 1;
|
||||
else
|
||||
Q <= D;
|
||||
|
||||
.. table:: Cell types for gate level logic networks (FFs with set and reset)
|
||||
:name: tab:CellLib_gates_dffsr
|
||||
|
||||
================== ============== ============== ==============
|
||||
:math:`ClkEdge` :math:`SetLvl` :math:`RstLvl` Cell Type
|
||||
================== ============== ============== ==============
|
||||
:verilog:`negedge` ``0`` ``0`` `$_DFFSR_NNN_`
|
||||
:verilog:`negedge` ``0`` ``1`` `$_DFFSR_NNP_`
|
||||
:verilog:`negedge` ``1`` ``0`` `$_DFFSR_NPN_`
|
||||
:verilog:`negedge` ``1`` ``1`` `$_DFFSR_NPP_`
|
||||
:verilog:`posedge` ``0`` ``0`` `$_DFFSR_PNN_`
|
||||
:verilog:`posedge` ``0`` ``1`` `$_DFFSR_PNP_`
|
||||
:verilog:`posedge` ``1`` ``0`` `$_DFFSR_PPN_`
|
||||
:verilog:`posedge` ``1`` ``1`` `$_DFFSR_PPP_`
|
||||
================== ============== ============== ==============
|
||||
|
||||
The cell types ``$_DFFSRE_[NP][NP][NP][NP]_`` implement d-type flip-flops with
|
||||
asynchronous set and reset and enable. The values in the table for these cell
|
||||
types relate to the following Verilog code template, where ``RST_EDGE`` is
|
||||
``posedge`` if ``RST_LVL`` if ``1``, ``negedge`` otherwise, and ``SET_EDGE`` is
|
||||
``posedge`` if ``SET_LVL`` if ``1``, ``negedge`` otherwise.
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @(CLK_EDGE C, RST_EDGE R, SET_EDGE S)
|
||||
if (R == RST_LVL)
|
||||
Q <= 0;
|
||||
else if (S == SET_LVL)
|
||||
Q <= 1;
|
||||
else if (E == EN_LVL)
|
||||
Q <= D;
|
||||
|
||||
|
||||
.. table:: Cell types for gate level logic networks (FFs with set and reset and enable)
|
||||
:name: tab:CellLib_gates_dffsre
|
||||
|
||||
================== ============== ============== ============= ================
|
||||
:math:`ClkEdge` :math:`SetLvl` :math:`RstLvl` :math:`EnLvl` Cell Type
|
||||
================== ============== ============== ============= ================
|
||||
:verilog:`negedge` ``0`` ``0`` ``0`` `$_DFFSRE_NNNN_`
|
||||
:verilog:`negedge` ``0`` ``0`` ``1`` `$_DFFSRE_NNNP_`
|
||||
:verilog:`negedge` ``0`` ``1`` ``0`` `$_DFFSRE_NNPN_`
|
||||
:verilog:`negedge` ``0`` ``1`` ``1`` `$_DFFSRE_NNPP_`
|
||||
:verilog:`negedge` ``1`` ``0`` ``0`` `$_DFFSRE_NPNN_`
|
||||
:verilog:`negedge` ``1`` ``0`` ``1`` `$_DFFSRE_NPNP_`
|
||||
:verilog:`negedge` ``1`` ``1`` ``0`` `$_DFFSRE_NPPN_`
|
||||
:verilog:`negedge` ``1`` ``1`` ``1`` `$_DFFSRE_NPPP_`
|
||||
:verilog:`posedge` ``0`` ``0`` ``0`` `$_DFFSRE_PNNN_`
|
||||
:verilog:`posedge` ``0`` ``0`` ``1`` `$_DFFSRE_PNNP_`
|
||||
:verilog:`posedge` ``0`` ``1`` ``0`` `$_DFFSRE_PNPN_`
|
||||
:verilog:`posedge` ``0`` ``1`` ``1`` `$_DFFSRE_PNPP_`
|
||||
:verilog:`posedge` ``1`` ``0`` ``0`` `$_DFFSRE_PPNN_`
|
||||
:verilog:`posedge` ``1`` ``0`` ``1`` `$_DFFSRE_PPNP_`
|
||||
:verilog:`posedge` ``1`` ``1`` ``0`` `$_DFFSRE_PPPN_`
|
||||
:verilog:`posedge` ``1`` ``1`` ``1`` `$_DFFSRE_PPPP_`
|
||||
================== ============== ============== ============= ================
|
||||
|
||||
.. todo:: flip-flops with async load, ``$_ALDFFE?_[NP]{2,3}_``
|
||||
|
||||
.. autocellgroup:: reg_ff
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
105
docs/source/cell/gate_reg_latch.rst
Normal file
105
docs/source/cell/gate_reg_latch.rst
Normal file
|
@ -0,0 +1,105 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Latch cells
|
||||
-----------
|
||||
|
||||
The cell types `$_DLATCH_N_` and `$_DLATCH_P_` represent d-type latches.
|
||||
|
||||
.. table:: Cell types for basic latches
|
||||
|
||||
======================================= =============
|
||||
Verilog Cell Type
|
||||
======================================= =============
|
||||
:verilog:`always @* if (!E) Q <= D` `$_DLATCH_N_`
|
||||
:verilog:`always @* if (E) Q <= D` `$_DLATCH_P_`
|
||||
======================================= =============
|
||||
|
||||
The cell types ``$_DLATCH_[NP][NP][01]_`` implement d-type latches with reset.
|
||||
The values in the table for these cell types relate to the following Verilog
|
||||
code template:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @*
|
||||
if (R == RST_LVL)
|
||||
Q <= RST_VAL;
|
||||
else if (E == EN_LVL)
|
||||
Q <= D;
|
||||
|
||||
.. table:: Cell types for gate level logic networks (latches with reset)
|
||||
:name: tab:CellLib_gates_adlatch
|
||||
|
||||
============= ============== ============== ===============
|
||||
:math:`EnLvl` :math:`RstLvl` :math:`RstVal` Cell Type
|
||||
============= ============== ============== ===============
|
||||
``0`` ``0`` ``0`` `$_DLATCH_NN0_`
|
||||
``0`` ``0`` ``1`` `$_DLATCH_NN1_`
|
||||
``0`` ``1`` ``0`` `$_DLATCH_NP0_`
|
||||
``0`` ``1`` ``1`` `$_DLATCH_NP1_`
|
||||
``1`` ``0`` ``0`` `$_DLATCH_PN0_`
|
||||
``1`` ``0`` ``1`` `$_DLATCH_PN1_`
|
||||
``1`` ``1`` ``0`` `$_DLATCH_PP0_`
|
||||
``1`` ``1`` ``1`` `$_DLATCH_PP1_`
|
||||
============= ============== ============== ===============
|
||||
|
||||
The cell types ``$_DLATCHSR_[NP][NP][NP]_`` implement d-type latches with set
|
||||
and reset. The values in the table for these cell types relate to the following
|
||||
Verilog code template:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @*
|
||||
if (R == RST_LVL)
|
||||
Q <= 0;
|
||||
else if (S == SET_LVL)
|
||||
Q <= 1;
|
||||
else if (E == EN_LVL)
|
||||
Q <= D;
|
||||
|
||||
.. table:: Cell types for gate level logic networks (latches with set and reset)
|
||||
:name: tab:CellLib_gates_dlatchsr
|
||||
|
||||
============= ============== ============== =================
|
||||
:math:`EnLvl` :math:`SetLvl` :math:`RstLvl` Cell Type
|
||||
============= ============== ============== =================
|
||||
``0`` ``0`` ``0`` `$_DLATCHSR_NNN_`
|
||||
``0`` ``0`` ``1`` `$_DLATCHSR_NNP_`
|
||||
``0`` ``1`` ``0`` `$_DLATCHSR_NPN_`
|
||||
``0`` ``1`` ``1`` `$_DLATCHSR_NPP_`
|
||||
``1`` ``0`` ``0`` `$_DLATCHSR_PNN_`
|
||||
``1`` ``0`` ``1`` `$_DLATCHSR_PNP_`
|
||||
``1`` ``1`` ``0`` `$_DLATCHSR_PPN_`
|
||||
``1`` ``1`` ``1`` `$_DLATCHSR_PPP_`
|
||||
============= ============== ============== =================
|
||||
|
||||
The cell types ``$_SR_[NP][NP]_`` implement sr-type latches. The values in the
|
||||
table for these cell types relate to the following Verilog code template:
|
||||
|
||||
.. code-block:: verilog
|
||||
:force:
|
||||
|
||||
always @*
|
||||
if (R == RST_LVL)
|
||||
Q <= 0;
|
||||
else if (S == SET_LVL)
|
||||
Q <= 1;
|
||||
|
||||
.. table:: Cell types for gate level logic networks (SR latches)
|
||||
:name: tab:CellLib_gates_sr
|
||||
|
||||
============== ============== ==========
|
||||
:math:`SetLvl` :math:`RstLvl` Cell Type
|
||||
============== ============== ==========
|
||||
``0`` ``0`` `$_SR_NN_`
|
||||
``0`` ``1`` `$_SR_NP_`
|
||||
``1`` ``0`` `$_SR_PN_`
|
||||
``1`` ``1`` `$_SR_PP_`
|
||||
============== ============== ==========
|
||||
|
||||
.. autocellgroup:: reg_latch
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
25
docs/source/cell/index_gate.rst
Normal file
25
docs/source/cell/index_gate.rst
Normal file
|
@ -0,0 +1,25 @@
|
|||
.. _sec:celllib_gates:
|
||||
|
||||
Gate-level cells
|
||||
----------------
|
||||
|
||||
For gate level logic networks, fixed function single bit cells are used that do
|
||||
not provide any parameters.
|
||||
|
||||
Simulation models for these cells can be found in the file
|
||||
:file:`techlibs/common/simcells.v` in the Yosys source tree.
|
||||
|
||||
In most cases gate level logic networks are created from RTL networks using the
|
||||
techmap pass. The flip-flop cells from the gate level logic network can be
|
||||
mapped to physical flip-flop cells from a Liberty file using the dfflibmap pass.
|
||||
The combinatorial logic cells can be mapped to physical cells from a Liberty
|
||||
file via ABC using the abc pass.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/cell/gate_comb_simple
|
||||
/cell/gate_comb_combined
|
||||
/cell/gate_reg_ff
|
||||
/cell/gate_reg_latch
|
||||
/cell/gate_other
|
30
docs/source/cell/index_word.rst
Normal file
30
docs/source/cell/index_word.rst
Normal file
|
@ -0,0 +1,30 @@
|
|||
Word-level cells
|
||||
----------------
|
||||
|
||||
Most of the RTL cells closely resemble the operators available in HDLs such as
|
||||
Verilog or VHDL. Therefore Verilog operators are used in the following sections
|
||||
to define the behaviour of the RTL cells.
|
||||
|
||||
Note that all RTL cells have parameters indicating the size of inputs and
|
||||
outputs. When passes modify RTL cells they must always keep the values of these
|
||||
parameters in sync with the size of the signals connected to the inputs and
|
||||
outputs.
|
||||
|
||||
Simulation models for the RTL cells can be found in the file
|
||||
:file:`techlibs/common/simlib.v` in the Yosys source tree.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/cell/word_unary
|
||||
/cell/word_binary
|
||||
/cell/word_mux
|
||||
/cell/word_reg
|
||||
/cell/word_mem
|
||||
/cell/word_fsm
|
||||
/cell/word_arith
|
||||
/cell/word_logic
|
||||
/cell/word_spec
|
||||
/cell/word_formal
|
||||
/cell/word_debug
|
||||
/cell/word_wire
|
21
docs/source/cell/properties.rst
Normal file
21
docs/source/cell/properties.rst
Normal file
|
@ -0,0 +1,21 @@
|
|||
Cell properties
|
||||
---------------
|
||||
|
||||
.. cell:defprop:: is_evaluable
|
||||
|
||||
These cells are able to be used in conjunction with the `eval` command. Some
|
||||
passes, such as `opt_expr`, may also be able to perform additional
|
||||
optimizations on cells which are evaluable.
|
||||
|
||||
.. cell:defprop:: x-aware
|
||||
|
||||
Some passes will treat these cells as the non 'x' aware cell. For example,
|
||||
during synthesis `$eqx` will typically be treated as `$eq`.
|
||||
|
||||
.. cell:defprop:: x-output
|
||||
|
||||
These cells can produce 'x' output even if all inputs are defined. For
|
||||
example, a `$div` cell with divisor (``B``) equal to zero has undefined
|
||||
output.
|
||||
|
||||
Refer to the :ref:`propindex` for the list of cells with a given property.
|
50
docs/source/cell/word_arith.rst
Normal file
50
docs/source/cell/word_arith.rst
Normal file
|
@ -0,0 +1,50 @@
|
|||
Coarse arithmetics
|
||||
------------------
|
||||
|
||||
.. todo:: Add information about `$alu`, `$fa`, and `$lcu` cells.
|
||||
|
||||
The `$macc` cell type represents a generalized multiply and accumulate
|
||||
operation. The cell is purely combinational. It outputs the result of summing up
|
||||
a sequence of products and other injected summands.
|
||||
|
||||
.. code-block::
|
||||
|
||||
Y = 0 +- a0factor1 * a0factor2 +- a1factor1 * a1factor2 +- ...
|
||||
+ B[0] + B[1] + ...
|
||||
|
||||
The A port consists of concatenated pairs of multiplier inputs ("factors"). A
|
||||
zero length factor2 acts as a constant 1, turning factor1 into a simple summand.
|
||||
|
||||
In this pseudocode, ``u(foo)`` means an unsigned int that's foo bits long.
|
||||
|
||||
.. code-block::
|
||||
|
||||
struct A {
|
||||
u(CONFIG.mul_info[0].factor1_len) a0factor1;
|
||||
u(CONFIG.mul_info[0].factor2_len) a0factor2;
|
||||
u(CONFIG.mul_info[1].factor1_len) a1factor1;
|
||||
u(CONFIG.mul_info[1].factor2_len) a1factor2;
|
||||
...
|
||||
};
|
||||
|
||||
The cell's ``CONFIG`` parameter determines the layout of cell port ``A``. The
|
||||
CONFIG parameter carries the following information:
|
||||
|
||||
.. code-block::
|
||||
|
||||
struct CONFIG {
|
||||
u4 num_bits;
|
||||
struct mul_info {
|
||||
bool is_signed;
|
||||
bool is_subtract;
|
||||
u(num_bits) factor1_len;
|
||||
u(num_bits) factor2_len;
|
||||
}[num_ports];
|
||||
};
|
||||
|
||||
B is an array of concatenated 1-bit-wide unsigned integers to also be summed up.
|
||||
|
||||
.. autocellgroup:: arith
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
91
docs/source/cell/word_binary.rst
Normal file
91
docs/source/cell/word_binary.rst
Normal file
|
@ -0,0 +1,91 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Binary operators
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
All binary RTL cells have two input ports ``A`` and ``B`` and one output port
|
||||
``Y``. They also have the following parameters:
|
||||
|
||||
``A_SIGNED``
|
||||
Set to a non-zero value if the input ``A`` is signed and therefore should be
|
||||
sign-extended when needed.
|
||||
|
||||
``A_WIDTH``
|
||||
The width of the input port ``A``.
|
||||
|
||||
``B_SIGNED``
|
||||
Set to a non-zero value if the input ``B`` is signed and therefore should be
|
||||
sign-extended when needed.
|
||||
|
||||
``B_WIDTH``
|
||||
The width of the input port ``B``.
|
||||
|
||||
``Y_WIDTH``
|
||||
The width of the output port ``Y``.
|
||||
|
||||
.. table:: Cell types for binary operators with their corresponding Verilog expressions.
|
||||
|
||||
======================= =============== ======================= ===========
|
||||
Verilog Cell Type Verilog Cell Type
|
||||
======================= =============== ======================= ===========
|
||||
:verilog:`Y = A & B` `$and` :verilog:`Y = A ** B` `$pow`
|
||||
:verilog:`Y = A | B` `$or` :verilog:`Y = A < B` `$lt`
|
||||
:verilog:`Y = A ^ B` `$xor` :verilog:`Y = A <= B` `$le`
|
||||
:verilog:`Y = A ~^ B` `$xnor` :verilog:`Y = A == B` `$eq`
|
||||
:verilog:`Y = A << B` `$shl` :verilog:`Y = A != B` `$ne`
|
||||
:verilog:`Y = A >> B` `$shr` :verilog:`Y = A >= B` `$ge`
|
||||
:verilog:`Y = A <<< B` `$sshl` :verilog:`Y = A > B` `$gt`
|
||||
:verilog:`Y = A >>> B` `$sshr` :verilog:`Y = A + B` `$add`
|
||||
:verilog:`Y = A && B` `$logic_and` :verilog:`Y = A - B` `$sub`
|
||||
:verilog:`Y = A || B` `$logic_or` :verilog:`Y = A * B` `$mul`
|
||||
:verilog:`Y = A === B` `$eqx` :verilog:`Y = A / B` `$div`
|
||||
:verilog:`Y = A !== B` `$nex` :verilog:`Y = A % B` `$mod`
|
||||
``N/A`` `$shift` ``N/A`` `$divfloor`
|
||||
``N/A`` `$shiftx` ``N/A`` `$modfloor`
|
||||
======================= =============== ======================= ===========
|
||||
|
||||
The `$shl` and `$shr` cells implement logical shifts, whereas the `$sshl` and
|
||||
`$sshr` cells implement arithmetic shifts. The `$shl` and `$sshl` cells
|
||||
implement the same operation. All four of these cells interpret the second
|
||||
operand as unsigned, and require ``B_SIGNED`` to be zero.
|
||||
|
||||
Two additional shift operator cells are available that do not directly
|
||||
correspond to any operator in Verilog, `$shift` and `$shiftx`. The `$shift` cell
|
||||
performs a right logical shift if the second operand is positive (or unsigned),
|
||||
and a left logical shift if it is negative. The `$shiftx` cell performs the same
|
||||
operation as the `$shift` cell, but the vacated bit positions are filled with
|
||||
undef (x) bits, and corresponds to the Verilog indexed part-select expression.
|
||||
|
||||
For the binary cells that output a logical value (`$logic_and`, `$logic_or`,
|
||||
`$eqx`, `$nex`, `$lt`, `$le`, `$eq`, `$ne`, `$ge`, `$gt`), when the ``Y_WIDTH``
|
||||
parameter is greater than 1, the output is zero-extended, and only the least
|
||||
significant bit varies.
|
||||
|
||||
Division and modulo cells are available in two rounding modes. The original
|
||||
`$div` and `$mod` cells are based on truncating division, and correspond to the
|
||||
semantics of the verilog ``/`` and ``%`` operators. The `$divfloor` and
|
||||
`$modfloor` cells represent flooring division and flooring modulo, the latter of
|
||||
which corresponds to the ``%`` operator in Python. See the following table for a
|
||||
side-by-side comparison between the different semantics.
|
||||
|
||||
.. table:: Comparison between different rounding modes for division and modulo cells.
|
||||
|
||||
+-----------+--------+-----------+-----------+-----------+-----------+
|
||||
| Division | Result | Truncating | Flooring |
|
||||
+-----------+--------+-----------+-----------+-----------+-----------+
|
||||
| | | $div | $mod | $divfloor | $modfloor |
|
||||
+===========+========+===========+===========+===========+===========+
|
||||
| -10 / 3 | -3.3 | -3 | -1 | -4 | 2 |
|
||||
+-----------+--------+-----------+-----------+-----------+-----------+
|
||||
| 10 / -3 | -3.3 | -3 | 1 | -4 | -2 |
|
||||
+-----------+--------+-----------+-----------+-----------+-----------+
|
||||
| -10 / -3 | 3.3 | 3 | -1 | 3 | -1 |
|
||||
+-----------+--------+-----------+-----------+-----------+-----------+
|
||||
| 10 / 3 | 3.3 | 3 | 1 | 3 | 1 |
|
||||
+-----------+--------+-----------+-----------+-----------+-----------+
|
||||
|
||||
.. autocellgroup:: binary
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
138
docs/source/cell/word_debug.rst
Normal file
138
docs/source/cell/word_debug.rst
Normal file
|
@ -0,0 +1,138 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Debugging cells
|
||||
---------------
|
||||
|
||||
The `$print` cell is used to log the values of signals, akin to (and
|
||||
translatable to) the ``$display`` and ``$write`` family of tasks in Verilog. It
|
||||
has the following parameters:
|
||||
|
||||
``FORMAT``
|
||||
The internal format string. The syntax is described below.
|
||||
|
||||
``ARGS_WIDTH``
|
||||
The width (in bits) of the signal on the ``ARGS`` port.
|
||||
|
||||
``TRG_ENABLE``
|
||||
True if triggered on specific signals defined in ``TRG``; false if triggered
|
||||
whenever ``ARGS`` or ``EN`` change and ``EN`` is 1.
|
||||
|
||||
If ``TRG_ENABLE`` is true, the following parameters also apply:
|
||||
|
||||
``TRG_WIDTH``
|
||||
The number of bits in the ``TRG`` port.
|
||||
|
||||
``TRG_POLARITY``
|
||||
For each bit in ``TRG``, 1 if that signal is positive-edge triggered, 0 if
|
||||
negative-edge triggered.
|
||||
|
||||
``PRIORITY``
|
||||
When multiple `$print` or `$check` cells fire on the same trigger, they
|
||||
execute in descending priority order.
|
||||
|
||||
Ports:
|
||||
|
||||
``TRG``
|
||||
The signals that control when this `$print` cell is triggered.
|
||||
|
||||
If the width of this port is zero and ``TRG_ENABLE`` is true, the cell is
|
||||
triggered during initial evaluation (time zero) only.
|
||||
|
||||
``EN``
|
||||
Enable signal for the whole cell.
|
||||
|
||||
``ARGS``
|
||||
The values to be displayed, in format string order.
|
||||
|
||||
.. autocellgroup:: debug
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
||||
|
||||
Format string syntax
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The format string syntax resembles Python f-strings. Regular text is passed
|
||||
through unchanged until a format specifier is reached, starting with a ``{``.
|
||||
|
||||
Format specifiers have the following syntax. Unless noted, all items are
|
||||
required:
|
||||
|
||||
``{``
|
||||
Denotes the start of the format specifier.
|
||||
|
||||
size
|
||||
Signal size in bits; this many bits are consumed from the ``ARGS`` port by
|
||||
this specifier.
|
||||
|
||||
``:``
|
||||
Separates the size from the remaining items.
|
||||
|
||||
justify
|
||||
``>`` for right-justified, ``<`` for left-justified.
|
||||
|
||||
padding
|
||||
``0`` for zero-padding, or a space for space-padding.
|
||||
|
||||
width\ *?*
|
||||
(optional) The number of characters wide to pad to.
|
||||
|
||||
base
|
||||
* ``b`` for base-2 integers (binary)
|
||||
* ``o`` for base-8 integers (octal)
|
||||
* ``d`` for base-10 integers (decimal)
|
||||
* ``h`` for base-16 integers (hexadecimal)
|
||||
* ``c`` for ASCII characters/strings
|
||||
* ``t`` and ``r`` for simulation time (corresponding to :verilog:`$time` and
|
||||
:verilog:`$realtime`)
|
||||
|
||||
For integers, this item may follow:
|
||||
|
||||
``+``\ *?*
|
||||
(optional, decimals only) Include a leading plus for non-negative numbers.
|
||||
This can assist with symmetry with negatives in tabulated output.
|
||||
|
||||
signedness
|
||||
``u`` for unsigned, ``s`` for signed. This distinction is only respected
|
||||
when rendering decimals.
|
||||
|
||||
ASCII characters/strings have no special options, but the signal size must be
|
||||
divisible by 8.
|
||||
|
||||
For simulation time, the signal size must be zero.
|
||||
|
||||
Finally:
|
||||
|
||||
``}``
|
||||
Denotes the end of the format specifier.
|
||||
|
||||
Some example format specifiers:
|
||||
|
||||
+ ``{8:>02hu}`` - 8-bit unsigned integer rendered as hexadecimal,
|
||||
right-justified, zero-padded to 2 characters wide.
|
||||
+ ``{32:< 15d+s}`` - 32-bit signed integer rendered as decimal, left-justified,
|
||||
space-padded to 15 characters wide, positive values prefixed with ``+``.
|
||||
+ ``{16:< 10hu}`` - 16-bit unsigned integer rendered as hexadecimal,
|
||||
left-justified, space-padded to 10 characters wide.
|
||||
+ ``{0:>010t}`` - simulation time, right-justified, zero-padded to 10 characters
|
||||
wide.
|
||||
|
||||
To include literal ``{`` and ``}`` characters in your format string, use ``{{``
|
||||
and ``}}`` respectively.
|
||||
|
||||
It is an error for a format string to consume more or less bits from ``ARGS``
|
||||
than the port width.
|
||||
|
||||
Values are never truncated, regardless of the specified width.
|
||||
|
||||
Note that further restrictions on allowable combinations of options may apply
|
||||
depending on the backend used.
|
||||
|
||||
For example, Verilog does not have a format specifier that allows zero-padding a
|
||||
string (i.e. more than 1 ASCII character), though zero-padding a single
|
||||
character is permitted.
|
||||
|
||||
Thus, while the RTLIL format specifier ``{8:>02c}`` translates to ``%02c``,
|
||||
``{16:>02c}`` cannot be represented in Verilog and will fail to emit. In this
|
||||
case, ``{16:> 02c}`` must be used, which translates to ``%2s``.
|
31
docs/source/cell/word_formal.rst
Normal file
31
docs/source/cell/word_formal.rst
Normal file
|
@ -0,0 +1,31 @@
|
|||
Formal verification cells
|
||||
-------------------------
|
||||
|
||||
.. role:: yoscrypt(code)
|
||||
:language: yoscrypt
|
||||
|
||||
.. note::
|
||||
|
||||
Some front-ends may not support the generic `$check` cell, in such cases
|
||||
calling :yoscrypt:`chformal -lower` will convert each `$check` cell into it's
|
||||
equivalent. See `chformal` for more.
|
||||
|
||||
.. todo:: Describe formal cells
|
||||
|
||||
`$check`, `$assert`, `$assume`, `$live`, `$fair`, `$cover`, `$equiv`,
|
||||
`$initstate`, `$anyconst`, `$anyseq`, `$anyinit`, `$allconst`, and `$allseq`.
|
||||
|
||||
Also `$ff` and `$_FF_` cells.
|
||||
|
||||
.. autocellgroup:: formal
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
||||
|
||||
Formal support cells
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autocellgroup:: formal_tag
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
9
docs/source/cell/word_fsm.rst
Normal file
9
docs/source/cell/word_fsm.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
Finite state machines
|
||||
---------------------
|
||||
|
||||
.. todo:: Describe `$fsm` cell
|
||||
|
||||
.. autocellgroup:: fsm
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
46
docs/source/cell/word_logic.rst
Normal file
46
docs/source/cell/word_logic.rst
Normal file
|
@ -0,0 +1,46 @@
|
|||
Arbitrary logic functions
|
||||
-------------------------
|
||||
|
||||
The `$lut` cell type implements a single-output LUT (lookup table). It
|
||||
implements an arbitrary logic function with its ``\LUT`` parameter to map input
|
||||
port ``\A`` to values of ``\Y`` output port values. In psuedocode: ``Y =
|
||||
\LUT[A]``. ``\A`` has width set by parameter ``\WIDTH`` and ``\Y`` has a width
|
||||
of 1. Every logic function with a single bit output has a unique `$lut`
|
||||
representation.
|
||||
|
||||
The `$sop` cell type implements a sum-of-products expression, also known as
|
||||
disjunctive normal form (DNF). It implements an arbitrary logic function. Its
|
||||
structure mimics a programmable logic array (PLA). Output port ``\Y`` is the sum
|
||||
of products of the bits of the input port ``\A`` as defined by parameter
|
||||
``\TABLE``. ``\A`` is ``\WIDTH`` bits wide. The number of products in the sum is
|
||||
set by parameter ``\DEPTH``, and each product has two bits for each input bit -
|
||||
for the presence of the unnegated and negated version of said input bit in the
|
||||
product. Therefore the ``\TABLE`` parameter holds ``2 * \WIDTH * \DEPTH`` bits.
|
||||
|
||||
For example:
|
||||
|
||||
Let ``\WIDTH`` be 3. We would like to represent ``\Y =~\A[0] + \A[1]~\A[2]``.
|
||||
There are 2 products to be summed, so ``\DEPTH`` shall be 2.
|
||||
|
||||
.. code-block::
|
||||
|
||||
~A[2]-----+
|
||||
A[2]----+|
|
||||
~A[1]---+||
|
||||
A[1]--+|||
|
||||
~A[0]-+||||
|
||||
A[0]+|||||
|
||||
|||||| product formula
|
||||
010000 ~\A[0]
|
||||
001001 \A[1]~\A[2]
|
||||
|
||||
So the value of ``\TABLE`` will become ``010000001001``.
|
||||
|
||||
Any logic function with a single bit output can be represented with ``$sop`` but
|
||||
may have variously minimized or ordered summands represented in the ``\TABLE``
|
||||
values.
|
||||
|
||||
.. autocellgroup:: logic
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
281
docs/source/cell/word_mem.rst
Normal file
281
docs/source/cell/word_mem.rst
Normal file
|
@ -0,0 +1,281 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
.. _sec:memcells:
|
||||
|
||||
Memories
|
||||
~~~~~~~~
|
||||
|
||||
Memories are either represented using ``RTLIL::Memory`` objects, `$memrd_v2`,
|
||||
`$memwr_v2`, and `$meminit_v2` cells, or by `$mem_v2` cells alone.
|
||||
|
||||
In the first alternative the ``RTLIL::Memory`` objects hold the general metadata
|
||||
for the memory (bit width, size in number of words, etc.) and for each port a
|
||||
`$memrd_v2` (read port) or `$memwr_v2` (write port) cell is created. Having
|
||||
individual cells for read and write ports has the advantage that they can be
|
||||
consolidated using resource sharing passes. In some cases this drastically
|
||||
reduces the number of required ports on the memory cell. In this alternative,
|
||||
memory initialization data is represented by `$meminit_v2` cells, which allow
|
||||
delaying constant folding for initialization addresses and data until after the
|
||||
frontend finishes.
|
||||
|
||||
The `$memrd_v2` cells have a clock input ``CLK``, an enable input ``EN``, an
|
||||
address input ``ADDR``, a data output ``DATA``, an asynchronous reset input
|
||||
``ARST``, and a synchronous reset input ``SRST``. They also have the following
|
||||
parameters:
|
||||
|
||||
``MEMID``
|
||||
The name of the ``RTLIL::Memory`` object that is associated with this read
|
||||
port.
|
||||
|
||||
``ABITS``
|
||||
The number of address bits (width of the ``ADDR`` input port).
|
||||
|
||||
``WIDTH``
|
||||
The number of data bits (width of the ``DATA`` output port). Note that this
|
||||
may be a power-of-two multiple of the underlying memory's width -- such ports
|
||||
are called wide ports and access an aligned group of cells at once. In this
|
||||
case, the corresponding low bits of ``ADDR`` must be tied to 0.
|
||||
|
||||
``CLK_ENABLE``
|
||||
When this parameter is non-zero, the clock is used. Otherwise this read port
|
||||
is asynchronous and the ``CLK`` input is not used.
|
||||
|
||||
``CLK_POLARITY``
|
||||
Clock is active on the positive edge if this parameter has the value ``1'b1``
|
||||
and on the negative edge if this parameter is ``1'b0``.
|
||||
|
||||
``TRANSPARENCY_MASK``
|
||||
This parameter is a bitmask of write ports that this read port is transparent
|
||||
with. The bits of this parameter are indexed by the write port's ``PORTID``
|
||||
parameter. Transparency can only be enabled between synchronous ports sharing
|
||||
a clock domain. When transparency is enabled for a given port pair, a read
|
||||
and write to the same address in the same cycle will return the new value.
|
||||
Otherwise the old value is returned.
|
||||
|
||||
``COLLISION_X_MASK``
|
||||
This parameter is a bitmask of write ports that have undefined collision
|
||||
behavior with this port. The bits of this parameter are indexed by the write
|
||||
port's ``PORTID`` parameter. This behavior can only be enabled between
|
||||
synchronous ports sharing a clock domain. When undefined collision is enabled
|
||||
for a given port pair, a read and write to the same address in the same cycle
|
||||
will return the undefined (all-X) value.This option is exclusive (for a given
|
||||
port pair) with the transparency option.
|
||||
|
||||
``ARST_VALUE``
|
||||
Whenever the ``ARST`` input is asserted, the data output will be reset to
|
||||
this value. Only used for synchronous ports.
|
||||
|
||||
``SRST_VALUE``
|
||||
Whenever the ``SRST`` input is synchronously asserted, the data output will
|
||||
be reset to this value. Only used for synchronous ports.
|
||||
|
||||
``INIT_VALUE``
|
||||
The initial value of the data output, for synchronous ports.
|
||||
|
||||
``CE_OVER_SRST``
|
||||
If this parameter is non-zero, the ``SRST`` input is only recognized when
|
||||
``EN`` is true. Otherwise, ``SRST`` is recognized regardless of ``EN``.
|
||||
|
||||
The `$memwr_v2` cells have a clock input ``CLK``, an enable input ``EN`` (one
|
||||
enable bit for each data bit), an address input ``ADDR`` and a data input
|
||||
``DATA``. They also have the following parameters:
|
||||
|
||||
``MEMID``
|
||||
The name of the ``RTLIL::Memory`` object that is associated with this write
|
||||
port.
|
||||
|
||||
``ABITS``
|
||||
The number of address bits (width of the ``ADDR`` input port).
|
||||
|
||||
``WIDTH``
|
||||
The number of data bits (width of the ``DATA`` output port). Like with
|
||||
`$memrd_v2` cells, the width is allowed to be any power-of-two multiple of
|
||||
memory width, with the corresponding restriction on address.
|
||||
|
||||
``CLK_ENABLE``
|
||||
When this parameter is non-zero, the clock is used. Otherwise this write port
|
||||
is asynchronous and the ``CLK`` input is not used.
|
||||
|
||||
``CLK_POLARITY``
|
||||
Clock is active on positive edge if this parameter has the value ``1'b1`` and
|
||||
on the negative edge if this parameter is ``1'b0``.
|
||||
|
||||
``PORTID``
|
||||
An identifier for this write port, used to index write port bit mask
|
||||
parameters.
|
||||
|
||||
``PRIORITY_MASK``
|
||||
This parameter is a bitmask of write ports that this write port has priority
|
||||
over in case of writing to the same address. The bits of this parameter are
|
||||
indexed by the other write port's ``PORTID`` parameter. Write ports can only
|
||||
have priority over write ports with lower port ID. When two ports write to
|
||||
the same address and neither has priority over the other, the result is
|
||||
undefined. Priority can only be set between two synchronous ports sharing
|
||||
the same clock domain.
|
||||
|
||||
The `$meminit_v2` cells have an address input ``ADDR``, a data input ``DATA``,
|
||||
with the width of the ``DATA`` port equal to ``WIDTH`` parameter times ``WORDS``
|
||||
parameter, and a bit enable mask input ``EN`` with width equal to ``WIDTH``
|
||||
parameter. All three of the inputs must resolve to a constant for synthesis to
|
||||
succeed.
|
||||
|
||||
``MEMID``
|
||||
The name of the ``RTLIL::Memory`` object that is associated with this
|
||||
initialization cell.
|
||||
|
||||
``ABITS``
|
||||
The number of address bits (width of the ``ADDR`` input port).
|
||||
|
||||
``WIDTH``
|
||||
The number of data bits per memory location.
|
||||
|
||||
``WORDS``
|
||||
The number of consecutive memory locations initialized by this cell.
|
||||
|
||||
``PRIORITY``
|
||||
The cell with the higher integer value in this parameter wins an
|
||||
initialization conflict.
|
||||
|
||||
The HDL frontend models a memory using ``RTLIL::Memory`` objects and
|
||||
asynchronous `$memrd_v2` and `$memwr_v2` cells. The `memory` pass (i.e. its
|
||||
various sub-passes) migrates `$dff` cells into the `$memrd_v2` and `$memwr_v2`
|
||||
cells making them synchronous, then converts them to a single `$mem_v2` cell and
|
||||
(optionally) maps this cell type to `$dff` cells for the individual words and
|
||||
multiplexer-based address decoders for the read and write interfaces. When the
|
||||
last step is disabled or not possible, a `$mem_v2` cell is left in the design.
|
||||
|
||||
The `$mem_v2` cell provides the following parameters:
|
||||
|
||||
``MEMID``
|
||||
The name of the original ``RTLIL::Memory`` object that became this `$mem_v2`
|
||||
cell.
|
||||
|
||||
``SIZE``
|
||||
The number of words in the memory.
|
||||
|
||||
``ABITS``
|
||||
The number of address bits.
|
||||
|
||||
``WIDTH``
|
||||
The number of data bits per word.
|
||||
|
||||
``INIT``
|
||||
The initial memory contents.
|
||||
|
||||
``RD_PORTS``
|
||||
The number of read ports on this memory cell.
|
||||
|
||||
``RD_WIDE_CONTINUATION``
|
||||
This parameter is ``RD_PORTS`` bits wide, containing a bitmask of "wide
|
||||
continuation" read ports. Such ports are used to represent the extra data
|
||||
bits of wide ports in the combined cell, and must have all control signals
|
||||
identical with the preceding port, except for address, which must have the
|
||||
proper sub-cell address encoded in the low bits.
|
||||
|
||||
``RD_CLK_ENABLE``
|
||||
This parameter is ``RD_PORTS`` bits wide, containing a clock enable bit for
|
||||
each read port.
|
||||
|
||||
``RD_CLK_POLARITY``
|
||||
This parameter is ``RD_PORTS`` bits wide, containing a clock polarity bit for
|
||||
each read port.
|
||||
|
||||
``RD_TRANSPARENCY_MASK``
|
||||
This parameter is ``RD_PORTS*WR_PORTS`` bits wide, containing a concatenation
|
||||
of all ``TRANSPARENCY_MASK`` values of the original `$memrd_v2` cells.
|
||||
|
||||
``RD_COLLISION_X_MASK``
|
||||
This parameter is ``RD_PORTS*WR_PORTS`` bits wide, containing a concatenation
|
||||
of all ``COLLISION_X_MASK`` values of the original `$memrd_v2` cells.
|
||||
|
||||
``RD_CE_OVER_SRST``
|
||||
This parameter is ``RD_PORTS`` bits wide, determining relative synchronous
|
||||
reset and enable priority for each read port.
|
||||
|
||||
``RD_INIT_VALUE``
|
||||
This parameter is ``RD_PORTS*WIDTH`` bits wide, containing the initial value
|
||||
for each synchronous read port.
|
||||
|
||||
``RD_ARST_VALUE``
|
||||
This parameter is ``RD_PORTS*WIDTH`` bits wide, containing the asynchronous
|
||||
reset value for each synchronous read port.
|
||||
|
||||
``RD_SRST_VALUE``
|
||||
This parameter is ``RD_PORTS*WIDTH`` bits wide, containing the synchronous
|
||||
reset value for each synchronous read port.
|
||||
|
||||
``WR_PORTS``
|
||||
The number of write ports on this memory cell.
|
||||
|
||||
``WR_WIDE_CONTINUATION``
|
||||
This parameter is ``WR_PORTS`` bits wide, containing a bitmask of "wide
|
||||
continuation" write ports.
|
||||
|
||||
``WR_CLK_ENABLE``
|
||||
This parameter is ``WR_PORTS`` bits wide, containing a clock enable bit for
|
||||
each write port.
|
||||
|
||||
``WR_CLK_POLARITY``
|
||||
This parameter is ``WR_PORTS`` bits wide, containing a clock polarity bit for
|
||||
each write port.
|
||||
|
||||
``WR_PRIORITY_MASK``
|
||||
This parameter is ``WR_PORTS*WR_PORTS`` bits wide, containing a concatenation
|
||||
of all ``PRIORITY_MASK`` values of the original `$memwr_v2` cells.
|
||||
|
||||
The `$mem_v2` cell has the following ports:
|
||||
|
||||
``RD_CLK``
|
||||
This input is ``RD_PORTS`` bits wide, containing all clock signals for the
|
||||
read ports.
|
||||
|
||||
``RD_EN``
|
||||
This input is ``RD_PORTS`` bits wide, containing all enable signals for the
|
||||
read ports.
|
||||
|
||||
``RD_ADDR``
|
||||
This input is ``RD_PORTS*ABITS`` bits wide, containing all address signals
|
||||
for the read ports.
|
||||
|
||||
``RD_DATA``
|
||||
This output is ``RD_PORTS*WIDTH`` bits wide, containing all data signals for
|
||||
the read ports.
|
||||
|
||||
``RD_ARST``
|
||||
This input is ``RD_PORTS`` bits wide, containing all asynchronous reset
|
||||
signals for the read ports.
|
||||
|
||||
``RD_SRST``
|
||||
This input is ``RD_PORTS`` bits wide, containing all synchronous reset
|
||||
signals for the read ports.
|
||||
|
||||
``WR_CLK``
|
||||
This input is ``WR_PORTS`` bits wide, containing all clock signals for the
|
||||
write ports.
|
||||
|
||||
``WR_EN``
|
||||
This input is ``WR_PORTS*WIDTH`` bits wide, containing all enable signals for
|
||||
the write ports.
|
||||
|
||||
``WR_ADDR``
|
||||
This input is ``WR_PORTS*ABITS`` bits wide, containing all address signals
|
||||
for the write ports.
|
||||
|
||||
``WR_DATA``
|
||||
This input is ``WR_PORTS*WIDTH`` bits wide, containing all data signals for
|
||||
the write ports.
|
||||
|
||||
The `memory_collect` pass can be used to convert discrete `$memrd_v2`,
|
||||
`$memwr_v2`, and `$meminit_v2` cells belonging to the same memory to a single
|
||||
`$mem_v2` cell, whereas the `memory_unpack` pass performs the inverse operation.
|
||||
The `memory_dff` pass can combine asynchronous memory ports that are fed by or
|
||||
feeding registers into synchronous memory ports. The `memory_bram` pass can be
|
||||
used to recognize `$mem_v2` cells that can be implemented with a block RAM
|
||||
resource on an FPGA. The `memory_map` pass can be used to implement `$mem_v2`
|
||||
cells as basic logic: word-wide DFFs and address decoders.
|
||||
|
||||
.. autocellgroup:: mem
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
47
docs/source/cell/word_mux.rst
Normal file
47
docs/source/cell/word_mux.rst
Normal file
|
@ -0,0 +1,47 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Multiplexers
|
||||
------------
|
||||
|
||||
Multiplexers are generated by the Verilog HDL frontend for ``?:``-expressions.
|
||||
Multiplexers are also generated by the proc pass to map the decision trees from
|
||||
RTLIL::Process objects to logic.
|
||||
|
||||
The simplest multiplexer cell type is `$mux`. Cells of this type have a
|
||||
``WITDH`` parameter and data inputs ``A`` and ``B`` and a data output ``Y``, all
|
||||
of the specified width. This cell also has a single bit control input ``S``. If
|
||||
``S`` is 0 the value from the input ``A`` is sent to the output, if it is 1 the
|
||||
value from the ``B`` input is sent to the output. So the `$mux` cell implements
|
||||
the function :verilog:`Y = S ? B : A`.
|
||||
|
||||
The `$pmux` cell is used to multiplex between many inputs using a one-hot select
|
||||
signal. Cells of this type have a ``WIDTH`` and a ``S_WIDTH`` parameter and
|
||||
inputs ``A``, ``B``, and ``S`` and an output ``Y``. The ``S`` input is
|
||||
``S_WIDTH`` bits wide. The ``A`` input and the output are both ``WIDTH`` bits
|
||||
wide and the ``B`` input is ``WIDTH*S_WIDTH`` bits wide. When all bits of ``S``
|
||||
are zero, the value from ``A`` input is sent to the output. If the :math:`n`\
|
||||
'th bit from ``S`` is set, the value :math:`n`\ 'th ``WIDTH`` bits wide slice of
|
||||
the ``B`` input is sent to the output. When more than one bit from ``S`` is set
|
||||
the output is undefined. Cells of this type are used to model "parallel cases"
|
||||
(defined by using the ``parallel_case`` attribute or detected by an
|
||||
optimization).
|
||||
|
||||
The `$tribuf` cell is used to implement tristate logic. Cells of this type have
|
||||
a ``WIDTH`` parameter and inputs ``A`` and ``EN`` and an output ``Y``. The ``A``
|
||||
input and ``Y`` output are ``WIDTH`` bits wide, and the ``EN`` input is one bit
|
||||
wide. When ``EN`` is 0, the output is not driven. When ``EN`` is 1, the value
|
||||
from ``A`` input is sent to the ``Y`` output. Therefore, the `$tribuf` cell
|
||||
implements the function :verilog:`Y = EN ? A : 'bz`.
|
||||
|
||||
Behavioural code with cascaded if-then-else- and case-statements usually results
|
||||
in trees of multiplexer cells. Many passes (from various optimizations to FSM
|
||||
extraction) heavily depend on these multiplexer trees to understand dependencies
|
||||
between signals. Therefore optimizations should not break these multiplexer
|
||||
trees (e.g. by replacing a multiplexer between a calculated signal and a
|
||||
constant zero with an `$and` gate).
|
||||
|
||||
.. autocellgroup:: mux
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
124
docs/source/cell/word_reg.rst
Normal file
124
docs/source/cell/word_reg.rst
Normal file
|
@ -0,0 +1,124 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Registers
|
||||
---------
|
||||
|
||||
SR-type latches are represented by `$sr` cells. These cells have input ports
|
||||
``SET`` and ``CLR`` and an output port ``Q``. They have the following
|
||||
parameters:
|
||||
|
||||
``WIDTH``
|
||||
The width of inputs ``SET`` and ``CLR`` and output ``Q``.
|
||||
|
||||
``SET_POLARITY``
|
||||
The set input bits are active-high if this parameter has the value ``1'b1``
|
||||
and active-low if this parameter is ``1'b0``.
|
||||
|
||||
``CLR_POLARITY``
|
||||
The reset input bits are active-high if this parameter has the value ``1'b1``
|
||||
and active-low if this parameter is ``1'b0``.
|
||||
|
||||
Both set and reset inputs have separate bits for every output bit. When both the
|
||||
set and reset inputs of an `$sr` cell are active for a given bit index, the
|
||||
reset input takes precedence.
|
||||
|
||||
D-type flip-flops are represented by `$dff` cells. These cells have a clock port
|
||||
``CLK``, an input port ``D`` and an output port ``Q``. The following parameters
|
||||
are available for `$dff` cells:
|
||||
|
||||
``WIDTH``
|
||||
The width of input ``D`` and output ``Q``.
|
||||
|
||||
``CLK_POLARITY``
|
||||
Clock is active on the positive edge if this parameter has the value ``1'b1``
|
||||
and on the negative edge if this parameter is ``1'b0``.
|
||||
|
||||
D-type flip-flops with asynchronous reset are represented by `$adff` cells. As
|
||||
the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition they also
|
||||
have a single-bit ``ARST`` input port for the reset pin and the following
|
||||
additional two parameters:
|
||||
|
||||
``ARST_POLARITY``
|
||||
The asynchronous reset is active-high if this parameter has the value
|
||||
``1'b1`` and active-low if this parameter is ``1'b0``.
|
||||
|
||||
``ARST_VALUE``
|
||||
The state of ``Q`` will be set to this value when the reset is active.
|
||||
|
||||
Usually these cells are generated by the `proc` pass using the information in
|
||||
the designs RTLIL::Process objects.
|
||||
|
||||
D-type flip-flops with synchronous reset are represented by `$sdff` cells. As
|
||||
the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition they also
|
||||
have a single-bit ``SRST`` input port for the reset pin and the following
|
||||
additional two parameters:
|
||||
|
||||
``SRST_POLARITY``
|
||||
The synchronous reset is active-high if this parameter has the value ``1'b1``
|
||||
and active-low if this parameter is ``1'b0``.
|
||||
|
||||
``SRST_VALUE``
|
||||
The state of ``Q`` will be set to this value when the reset is active.
|
||||
|
||||
Note that the `$adff` and `$sdff` cells can only be used when the reset value is
|
||||
constant.
|
||||
|
||||
D-type flip-flops with asynchronous load are represented by `$aldff` cells. As
|
||||
the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition they also
|
||||
have a single-bit ``ALOAD`` input port for the async load enable pin, a ``AD``
|
||||
input port with the same width as data for the async load data, and the
|
||||
following additional parameter:
|
||||
|
||||
``ALOAD_POLARITY``
|
||||
The asynchronous load is active-high if this parameter has the value ``1'b1``
|
||||
and active-low if this parameter is ``1'b0``.
|
||||
|
||||
D-type flip-flops with asynchronous set and reset are represented by `$dffsr`
|
||||
cells. As the `$dff` cells they have ``CLK``, ``D`` and ``Q`` ports. In addition
|
||||
they also have multi-bit ``SET`` and ``CLR`` input ports and the corresponding
|
||||
polarity parameters, like `$sr` cells.
|
||||
|
||||
D-type flip-flops with enable are represented by `$dffe`, `$adffe`, `$aldffe`,
|
||||
`$dffsre`, `$sdffe`, and `$sdffce` cells, which are enhanced variants of `$dff`,
|
||||
`$adff`, `$aldff`, `$dffsr`, `$sdff` (with reset over enable) and `$sdff` (with
|
||||
enable over reset) cells, respectively. They have the same ports and parameters
|
||||
as their base cell. In addition they also have a single-bit ``EN`` input port
|
||||
for the enable pin and the following parameter:
|
||||
|
||||
``EN_POLARITY``
|
||||
The enable input is active-high if this parameter has the value ``1'b1`` and
|
||||
active-low if this parameter is ``1'b0``.
|
||||
|
||||
D-type latches are represented by `$dlatch` cells. These cells have an enable
|
||||
port ``EN``, an input port ``D``, and an output port ``Q``. The following
|
||||
parameters are available for `$dlatch` cells:
|
||||
|
||||
``WIDTH``
|
||||
The width of input ``D`` and output ``Q``.
|
||||
|
||||
``EN_POLARITY``
|
||||
The enable input is active-high if this parameter has the value ``1'b1`` and
|
||||
active-low if this parameter is ``1'b0``.
|
||||
|
||||
The latch is transparent when the ``EN`` input is active.
|
||||
|
||||
D-type latches with reset are represented by `$adlatch` cells. In addition to
|
||||
`$dlatch` ports and parameters, they also have a single-bit ``ARST`` input port
|
||||
for the reset pin and the following additional parameters:
|
||||
|
||||
``ARST_POLARITY``
|
||||
The asynchronous reset is active-high if this parameter has the value
|
||||
``1'b1`` and active-low if this parameter is ``1'b0``.
|
||||
|
||||
``ARST_VALUE``
|
||||
The state of ``Q`` will be set to this value when the reset is active.
|
||||
|
||||
D-type latches with set and reset are represented by `$dlatchsr` cells. In
|
||||
addition to `$dlatch` ports and parameters, they also have multi-bit ``SET`` and
|
||||
``CLR`` input ports and the corresponding polarity parameters, like `$sr` cells.
|
||||
|
||||
.. autocellgroup:: reg
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
9
docs/source/cell/word_spec.rst
Normal file
9
docs/source/cell/word_spec.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
Specify rules
|
||||
-------------
|
||||
|
||||
.. todo:: `$specify2`, `$specify3`, and `$specrule` cells.
|
||||
|
||||
.. autocellgroup:: spec
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
50
docs/source/cell/word_unary.rst
Normal file
50
docs/source/cell/word_unary.rst
Normal file
|
@ -0,0 +1,50 @@
|
|||
.. role:: verilog(code)
|
||||
:language: Verilog
|
||||
|
||||
Unary operators
|
||||
---------------
|
||||
|
||||
All unary RTL cells have one input port ``A`` and one output port ``Y``. They
|
||||
also have the following parameters:
|
||||
|
||||
``A_SIGNED``
|
||||
Set to a non-zero value if the input ``A`` is signed and therefore should be
|
||||
sign-extended when needed.
|
||||
|
||||
``A_WIDTH``
|
||||
The width of the input port ``A``.
|
||||
|
||||
``Y_WIDTH``
|
||||
The width of the output port ``Y``.
|
||||
|
||||
.. table:: Cell types for unary operators with their corresponding Verilog expressions.
|
||||
|
||||
================== ==============
|
||||
Verilog Cell Type
|
||||
================== ==============
|
||||
:verilog:`Y = ~A` `$not`
|
||||
:verilog:`Y = +A` `$pos`
|
||||
:verilog:`Y = -A` `$neg`
|
||||
:verilog:`Y = &A` `$reduce_and`
|
||||
:verilog:`Y = |A` `$reduce_or`
|
||||
:verilog:`Y = ^A` `$reduce_xor`
|
||||
:verilog:`Y = ~^A` `$reduce_xnor`
|
||||
:verilog:`Y = |A` `$reduce_bool`
|
||||
:verilog:`Y = !A` `$logic_not`
|
||||
================== ==============
|
||||
|
||||
For the unary cells that output a logical value (`$reduce_and`, `$reduce_or`,
|
||||
`$reduce_xor`, `$reduce_xnor`, `$reduce_bool`, `$logic_not`), when the
|
||||
``Y_WIDTH`` parameter is greater than 1, the output is zero-extended, and only
|
||||
the least significant bit varies.
|
||||
|
||||
Note that `$reduce_or` and `$reduce_bool` generally represent the same logic
|
||||
function. But the `read_verilog` frontend will generate them in different
|
||||
situations. A `$reduce_or` cell is generated when the prefix ``|`` operator is
|
||||
being used. A `$reduce_bool` cell is generated when a bit vector is used as a
|
||||
condition in an ``if``-statement or ``?:``-expression.
|
||||
|
||||
.. autocellgroup:: unary
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
9
docs/source/cell/word_wire.rst
Normal file
9
docs/source/cell/word_wire.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
Wire cells
|
||||
-------------------------
|
||||
|
||||
.. todo:: Add information about `$slice` and `$concat` cells.
|
||||
|
||||
.. autocellgroup:: wire
|
||||
:members:
|
||||
:source:
|
||||
:linenos:
|
15
docs/source/cell_index.rst
Normal file
15
docs/source/cell_index.rst
Normal file
|
@ -0,0 +1,15 @@
|
|||
Internal cell library
|
||||
=====================
|
||||
|
||||
The intermediate language used by Yosys (RTLIL) represents logic and memory with
|
||||
a series of cells. This section provides details for those cells, breaking them
|
||||
down into two major categories: coarse-grain word-level cells; and fine-grain
|
||||
gate-level cells. An additional section contains a list of properties which may
|
||||
be shared across multiple cells.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/cell/index_word
|
||||
/cell/index_gate
|
||||
/cell/properties
|
3
docs/source/code_examples/.gitignore
vendored
3
docs/source/code_examples/.gitignore
vendored
|
@ -1,2 +1,5 @@
|
|||
*.dot
|
||||
*.pdf
|
||||
*.out
|
||||
*.log
|
||||
*.stat
|
||||
|
|
|
@ -2,9 +2,10 @@ PROGRAM_PREFIX :=
|
|||
|
||||
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
||||
|
||||
.PHONY: all dots
|
||||
all: dots test0.log test1.log test2.log
|
||||
dots: test1.dot
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: test1.dot my_cmd.so
|
||||
examples: test0.log test1.log test2.log my_cmd.so
|
||||
|
||||
CXXFLAGS=$(shell $(YOSYS)-config --cxxflags)
|
||||
DATDIR=$(shell $(YOSYS)-config --datdir)
|
||||
|
|
2
docs/source/code_examples/fifo/.gitignore
vendored
Normal file
2
docs/source/code_examples/fifo/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.out
|
||||
*.stat
|
|
@ -10,8 +10,10 @@ MAPDOT_NAMES += rdata_map_ffs rdata_map_luts rdata_map_cells
|
|||
DOTS := $(addsuffix .dot,$(DOT_NAMES))
|
||||
MAPDOTS := $(addsuffix .dot,$(MAPDOT_NAMES))
|
||||
|
||||
all: dots fifo.out fifo.stat
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: $(DOTS) $(MAPDOTS)
|
||||
examples: fifo.out fifo.stat
|
||||
|
||||
$(DOTS) fifo.out: fifo.v fifo.ys
|
||||
$(YOSYS) fifo.ys -l fifo.out -Q -T
|
||||
|
@ -22,3 +24,4 @@ $(MAPDOTS) fifo.stat: fifo.v fifo_map.ys
|
|||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.dot
|
||||
rm -f fifo.out fifo.stat
|
||||
|
|
|
@ -1,425 +0,0 @@
|
|||
|
||||
-- Executing script file `fifo.ys' --
|
||||
$ yosys fifo.v
|
||||
|
||||
-- Parsing `fifo.v' using frontend ` -vlog2k' --
|
||||
|
||||
1. Executing Verilog-2005 frontend: fifo.v
|
||||
Parsing Verilog input from `fifo.v' to AST representation.
|
||||
Storing AST representation for module `$abstract\addr_gen'.
|
||||
Storing AST representation for module `$abstract\fifo'.
|
||||
Successfully finished Verilog frontend.
|
||||
echo on
|
||||
|
||||
yosys> hierarchy -top addr_gen
|
||||
|
||||
2. Executing HIERARCHY pass (managing design hierarchy).
|
||||
|
||||
3. Executing AST frontend in derive mode using pre-parsed AST for module `\addr_gen'.
|
||||
Generating RTLIL representation for module `\addr_gen'.
|
||||
|
||||
3.1. Analyzing design hierarchy..
|
||||
Top module: \addr_gen
|
||||
|
||||
3.2. Analyzing design hierarchy..
|
||||
Top module: \addr_gen
|
||||
Removing unused module `$abstract\fifo'.
|
||||
Removing unused module `$abstract\addr_gen'.
|
||||
Removed 2 unused modules.
|
||||
|
||||
yosys> select -module addr_gen
|
||||
|
||||
yosys [addr_gen]> select -list
|
||||
addr_gen
|
||||
addr_gen/$1\addr[7:0]
|
||||
addr_gen/$add$fifo.v:19$3_Y
|
||||
addr_gen/$eq$fifo.v:16$2_Y
|
||||
addr_gen/$0\addr[7:0]
|
||||
addr_gen/addr
|
||||
addr_gen/rst
|
||||
addr_gen/clk
|
||||
addr_gen/en
|
||||
addr_gen/$add$fifo.v:19$3
|
||||
addr_gen/$eq$fifo.v:16$2
|
||||
addr_gen/$proc$fifo.v:0$4
|
||||
addr_gen/$proc$fifo.v:12$1
|
||||
|
||||
yosys [addr_gen]> select t:*
|
||||
|
||||
yosys [addr_gen]*> select -list
|
||||
addr_gen/$add$fifo.v:19$3
|
||||
addr_gen/$eq$fifo.v:16$2
|
||||
|
||||
yosys [addr_gen]*> select -set new_cells %
|
||||
|
||||
yosys [addr_gen]*> select -clear
|
||||
|
||||
yosys> show -format dot -prefix addr_gen_show addr_gen
|
||||
|
||||
4. Generating Graphviz representation of design.
|
||||
Writing dot description to `addr_gen_show.dot'.
|
||||
Dumping module addr_gen to page 1.
|
||||
|
||||
yosys> show -format dot -prefix new_cells_show -notitle @new_cells
|
||||
|
||||
5. Generating Graphviz representation of design.
|
||||
Writing dot description to `new_cells_show.dot'.
|
||||
Dumping selected parts of module addr_gen to page 1.
|
||||
|
||||
yosys> show -color maroon3 @new_cells -color cornflowerblue p:* -notitle -format dot -prefix addr_gen_hier
|
||||
|
||||
6. Generating Graphviz representation of design.
|
||||
Writing dot description to `addr_gen_hier.dot'.
|
||||
Dumping module addr_gen to page 1.
|
||||
|
||||
yosys> proc -noopt
|
||||
|
||||
7. Executing PROC pass (convert processes to netlists).
|
||||
|
||||
yosys> proc_clean
|
||||
|
||||
7.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
|
||||
Cleaned up 0 empty switches.
|
||||
|
||||
yosys> proc_rmdead
|
||||
|
||||
7.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
|
||||
Marked 2 switch rules as full_case in process $proc$fifo.v:12$1 in module addr_gen.
|
||||
Removed a total of 0 dead cases.
|
||||
|
||||
yosys> proc_prune
|
||||
|
||||
7.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
|
||||
Removed 0 redundant assignments.
|
||||
Promoted 1 assignment to connection.
|
||||
|
||||
yosys> proc_init
|
||||
|
||||
7.4. Executing PROC_INIT pass (extract init attributes).
|
||||
Found init rule in `\addr_gen.$proc$fifo.v:0$4'.
|
||||
Set init value: \addr = 8'00000000
|
||||
|
||||
yosys> proc_arst
|
||||
|
||||
7.5. Executing PROC_ARST pass (detect async resets in processes).
|
||||
Found async reset \rst in `\addr_gen.$proc$fifo.v:12$1'.
|
||||
|
||||
yosys> proc_rom
|
||||
|
||||
7.6. Executing PROC_ROM pass (convert switches to ROMs).
|
||||
Converted 0 switches.
|
||||
<suppressed ~2 debug messages>
|
||||
|
||||
yosys> proc_mux
|
||||
|
||||
7.7. Executing PROC_MUX pass (convert decision trees to multiplexers).
|
||||
Creating decoders for process `\addr_gen.$proc$fifo.v:0$4'.
|
||||
Creating decoders for process `\addr_gen.$proc$fifo.v:12$1'.
|
||||
1/1: $0\addr[7:0]
|
||||
|
||||
yosys> proc_dlatch
|
||||
|
||||
7.8. Executing PROC_DLATCH pass (convert process syncs to latches).
|
||||
|
||||
yosys> proc_dff
|
||||
|
||||
7.9. Executing PROC_DFF pass (convert process syncs to FFs).
|
||||
Creating register for signal `\addr_gen.\addr' using process `\addr_gen.$proc$fifo.v:12$1'.
|
||||
created $adff cell `$procdff$10' with positive edge clock and positive level reset.
|
||||
|
||||
yosys> proc_memwr
|
||||
|
||||
7.10. Executing PROC_MEMWR pass (convert process memory writes to cells).
|
||||
|
||||
yosys> proc_clean
|
||||
|
||||
7.11. Executing PROC_CLEAN pass (remove empty switches from decision trees).
|
||||
Removing empty process `addr_gen.$proc$fifo.v:0$4'.
|
||||
Found and cleaned up 2 empty switches in `\addr_gen.$proc$fifo.v:12$1'.
|
||||
Removing empty process `addr_gen.$proc$fifo.v:12$1'.
|
||||
Cleaned up 2 empty switches.
|
||||
|
||||
yosys> select -set new_cells t:$mux t:*dff
|
||||
|
||||
yosys> show -color maroon3 @new_cells -notitle -format dot -prefix addr_gen_proc
|
||||
|
||||
8. Generating Graphviz representation of design.
|
||||
Writing dot description to `addr_gen_proc.dot'.
|
||||
Dumping module addr_gen to page 1.
|
||||
|
||||
yosys> opt_expr
|
||||
|
||||
9. Executing OPT_EXPR pass (perform const folding).
|
||||
Optimizing module addr_gen.
|
||||
|
||||
yosys> clean
|
||||
Removed 0 unused cells and 4 unused wires.
|
||||
|
||||
yosys> select -set new_cells t:$eq
|
||||
|
||||
yosys> show -color cornflowerblue @new_cells -notitle -format dot -prefix addr_gen_clean
|
||||
|
||||
10. Generating Graphviz representation of design.
|
||||
Writing dot description to `addr_gen_clean.dot'.
|
||||
Dumping module addr_gen to page 1.
|
||||
|
||||
yosys> design -reset
|
||||
|
||||
yosys> read_verilog fifo.v
|
||||
|
||||
11. Executing Verilog-2005 frontend: fifo.v
|
||||
Parsing Verilog input from `fifo.v' to AST representation.
|
||||
Generating RTLIL representation for module `\addr_gen'.
|
||||
Generating RTLIL representation for module `\fifo'.
|
||||
Successfully finished Verilog frontend.
|
||||
|
||||
yosys> hierarchy -check -top fifo
|
||||
|
||||
12. Executing HIERARCHY pass (managing design hierarchy).
|
||||
|
||||
12.1. Analyzing design hierarchy..
|
||||
Top module: \fifo
|
||||
Used module: \addr_gen
|
||||
Parameter \MAX_DATA = 256
|
||||
|
||||
12.2. Executing AST frontend in derive mode using pre-parsed AST for module `\addr_gen'.
|
||||
Parameter \MAX_DATA = 256
|
||||
Generating RTLIL representation for module `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000'.
|
||||
Parameter \MAX_DATA = 256
|
||||
Found cached RTLIL representation for module `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000'.
|
||||
|
||||
12.3. Analyzing design hierarchy..
|
||||
Top module: \fifo
|
||||
Used module: $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000
|
||||
|
||||
12.4. Analyzing design hierarchy..
|
||||
Top module: \fifo
|
||||
Used module: $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000
|
||||
Removing unused module `\addr_gen'.
|
||||
Removed 1 unused modules.
|
||||
|
||||
yosys> proc
|
||||
|
||||
13. Executing PROC pass (convert processes to netlists).
|
||||
|
||||
yosys> proc_clean
|
||||
|
||||
13.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
|
||||
Cleaned up 0 empty switches.
|
||||
|
||||
yosys> proc_rmdead
|
||||
|
||||
13.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
|
||||
Marked 2 switch rules as full_case in process $proc$fifo.v:62$24 in module fifo.
|
||||
Marked 1 switch rules as full_case in process $proc$fifo.v:36$16 in module fifo.
|
||||
Marked 2 switch rules as full_case in process $proc$fifo.v:12$32 in module $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.
|
||||
Removed a total of 0 dead cases.
|
||||
|
||||
yosys> proc_prune
|
||||
|
||||
13.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
|
||||
Removed 0 redundant assignments.
|
||||
Promoted 6 assignments to connections.
|
||||
|
||||
yosys> proc_init
|
||||
|
||||
13.4. Executing PROC_INIT pass (extract init attributes).
|
||||
Found init rule in `\fifo.$proc$fifo.v:0$31'.
|
||||
Set init value: \count = 9'000000000
|
||||
Found init rule in `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:0$35'.
|
||||
Set init value: \addr = 8'00000000
|
||||
|
||||
yosys> proc_arst
|
||||
|
||||
13.5. Executing PROC_ARST pass (detect async resets in processes).
|
||||
Found async reset \rst in `\fifo.$proc$fifo.v:62$24'.
|
||||
Found async reset \rst in `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:12$32'.
|
||||
|
||||
yosys> proc_rom
|
||||
|
||||
13.6. Executing PROC_ROM pass (convert switches to ROMs).
|
||||
Converted 0 switches.
|
||||
<suppressed ~5 debug messages>
|
||||
|
||||
yosys> proc_mux
|
||||
|
||||
13.7. Executing PROC_MUX pass (convert decision trees to multiplexers).
|
||||
Creating decoders for process `\fifo.$proc$fifo.v:0$31'.
|
||||
Creating decoders for process `\fifo.$proc$fifo.v:62$24'.
|
||||
1/1: $0\count[8:0]
|
||||
Creating decoders for process `\fifo.$proc$fifo.v:36$16'.
|
||||
1/3: $1$memwr$\data$fifo.v:38$15_EN[7:0]$22
|
||||
2/3: $1$memwr$\data$fifo.v:38$15_DATA[7:0]$21
|
||||
3/3: $1$memwr$\data$fifo.v:38$15_ADDR[7:0]$20
|
||||
Creating decoders for process `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:0$35'.
|
||||
Creating decoders for process `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:12$32'.
|
||||
1/1: $0\addr[7:0]
|
||||
|
||||
yosys> proc_dlatch
|
||||
|
||||
13.8. Executing PROC_DLATCH pass (convert process syncs to latches).
|
||||
|
||||
yosys> proc_dff
|
||||
|
||||
13.9. Executing PROC_DFF pass (convert process syncs to FFs).
|
||||
Creating register for signal `\fifo.\count' using process `\fifo.$proc$fifo.v:62$24'.
|
||||
created $adff cell `$procdff$55' with positive edge clock and positive level reset.
|
||||
Creating register for signal `\fifo.\rdata' using process `\fifo.$proc$fifo.v:36$16'.
|
||||
created $dff cell `$procdff$56' with positive edge clock.
|
||||
Creating register for signal `\fifo.$memwr$\data$fifo.v:38$15_ADDR' using process `\fifo.$proc$fifo.v:36$16'.
|
||||
created $dff cell `$procdff$57' with positive edge clock.
|
||||
Creating register for signal `\fifo.$memwr$\data$fifo.v:38$15_DATA' using process `\fifo.$proc$fifo.v:36$16'.
|
||||
created $dff cell `$procdff$58' with positive edge clock.
|
||||
Creating register for signal `\fifo.$memwr$\data$fifo.v:38$15_EN' using process `\fifo.$proc$fifo.v:36$16'.
|
||||
created $dff cell `$procdff$59' with positive edge clock.
|
||||
Creating register for signal `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.\addr' using process `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:12$32'.
|
||||
created $adff cell `$procdff$60' with positive edge clock and positive level reset.
|
||||
|
||||
yosys> proc_memwr
|
||||
|
||||
13.10. Executing PROC_MEMWR pass (convert process memory writes to cells).
|
||||
|
||||
yosys> proc_clean
|
||||
|
||||
13.11. Executing PROC_CLEAN pass (remove empty switches from decision trees).
|
||||
Removing empty process `fifo.$proc$fifo.v:0$31'.
|
||||
Found and cleaned up 2 empty switches in `\fifo.$proc$fifo.v:62$24'.
|
||||
Removing empty process `fifo.$proc$fifo.v:62$24'.
|
||||
Found and cleaned up 1 empty switch in `\fifo.$proc$fifo.v:36$16'.
|
||||
Removing empty process `fifo.$proc$fifo.v:36$16'.
|
||||
Removing empty process `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:0$35'.
|
||||
Found and cleaned up 2 empty switches in `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:12$32'.
|
||||
Removing empty process `$paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.$proc$fifo.v:12$32'.
|
||||
Cleaned up 5 empty switches.
|
||||
|
||||
yosys> opt_expr -keepdc
|
||||
|
||||
13.12. Executing OPT_EXPR pass (perform const folding).
|
||||
Optimizing module fifo.
|
||||
Optimizing module $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.
|
||||
|
||||
yosys> select -set new_cells t:$memrd
|
||||
|
||||
yosys> show -color maroon3 c:fifo_reader -color cornflowerblue @new_cells -notitle -format dot -prefix rdata_proc o:rdata %ci*
|
||||
|
||||
14. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_proc.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
||||
|
||||
yosys> flatten
|
||||
|
||||
15. Executing FLATTEN pass (flatten design).
|
||||
Deleting now unused module $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000.
|
||||
<suppressed ~2 debug messages>
|
||||
|
||||
yosys> clean
|
||||
Removed 3 unused cells and 25 unused wires.
|
||||
|
||||
yosys> select -set rdata_path o:rdata %ci*
|
||||
|
||||
yosys> select -set new_cells @rdata_path o:rdata %ci3 %d i:* %d
|
||||
|
||||
yosys> show -color maroon3 @new_cells -notitle -format dot -prefix rdata_flat @rdata_path
|
||||
|
||||
16. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_flat.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
||||
|
||||
yosys> opt_dff
|
||||
|
||||
17. Executing OPT_DFF pass (perform DFF optimizations).
|
||||
Adding EN signal on $procdff$55 ($adff) from module fifo (D = $0\count[8:0], Q = \count).
|
||||
Adding EN signal on $flatten\fifo_writer.$procdff$60 ($adff) from module fifo (D = $flatten\fifo_writer.$procmux$51_Y, Q = \fifo_writer.addr).
|
||||
Adding EN signal on $flatten\fifo_reader.$procdff$60 ($adff) from module fifo (D = $flatten\fifo_reader.$procmux$51_Y, Q = \fifo_reader.addr).
|
||||
|
||||
yosys> select -set new_cells t:$adffe
|
||||
|
||||
yosys> show -color maroon3 @new_cells -notitle -format dot -prefix rdata_adffe o:rdata %ci*
|
||||
|
||||
18. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_adffe.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
||||
|
||||
yosys> wreduce
|
||||
|
||||
19. Executing WREDUCE pass (reducing word size of cells).
|
||||
Removed top 31 bits (of 32) from port B of cell fifo.$add$fifo.v:66$27 ($add).
|
||||
Removed top 23 bits (of 32) from port Y of cell fifo.$add$fifo.v:66$27 ($add).
|
||||
Removed top 31 bits (of 32) from port B of cell fifo.$sub$fifo.v:68$30 ($sub).
|
||||
Removed top 23 bits (of 32) from port Y of cell fifo.$sub$fifo.v:68$30 ($sub).
|
||||
Removed top 1 bits (of 2) from port B of cell fifo.$auto$opt_dff.cc:195:make_patterns_logic$66 ($ne).
|
||||
Removed cell fifo.$flatten\fifo_writer.$procmux$53 ($mux).
|
||||
Removed top 31 bits (of 32) from port B of cell fifo.$flatten\fifo_writer.$add$fifo.v:19$34 ($add).
|
||||
Removed top 24 bits (of 32) from port Y of cell fifo.$flatten\fifo_writer.$add$fifo.v:19$34 ($add).
|
||||
Removed cell fifo.$flatten\fifo_reader.$procmux$53 ($mux).
|
||||
Removed top 31 bits (of 32) from port B of cell fifo.$flatten\fifo_reader.$add$fifo.v:19$34 ($add).
|
||||
Removed top 24 bits (of 32) from port Y of cell fifo.$flatten\fifo_reader.$add$fifo.v:19$34 ($add).
|
||||
Removed top 23 bits (of 32) from wire fifo.$add$fifo.v:66$27_Y.
|
||||
Removed top 24 bits (of 32) from wire fifo.$flatten\fifo_reader.$add$fifo.v:19$34_Y.
|
||||
|
||||
yosys> show -notitle -format dot -prefix rdata_wreduce o:rdata %ci*
|
||||
|
||||
20. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_wreduce.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
||||
|
||||
yosys> opt_clean
|
||||
|
||||
21. Executing OPT_CLEAN pass (remove unused cells and wires).
|
||||
Finding unused cells or wires in module \fifo..
|
||||
Removed 0 unused cells and 4 unused wires.
|
||||
<suppressed ~1 debug messages>
|
||||
|
||||
yosys> memory_dff
|
||||
|
||||
22. Executing MEMORY_DFF pass (merging $dff cells to $memrd).
|
||||
Checking read port `\data'[0] in module `\fifo': merging output FF to cell.
|
||||
Write port 0: non-transparent.
|
||||
|
||||
yosys> select -set new_cells t:$memrd_v2
|
||||
|
||||
yosys> show -color maroon3 @new_cells -notitle -format dot -prefix rdata_memrdv2 o:rdata %ci*
|
||||
|
||||
23. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_memrdv2.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
||||
|
||||
yosys> alumacc
|
||||
|
||||
24. Executing ALUMACC pass (create $alu and $macc cells).
|
||||
Extracting $alu and $macc cells in module fifo:
|
||||
creating $macc model for $add$fifo.v:66$27 ($add).
|
||||
creating $macc model for $flatten\fifo_reader.$add$fifo.v:19$34 ($add).
|
||||
creating $macc model for $flatten\fifo_writer.$add$fifo.v:19$34 ($add).
|
||||
creating $macc model for $sub$fifo.v:68$30 ($sub).
|
||||
creating $alu model for $macc $sub$fifo.v:68$30.
|
||||
creating $alu model for $macc $flatten\fifo_writer.$add$fifo.v:19$34.
|
||||
creating $alu model for $macc $flatten\fifo_reader.$add$fifo.v:19$34.
|
||||
creating $alu model for $macc $add$fifo.v:66$27.
|
||||
creating $alu cell for $add$fifo.v:66$27: $auto$alumacc.cc:485:replace_alu$80
|
||||
creating $alu cell for $flatten\fifo_reader.$add$fifo.v:19$34: $auto$alumacc.cc:485:replace_alu$83
|
||||
creating $alu cell for $flatten\fifo_writer.$add$fifo.v:19$34: $auto$alumacc.cc:485:replace_alu$86
|
||||
creating $alu cell for $sub$fifo.v:68$30: $auto$alumacc.cc:485:replace_alu$89
|
||||
created 4 $alu and 0 $macc cells.
|
||||
|
||||
yosys> select -set new_cells t:$alu t:$macc
|
||||
|
||||
yosys> show -color maroon3 @new_cells -notitle -format dot -prefix rdata_alumacc o:rdata %ci*
|
||||
|
||||
25. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_alumacc.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
||||
|
||||
yosys> memory_collect
|
||||
|
||||
26. Executing MEMORY_COLLECT pass (generating $mem cells).
|
||||
|
||||
yosys> select -set new_cells t:$mem_v2
|
||||
|
||||
yosys> select -set rdata_path @new_cells %ci*:-$mem_v2[WR_DATA,WR_ADDR,WR_EN] @new_cells %co* %%
|
||||
|
||||
yosys> show -color maroon3 @new_cells -notitle -format dot -prefix rdata_coarse @rdata_path
|
||||
|
||||
27. Generating Graphviz representation of design.
|
||||
Writing dot description to `rdata_coarse.dot'.
|
||||
Dumping selected parts of module fifo to page 1.
|
|
@ -1,57 +0,0 @@
|
|||
|
||||
yosys> stat
|
||||
|
||||
2. Printing statistics.
|
||||
|
||||
=== fifo ===
|
||||
|
||||
Number of wires: 28
|
||||
Number of wire bits: 219
|
||||
Number of public wires: 9
|
||||
Number of public wire bits: 45
|
||||
Number of memories: 1
|
||||
Number of memory bits: 2048
|
||||
Number of processes: 3
|
||||
Number of cells: 9
|
||||
$add 1
|
||||
$logic_and 2
|
||||
$logic_not 2
|
||||
$memrd 1
|
||||
$sub 1
|
||||
addr_gen 2
|
||||
|
||||
=== addr_gen ===
|
||||
|
||||
Number of wires: 8
|
||||
Number of wire bits: 60
|
||||
Number of public wires: 4
|
||||
Number of public wire bits: 11
|
||||
Number of memories: 0
|
||||
Number of memory bits: 0
|
||||
Number of processes: 2
|
||||
Number of cells: 2
|
||||
$add 1
|
||||
$eq 1
|
||||
|
||||
|
||||
yosys> stat -top fifo
|
||||
|
||||
17. Printing statistics.
|
||||
|
||||
=== fifo ===
|
||||
|
||||
Number of wires: 94
|
||||
Number of wire bits: 260
|
||||
Number of public wires: 94
|
||||
Number of public wire bits: 260
|
||||
Number of memories: 0
|
||||
Number of memory bits: 0
|
||||
Number of processes: 0
|
||||
Number of cells: 138
|
||||
$scopeinfo 2
|
||||
SB_CARRY 26
|
||||
SB_DFF 26
|
||||
SB_DFFER 25
|
||||
SB_LUT4 58
|
||||
SB_RAM40_4K 1
|
||||
|
|
@ -4,8 +4,10 @@ YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
|||
|
||||
DOTS = counter_00.dot counter_01.dot counter_02.dot counter_03.dot
|
||||
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: $(DOTS)
|
||||
examples:
|
||||
|
||||
$(DOTS): counter.v counter.ys mycells.lib
|
||||
$(YOSYS) counter.ys
|
||||
|
|
|
@ -4,8 +4,10 @@ YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
|||
|
||||
DOTS = macc_simple_xmap.dot macc_xilinx_xmap.dot
|
||||
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: $(DOTS)
|
||||
examples:
|
||||
|
||||
macc_simple_xmap.dot: macc_simple_*.v macc_simple_test.ys
|
||||
$(YOSYS) macc_simple_test.ys
|
||||
|
|
|
@ -6,13 +6,13 @@ DOT_NAMES = opt_share opt_muxtree opt_merge opt_expr
|
|||
|
||||
DOTS := $(addsuffix .dot,$(DOT_NAMES))
|
||||
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: $(DOTS)
|
||||
examples:
|
||||
|
||||
%_full.dot: %.ys
|
||||
%.dot: %.ys
|
||||
$(YOSYS) $<
|
||||
|
||||
%.dot: %_full.dot
|
||||
gvpack -u -o $@ $*_full.dot
|
||||
|
||||
.PHONY: clean
|
||||
|
|
|
@ -2,9 +2,10 @@ PROGRAM_PREFIX :=
|
|||
|
||||
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
||||
|
||||
.PHONY: all dots
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: scrambler_p01.dot scrambler_p02.dot
|
||||
examples:
|
||||
|
||||
scrambler_p01.dot scrambler_p02.dot: scrambler.ys scrambler.v
|
||||
$(YOSYS) scrambler.ys
|
||||
|
|
|
@ -11,14 +11,15 @@ MEMDEMO_DOTS := $(addsuffix .dot,$(MEMDEMO))
|
|||
SUBMOD = submod_00 submod_01 submod_02 submod_03
|
||||
SUBMOD_DOTS := $(addsuffix .dot,$(SUBMOD))
|
||||
|
||||
.PHONY: all dots
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: select.dot $(SUMPROD_DOTS) $(MEMDEMO_DOTS) $(SUBMOD_DOTS)
|
||||
examples: sumprod.out
|
||||
|
||||
select.dot: select.v select.ys
|
||||
$(YOSYS) select.ys
|
||||
|
||||
$(SUMPROD_DOTS): sumprod.v sumprod.ys
|
||||
$(SUMPROD_DOTS) sumprod.out: sumprod.v sumprod.ys
|
||||
$(YOSYS) sumprod.ys
|
||||
|
||||
$(MEMDEMO_DOTS): memdemo.v memdemo.ys
|
||||
|
@ -30,3 +31,4 @@ $(SUBMOD_DOTS): memdemo.v submod.ys
|
|||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.dot
|
||||
rm -f sumprod.out
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
|
||||
|
||||
attribute \src "sumprod.v:4.21-4.25"
|
||||
wire width 8 output 5 \prod
|
||||
|
||||
attribute \src "sumprod.v:10.17-10.26"
|
||||
cell $mul $mul$sumprod.v:10$4
|
||||
parameter \A_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_SIGNED 0
|
||||
parameter \B_WIDTH 8
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A $mul$sumprod.v:10$3_Y
|
||||
connect \B \c
|
||||
connect \Y \prod
|
||||
end
|
||||
|
||||
|
||||
attribute \src "sumprod.v:10.17-10.22"
|
||||
wire width 8 $mul$sumprod.v:10$3_Y
|
||||
|
||||
attribute \src "sumprod.v:3.21-3.22"
|
||||
wire width 8 input 3 \c
|
||||
|
||||
attribute \src "sumprod.v:4.21-4.25"
|
||||
wire width 8 output 5 \prod
|
||||
|
||||
attribute \src "sumprod.v:10.17-10.26"
|
||||
cell $mul $mul$sumprod.v:10$4
|
||||
parameter \A_SIGNED 0
|
||||
parameter \A_WIDTH 8
|
||||
parameter \B_SIGNED 0
|
||||
parameter \B_WIDTH 8
|
||||
parameter \Y_WIDTH 8
|
||||
connect \A $mul$sumprod.v:10$3_Y
|
||||
connect \B \c
|
||||
connect \Y \prod
|
||||
end
|
|
@ -8,9 +8,10 @@ EXAMPLE_DOTS := $(addsuffix .dot,$(EXAMPLE))
|
|||
CMOS = cmos_00 cmos_01
|
||||
CMOS_DOTS := $(addsuffix .dot,$(CMOS))
|
||||
|
||||
.PHONY: all dots
|
||||
all: dots example.out
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: splice.dot $(EXAMPLE_DOTS) $(CMOS_DOTS)
|
||||
examples: example.out
|
||||
|
||||
splice.dot: splice.v
|
||||
$(YOSYS) -p 'prep -top splice_demo; show -format dot -prefix splice' splice.v
|
||||
|
@ -27,3 +28,4 @@ $(CMOS_DOTS): cmos.v cmos.ys
|
|||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf *.dot
|
||||
rm -f example.out
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
|
||||
-- Executing script file `example_lscd.ys' --
|
||||
|
||||
1. Executing Verilog-2005 frontend: example.v
|
||||
Parsing Verilog input from `example.v' to AST representation.
|
||||
Generating RTLIL representation for module `\example'.
|
||||
Successfully finished Verilog frontend.
|
||||
echo on
|
||||
|
||||
yosys> ls
|
||||
|
||||
1 modules:
|
||||
example
|
||||
|
||||
yosys> cd example
|
||||
|
||||
yosys [example]> ls
|
||||
|
||||
8 wires:
|
||||
$0\y[1:0]
|
||||
$add$example.v:5$2_Y
|
||||
$ternary$example.v:5$3_Y
|
||||
a
|
||||
b
|
||||
c
|
||||
clk
|
||||
y
|
||||
|
||||
2 cells:
|
||||
$add$example.v:5$2
|
||||
$ternary$example.v:5$3
|
||||
|
||||
1 processes:
|
||||
$proc$example.v:3$1
|
||||
|
||||
yosys [example]> dump $2
|
||||
|
||||
|
||||
attribute \src "example.v:5.22-5.27"
|
||||
cell $add $add$example.v:5$2
|
||||
parameter \Y_WIDTH 2
|
||||
parameter \B_WIDTH 1
|
||||
parameter \A_WIDTH 1
|
||||
parameter \B_SIGNED 0
|
||||
parameter \A_SIGNED 0
|
||||
connect \Y $add$example.v:5$2_Y
|
||||
connect \B \b
|
||||
connect \A \a
|
||||
end
|
||||
|
||||
yosys [example]> cd ..
|
||||
|
||||
yosys> echo off
|
||||
echo off
|
|
@ -1,6 +1,7 @@
|
|||
.PHONY: all dots
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots:
|
||||
examples:
|
||||
|
||||
.PHONY: test
|
||||
test: stubnets.so
|
||||
|
|
|
@ -9,9 +9,10 @@ YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
|||
|
||||
DOTS = $(addsuffix .dot,$(DOT_TARGETS))
|
||||
|
||||
.PHONY: all dots
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: $(DOTS)
|
||||
examples:
|
||||
|
||||
%.dot: %.v %.ys
|
||||
$(YOSYS) -p 'script $*.ys; show -notitle -prefix $* -format dot'
|
||||
|
|
|
@ -2,9 +2,10 @@ PROGRAM_PREFIX :=
|
|||
|
||||
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
||||
|
||||
.PHONY: all dots
|
||||
all: dots
|
||||
.PHONY: all dots examples
|
||||
all: dots examples
|
||||
dots: red_or3x1.dot sym_mul.dot mymul.dot mulshift.dot addshift.dot
|
||||
examples:
|
||||
|
||||
red_or3x1.dot: red_or3x1_*
|
||||
$(YOSYS) red_or3x1_test.ys
|
||||
|
|
|
@ -1,46 +1,26 @@
|
|||
#!/usr/bin/env python3
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import os
|
||||
|
||||
project = 'YosysHQ Yosys'
|
||||
author = 'YosysHQ GmbH'
|
||||
copyright ='2024 YosysHQ GmbH'
|
||||
yosys_ver = "0.45"
|
||||
yosys_ver = "0.47"
|
||||
|
||||
# select HTML theme
|
||||
html_theme = 'furo'
|
||||
templates_path = ["_templates"]
|
||||
html_logo = '_static/logo.png'
|
||||
html_favicon = '_static/favico.png'
|
||||
html_css_files = ['yosyshq.css', 'custom.css']
|
||||
|
||||
html_theme_options = {
|
||||
"sidebar_hide_name": True,
|
||||
|
||||
"light_css_variables": {
|
||||
"color-brand-primary": "#d6368f",
|
||||
"color-brand-content": "#4b72b8",
|
||||
"color-api-name": "#8857a3",
|
||||
"color-api-pre-name": "#4b72b8",
|
||||
"color-link": "#8857a3",
|
||||
},
|
||||
|
||||
"dark_css_variables": {
|
||||
"color-brand-primary": "#e488bb",
|
||||
"color-brand-content": "#98bdff",
|
||||
"color-api-name": "#8857a3",
|
||||
"color-api-pre-name": "#4b72b8",
|
||||
"color-link": "#be95d5",
|
||||
},
|
||||
}
|
||||
html_theme = 'furo-ys'
|
||||
html_css_files = ['custom.css']
|
||||
|
||||
# These folders are copied to the documentation's HTML output
|
||||
html_static_path = ['_static', "_images"]
|
||||
|
||||
# code blocks style
|
||||
pygments_style = 'colorful'
|
||||
# default to no highlight
|
||||
highlight_language = 'none'
|
||||
|
||||
# default single quotes to attempt auto reference, or fallback to code
|
||||
default_role = 'autoref'
|
||||
|
||||
extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex']
|
||||
|
||||
if os.getenv("READTHEDOCS"):
|
||||
|
@ -97,9 +77,15 @@ latex_elements = {
|
|||
sys.path += [os.path.dirname(__file__) + "/../"]
|
||||
extensions.append('util.cmdref')
|
||||
|
||||
def setup(sphinx):
|
||||
from util.RtlilLexer import RtlilLexer
|
||||
sphinx.add_lexer("RTLIL", RtlilLexer)
|
||||
# use autodocs
|
||||
extensions.append('sphinx.ext.autodoc')
|
||||
extensions.append('util.cellref')
|
||||
cells_json = Path(__file__).parent / 'generated' / 'cells.json'
|
||||
|
||||
from util.YoscryptLexer import YoscryptLexer
|
||||
sphinx.add_lexer("yoscrypt", YoscryptLexer)
|
||||
from sphinx.application import Sphinx
|
||||
def setup(app: Sphinx) -> None:
|
||||
from util.RtlilLexer import RtlilLexer
|
||||
app.add_lexer("RTLIL", RtlilLexer)
|
||||
|
||||
from furo_ys.lexers.YoscryptLexer import YoscryptLexer
|
||||
app.add_lexer("yoscrypt", YoscryptLexer)
|
||||
|
|
|
@ -2,13 +2,12 @@ Synthesis starter
|
|||
-----------------
|
||||
|
||||
This page will be a guided walkthrough of the prepackaged iCE40 FPGA synthesis
|
||||
script - :cmd:ref:`synth_ice40`. We will take a simple design through each
|
||||
step, looking at the commands being called and what they do to the design. While
|
||||
:cmd:ref:`synth_ice40` is specific to the iCE40 platform, most of the operations
|
||||
we will be discussing are common across the majority of FPGA synthesis scripts.
|
||||
Thus, this document will provide a good foundational understanding of how
|
||||
synthesis in Yosys is performed, regardless of the actual architecture being
|
||||
used.
|
||||
script - `synth_ice40`. We will take a simple design through each step, looking
|
||||
at the commands being called and what they do to the design. While `synth_ice40`
|
||||
is specific to the iCE40 platform, most of the operations we will be discussing
|
||||
are common across the majority of FPGA synthesis scripts. Thus, this document
|
||||
will provide a good foundational understanding of how synthesis in Yosys is
|
||||
performed, regardless of the actual architecture being used.
|
||||
|
||||
.. seealso:: Advanced usage docs for
|
||||
:doc:`/using_yosys/synthesis/synth`
|
||||
|
@ -59,8 +58,8 @@ can run each of the commands individually for a better sense of how each part
|
|||
contributes to the flow. We will also start with just a single module;
|
||||
``addr_gen``.
|
||||
|
||||
At the bottom of the :cmd:ref:`help` output for
|
||||
:cmd:ref:`synth_ice40` is the complete list of commands called by this script.
|
||||
At the bottom of the `help` output for
|
||||
`synth_ice40` is the complete list of commands called by this script.
|
||||
Let's start with the section labeled ``begin``:
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
|
@ -105,10 +104,10 @@ Since we're just getting started, let's instead begin with :yoscrypt:`hierarchy
|
|||
|
||||
.. note::
|
||||
|
||||
:cmd:ref:`hierarchy` should always be the first command after the design has
|
||||
been read. By specifying the top module, :cmd:ref:`hierarchy` will also set
|
||||
the ``(* top *)`` attribute on it. This is used by other commands that need
|
||||
to know which module is the top.
|
||||
`hierarchy` should always be the first command after the design has been
|
||||
read. By specifying the top module, `hierarchy` will also set the ``(* top
|
||||
*)`` attribute on it. This is used by other commands that need to know which
|
||||
module is the top.
|
||||
|
||||
.. use doscon for a console-like display that supports the `yosys> [command]` format.
|
||||
|
||||
|
@ -125,24 +124,24 @@ Our ``addr_gen`` circuit now looks like this:
|
|||
:class: width-helper invert-helper
|
||||
:name: addr_gen_hier
|
||||
|
||||
``addr_gen`` module after :cmd:ref:`hierarchy`
|
||||
``addr_gen`` module after `hierarchy`
|
||||
|
||||
Simple operations like ``addr + 1`` and ``addr == MAX_DATA-1`` can be extracted
|
||||
from our ``always @`` block in :ref:`addr_gen-v`. This gives us the highlighted
|
||||
``$add`` and ``$eq`` cells we see. But control logic (like the ``if .. else``)
|
||||
and memory elements (like the ``addr <= 0``) are not so straightforward. These
|
||||
get put into "processes", shown in the schematic as ``PROC``. Note how the
|
||||
second line refers to the line numbers of the start/end of the corresponding
|
||||
``always @`` block. In the case of an ``initial`` block, we instead see the
|
||||
``PROC`` referring to line 0.
|
||||
`$add` and `$eq` cells we see. But control logic (like the ``if .. else``) and
|
||||
memory elements (like the ``addr <= 0``) are not so straightforward. These get
|
||||
put into "processes", shown in the schematic as ``PROC``. Note how the second
|
||||
line refers to the line numbers of the start/end of the corresponding ``always
|
||||
@`` block. In the case of an ``initial`` block, we instead see the ``PROC``
|
||||
referring to line 0.
|
||||
|
||||
To handle these, let us now introduce the next command: :doc:`/cmd/proc`.
|
||||
:cmd:ref:`proc` is a macro command like :cmd:ref:`synth_ice40`. Rather than
|
||||
modifying the design directly, it instead calls a series of other commands. In
|
||||
the case of :cmd:ref:`proc`, these sub-commands work to convert the behavioral
|
||||
logic of processes into multiplexers and registers. Let's see what happens when
|
||||
we run it. For now, we will call :yoscrypt:`proc -noopt` to prevent some
|
||||
automatic optimizations which would normally happen.
|
||||
To handle these, let us now introduce the next command: :doc:`/cmd/proc`. `proc`
|
||||
is a macro command like `synth_ice40`. Rather than modifying the design
|
||||
directly, it instead calls a series of other commands. In the case of `proc`,
|
||||
these sub-commands work to convert the behavioral logic of processes into
|
||||
multiplexers and registers. Let's see what happens when we run it. For now, we
|
||||
will call :yoscrypt:`proc -noopt` to prevent some automatic optimizations which
|
||||
would normally happen.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/addr_gen_proc.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -151,19 +150,18 @@ automatic optimizations which would normally happen.
|
|||
``addr_gen`` module after :yoscrypt:`proc -noopt`
|
||||
|
||||
There are now a few new cells from our ``always @``, which have been
|
||||
highlighted. The ``if`` statements are now modeled with ``$mux`` cells, while
|
||||
the register uses an ``$adff`` cell. If we look at the terminal output we can
|
||||
also see all of the different ``proc_*`` commands being called. We will look at
|
||||
each of these in more detail in :doc:`/using_yosys/synthesis/proc`.
|
||||
highlighted. The ``if`` statements are now modeled with `$mux` cells, while the
|
||||
register uses an `$adff` cell. If we look at the terminal output we can also
|
||||
see all of the different ``proc_*`` commands being called. We will look at each
|
||||
of these in more detail in :doc:`/using_yosys/synthesis/proc`.
|
||||
|
||||
Notice how in the top left of :ref:`addr_gen_proc` we have a floating wire,
|
||||
generated from the initial assignment of 0 to the ``addr`` wire. However, this
|
||||
initial assignment is not synthesizable, so this will need to be cleaned up
|
||||
before we can generate the physical hardware. We can do this now by calling
|
||||
:cmd:ref:`clean`. We're also going to call :cmd:ref:`opt_expr` now, which would
|
||||
normally be called at the end of :cmd:ref:`proc`. We can call both commands at
|
||||
the same time by separating them with a colon and space: :yoscrypt:`opt_expr;
|
||||
clean`.
|
||||
`clean`. We're also going to call `opt_expr` now, which would normally be
|
||||
called at the end of `proc`. We can call both commands at the same time by
|
||||
separating them with a colon and space: :yoscrypt:`opt_expr; clean`.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/addr_gen_clean.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -171,24 +169,24 @@ clean`.
|
|||
|
||||
``addr_gen`` module after :yoscrypt:`opt_expr; clean`
|
||||
|
||||
You may also notice that the highlighted ``$eq`` cell input of ``255`` has
|
||||
changed to ``8'11111111``. Constant values are presented in the format
|
||||
You may also notice that the highlighted `$eq` cell input of ``255`` has changed
|
||||
to ``8'11111111``. Constant values are presented in the format
|
||||
``<bit_width>'<bits>``, with 32-bit values instead using the decimal number.
|
||||
This indicates that the constant input has been reduced from 32-bit wide to
|
||||
8-bit wide. This is a side-effect of running :cmd:ref:`opt_expr`, which
|
||||
performs constant folding and simple expression rewriting. For more on why
|
||||
this happens, refer to :doc:`/using_yosys/synthesis/opt` and the :ref:`section
|
||||
on opt_expr <adv_opt_expr>`.
|
||||
8-bit wide. This is a side-effect of running `opt_expr`, which performs
|
||||
constant folding and simple expression rewriting. For more on why this
|
||||
happens, refer to :doc:`/using_yosys/synthesis/opt` and the :ref:`section on
|
||||
opt_expr <adv_opt_expr>`.
|
||||
|
||||
.. note::
|
||||
|
||||
:doc:`/cmd/clean` can also be called with two semicolons after any command,
|
||||
for example we could have called :yoscrypt:`opt_expr;;` instead of
|
||||
:yoscrypt:`opt_expr; clean`. You may notice some scripts will end each line
|
||||
with ``;;``. It is beneficial to run :cmd:ref:`clean` before inspecting
|
||||
intermediate products to remove disconnected parts of the circuit which have
|
||||
been left over, and in some cases can reduce the processing required in
|
||||
subsequent commands.
|
||||
with ``;;``. It is beneficial to run `clean` before inspecting intermediate
|
||||
products to remove disconnected parts of the circuit which have been left
|
||||
over, and in some cases can reduce the processing required in subsequent
|
||||
commands.
|
||||
|
||||
.. todo:: consider a brief glossary for terms like adff
|
||||
|
||||
|
@ -202,8 +200,8 @@ The full example
|
|||
|
||||
Let's now go back and check on our full design by using :yoscrypt:`hierarchy
|
||||
-check -top fifo`. By passing the ``-check`` option there we are also telling
|
||||
the :cmd:ref:`hierarchy` command that if the design includes any non-blackbox
|
||||
modules without an implementation it should return an error.
|
||||
the `hierarchy` command that if the design includes any non-blackbox modules
|
||||
without an implementation it should return an error.
|
||||
|
||||
Note that if we tried to run this command now then we would get an error. This
|
||||
is because we already removed all of the modules other than ``addr_gen``. We
|
||||
|
@ -218,18 +216,17 @@ could restart our shell session, but instead let's use two new commands:
|
|||
:end-before: yosys> proc
|
||||
:caption: reloading :file:`fifo.v` and running :yoscrypt:`hierarchy -check -top fifo`
|
||||
|
||||
Notice how this time we didn't see any of those `$abstract` modules? That's
|
||||
Notice how this time we didn't see any of those ``$abstract`` modules? That's
|
||||
because when we ran ``yosys fifo.v``, the first command Yosys called was
|
||||
:yoscrypt:`read_verilog -defer fifo.v`. The ``-defer`` option there tells
|
||||
:cmd:ref:`read_verilog` only read the abstract syntax tree and defer actual
|
||||
compilation to a later :cmd:ref:`hierarchy` command. This is useful in cases
|
||||
where the default parameters of modules yield invalid code which is not
|
||||
synthesizable. This is why Yosys defers compilation automatically and is one of
|
||||
the reasons why hierarchy should always be the first command after loading the
|
||||
design. If we know that our design won't run into this issue, we can skip the
|
||||
``-defer``.
|
||||
`read_verilog` only read the abstract syntax tree and defer actual compilation
|
||||
to a later `hierarchy` command. This is useful in cases where the default
|
||||
parameters of modules yield invalid code which is not synthesizable. This is why
|
||||
Yosys defers compilation automatically and is one of the reasons why hierarchy
|
||||
should always be the first command after loading the design. If we know that
|
||||
our design won't run into this issue, we can skip the ``-defer``.
|
||||
|
||||
.. todo:: :cmd:ref:`hierarchy` failure modes
|
||||
.. todo:: `hierarchy` failure modes
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -243,19 +240,19 @@ design. If we know that our design won't run into this issue, we can skip the
|
|||
interactive terminal. :kbd:`ctrl+c` (i.e. SIGINT) will also end the terminal
|
||||
session but will return an error code rather than exiting gracefully.
|
||||
|
||||
We can also run :cmd:ref:`proc` now to finish off the full :ref:`synth_begin`.
|
||||
Because the design schematic is quite large, we will be showing just the data
|
||||
path for the ``rdata`` output. If you would like to see the entire design for
|
||||
yourself, you can do so with :doc:`/cmd/show`. Note that the :cmd:ref:`show`
|
||||
command only works with a single module, so you may need to call it with
|
||||
:yoscrypt:`show fifo`. :ref:`show_intro` section in
|
||||
:doc:`/getting_started/scripting_intro` has more on how to use :cmd:ref:`show`.
|
||||
We can also run `proc` now to finish off the full :ref:`synth_begin`. Because
|
||||
the design schematic is quite large, we will be showing just the data path for
|
||||
the ``rdata`` output. If you would like to see the entire design for yourself,
|
||||
you can do so with :doc:`/cmd/show`. Note that the `show` command only works
|
||||
with a single module, so you may need to call it with :yoscrypt:`show fifo`.
|
||||
:ref:`show_intro` section in :doc:`/getting_started/scripting_intro` has more on
|
||||
how to use `show`.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_proc.*
|
||||
:class: width-helper invert-helper
|
||||
:name: rdata_proc
|
||||
|
||||
``rdata`` output after :cmd:ref:`proc`
|
||||
``rdata`` output after `proc`
|
||||
|
||||
The highlighted ``fifo_reader`` block contains an instance of the
|
||||
:ref:`addr_gen_proc` that we looked at earlier. Notice how the type is shown as
|
||||
|
@ -263,10 +260,10 @@ The highlighted ``fifo_reader`` block contains an instance of the
|
|||
instance of the ``addr_gen`` module with the ``MAX_DATA`` parameter set to the
|
||||
given value.
|
||||
|
||||
The other highlighted block is a ``$memrd`` cell. At this stage of synthesis we
|
||||
The other highlighted block is a `$memrd` cell. At this stage of synthesis we
|
||||
don't yet know what type of memory is going to be implemented, but we *do* know
|
||||
that ``rdata <= data[raddr];`` could be implemented as a read from memory. Note
|
||||
that the ``$memrd`` cell here is asynchronous, with both the clock and enable
|
||||
that the `$memrd` cell here is asynchronous, with both the clock and enable
|
||||
signal undefined; shown with the ``1'x`` inputs.
|
||||
|
||||
.. seealso:: Advanced usage docs for
|
||||
|
@ -276,7 +273,7 @@ Flattening
|
|||
~~~~~~~~~~
|
||||
|
||||
At this stage of a synthesis flow there are a few other commands we could run.
|
||||
In :cmd:ref:`synth_ice40` we get these:
|
||||
In `synth_ice40` we get these:
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -286,7 +283,7 @@ In :cmd:ref:`synth_ice40` we get these:
|
|||
:name: synth_flatten
|
||||
:caption: ``flatten`` section
|
||||
|
||||
First off is :cmd:ref:`flatten`. Flattening the design like this can allow for
|
||||
First off is `flatten`. Flattening the design like this can allow for
|
||||
optimizations between modules which would otherwise be missed. Let's run
|
||||
:yoscrypt:`flatten;;` on our design.
|
||||
|
||||
|
@ -309,23 +306,22 @@ optimizations between modules which would otherwise be missed. Let's run
|
|||
The pieces have moved around a bit, but we can see :ref:`addr_gen_proc` from
|
||||
earlier has replaced the ``fifo_reader`` block in :ref:`rdata_proc`. We can
|
||||
also see that the ``addr`` output has been renamed to :file:`fifo_reader.addr`
|
||||
and merged with the ``raddr`` wire feeding into the ``$memrd`` cell. This wire
|
||||
merging happened during the call to :cmd:ref:`clean` which we can see in the
|
||||
and merged with the ``raddr`` wire feeding into the `$memrd` cell. This wire
|
||||
merging happened during the call to `clean` which we can see in the
|
||||
:ref:`flat_clean`.
|
||||
|
||||
.. note::
|
||||
|
||||
:cmd:ref:`flatten` and :cmd:ref:`clean` would normally be combined into a
|
||||
`flatten` and `clean` would normally be combined into a
|
||||
single :yoterm:`yosys> flatten;;` output, but they appear separately here as
|
||||
a side effect of using :cmd:ref:`echo` for generating the terminal style
|
||||
a side effect of using `echo` for generating the terminal style
|
||||
output.
|
||||
|
||||
Depending on the target architecture, this stage of synthesis might also see
|
||||
commands such as :cmd:ref:`tribuf` with the ``-logic`` option and
|
||||
:cmd:ref:`deminout`. These remove tristate and inout constructs respectively,
|
||||
replacing them with logic suitable for mapping to an FPGA. Since we do not have
|
||||
any such constructs in our example running these commands does not change our
|
||||
design.
|
||||
commands such as `tribuf` with the ``-logic`` option and `deminout`. These
|
||||
remove tristate and inout constructs respectively, replacing them with logic
|
||||
suitable for mapping to an FPGA. Since we do not have any such constructs in
|
||||
our example running these commands does not change our design.
|
||||
|
||||
The coarse-grain representation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -342,9 +338,9 @@ optimizations and other transformations done previously.
|
|||
|
||||
.. note::
|
||||
|
||||
While the iCE40 flow had a :ref:`synth_flatten` and put :cmd:ref:`proc` in
|
||||
the :ref:`synth_begin`, some synthesis scripts will instead include these in
|
||||
this section.
|
||||
While the iCE40 flow had a :ref:`synth_flatten` and put `proc` in the
|
||||
:ref:`synth_begin`, some synthesis scripts will instead include these in this
|
||||
section.
|
||||
|
||||
Part 1
|
||||
^^^^^^
|
||||
|
@ -359,36 +355,35 @@ In the iCE40 flow, we start with the following commands:
|
|||
:caption: ``coarse`` section (part 1)
|
||||
:name: synth_coarse1
|
||||
|
||||
We've already come across :cmd:ref:`opt_expr`, and :cmd:ref:`opt_clean` is the
|
||||
same as :cmd:ref:`clean` but with more verbose output. The :cmd:ref:`check`
|
||||
pass identifies a few obvious problems which will cause errors later. Calling
|
||||
it here lets us fail faster rather than wasting time on something we know is
|
||||
impossible.
|
||||
We've already come across `opt_expr`, and `opt_clean` is the same as `clean` but
|
||||
with more verbose output. The `check` pass identifies a few obvious problems
|
||||
which will cause errors later. Calling it here lets us fail faster rather than
|
||||
wasting time on something we know is impossible.
|
||||
|
||||
Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple
|
||||
optimizations on the design. This command also ensures that only a specific
|
||||
subset of FF types are included, in preparation for the next command:
|
||||
:doc:`/cmd/fsm`. Both :cmd:ref:`opt` and :cmd:ref:`fsm` are macro commands
|
||||
which are explored in more detail in :doc:`/using_yosys/synthesis/opt` and
|
||||
:doc:`/cmd/fsm`. Both `opt` and `fsm` are macro commands which are explored in
|
||||
more detail in :doc:`/using_yosys/synthesis/opt` and
|
||||
:doc:`/using_yosys/synthesis/fsm` respectively.
|
||||
|
||||
Up until now, the data path for ``rdata`` has remained the same since
|
||||
:ref:`rdata_flat`. However the next call to :cmd:ref:`opt` does cause a change.
|
||||
Specifically, the call to :cmd:ref:`opt_dff` without the ``-nodffe -nosdff``
|
||||
options is able to fold one of the ``$mux`` cells into the ``$adff`` to form an
|
||||
``$adffe`` cell; highlighted below:
|
||||
:ref:`rdata_flat`. However the next call to `opt` does cause a change.
|
||||
Specifically, the call to `opt_dff` without the ``-nodffe -nosdff`` options is
|
||||
able to fold one of the `$mux` cells into the `$adff` to form an `$adffe` cell;
|
||||
highlighted below:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.out
|
||||
:language: doscon
|
||||
:start-at: yosys> opt_dff
|
||||
:end-before: yosys> select
|
||||
:caption: output of :cmd:ref:`opt_dff`
|
||||
:caption: output of `opt_dff`
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_adffe.*
|
||||
:class: width-helper invert-helper
|
||||
:name: rdata_adffe
|
||||
|
||||
``rdata`` output after :cmd:ref:`opt_dff`
|
||||
``rdata`` output after `opt_dff`
|
||||
|
||||
.. seealso:: Advanced usage docs for
|
||||
|
||||
|
@ -414,27 +409,27 @@ First up is :doc:`/cmd/wreduce`. If we run this we get the following:
|
|||
:language: doscon
|
||||
:start-at: yosys> wreduce
|
||||
:end-before: yosys> select
|
||||
:caption: output of :cmd:ref:`wreduce`
|
||||
:caption: output of `wreduce`
|
||||
|
||||
Looking at the data path for ``rdata``, the most relevant of these width
|
||||
reductions are the ones affecting ``fifo.$flatten\fifo_reader.$add$fifo.v``.
|
||||
That is the ``$add`` cell incrementing the fifo_reader address. We can look at
|
||||
That is the `$add` cell incrementing the fifo_reader address. We can look at
|
||||
the schematic and see the output of that cell has now changed.
|
||||
|
||||
.. todo:: pending bugfix in :cmd:ref:`wreduce` and/or :cmd:ref:`opt_clean`
|
||||
.. todo:: pending bugfix in `wreduce` and/or `opt_clean`
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_wreduce.*
|
||||
:class: width-helper invert-helper
|
||||
:name: rdata_wreduce
|
||||
|
||||
``rdata`` output after :cmd:ref:`wreduce`
|
||||
``rdata`` output after `wreduce`
|
||||
|
||||
The next two (new) commands are :doc:`/cmd/peepopt` and :doc:`/cmd/share`.
|
||||
Neither of these affect our design, and they're explored in more detail in
|
||||
:doc:`/using_yosys/synthesis/opt`, so let's skip over them. :yoscrypt:`techmap
|
||||
-map +/cmp2lut.v -D LUT_WIDTH=4` optimizes certain comparison operators by
|
||||
converting them to LUTs instead. The usage of :cmd:ref:`techmap` is explored
|
||||
more in :doc:`/using_yosys/synthesis/techmap_synth`.
|
||||
converting them to LUTs instead. The usage of `techmap` is explored more in
|
||||
:doc:`/using_yosys/synthesis/techmap_synth`.
|
||||
|
||||
Our next command to run is
|
||||
:doc:`/cmd/memory_dff`.
|
||||
|
@ -443,17 +438,17 @@ Our next command to run is
|
|||
:language: doscon
|
||||
:start-at: yosys> memory_dff
|
||||
:end-before: yosys> select
|
||||
:caption: output of :cmd:ref:`memory_dff`
|
||||
:caption: output of `memory_dff`
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_memrdv2.*
|
||||
:class: width-helper invert-helper
|
||||
:name: rdata_memrdv2
|
||||
|
||||
``rdata`` output after :cmd:ref:`memory_dff`
|
||||
``rdata`` output after `memory_dff`
|
||||
|
||||
As the title suggests, :cmd:ref:`memory_dff` has merged the output ``$dff`` into
|
||||
the ``$memrd`` cell and converted it to a ``$memrd_v2`` (highlighted). This has
|
||||
also connected the ``CLK`` port to the ``clk`` input as it is now a synchronous
|
||||
As the title suggests, `memory_dff` has merged the output `$dff` into the
|
||||
`$memrd` cell and converted it to a `$memrd_v2` (highlighted). This has also
|
||||
connected the ``CLK`` port to the ``clk`` input as it is now a synchronous
|
||||
memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and
|
||||
``SRST=1'0``) inputs.
|
||||
|
||||
|
@ -466,12 +461,11 @@ memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and
|
|||
Part 3
|
||||
^^^^^^
|
||||
|
||||
The third part of the :cmd:ref:`synth_ice40` flow is a series of commands for
|
||||
mapping to DSPs. By default, the iCE40 flow will not map to the hardware DSP
|
||||
blocks and will only be performed if called with the ``-dsp`` flag:
|
||||
:yoscrypt:`synth_ice40 -dsp`. While our example has nothing that could be
|
||||
mapped to DSPs we can still take a quick look at the commands here and describe
|
||||
what they do.
|
||||
The third part of the `synth_ice40` flow is a series of commands for mapping to
|
||||
DSPs. By default, the iCE40 flow will not map to the hardware DSP blocks and
|
||||
will only be performed if called with the ``-dsp`` flag: :yoscrypt:`synth_ice40
|
||||
-dsp`. While our example has nothing that could be mapped to DSPs we can still
|
||||
take a quick look at the commands here and describe what they do.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -482,29 +476,27 @@ what they do.
|
|||
:name: synth_coarse3
|
||||
|
||||
:yoscrypt:`wreduce t:$mul` performs width reduction again, this time targetting
|
||||
only cells of type ``$mul``. :yoscrypt:`techmap -map +/mul2dsp.v -map
|
||||
+/ice40/dsp_map.v ... -D DSP_NAME=$__MUL16X16` uses :cmd:ref:`techmap` to map
|
||||
``$mul`` cells to ``$__MUL16X16`` which are, in turn, mapped to the iCE40
|
||||
``SB_MAC16``. Any multipliers which aren't compatible with conversion to
|
||||
``$__MUL16X16`` are relabelled to ``$__soft_mul`` before :cmd:ref:`chtype`
|
||||
changes them back to ``$mul``.
|
||||
only cells of type `$mul`. :yoscrypt:`techmap -map +/mul2dsp.v -map
|
||||
+/ice40/dsp_map.v ... -D DSP_NAME=$__MUL16X16` uses `techmap` to map `$mul`
|
||||
cells to ``$__MUL16X16`` which are, in turn, mapped to the iCE40 ``SB_MAC16``.
|
||||
Any multipliers which aren't compatible with conversion to ``$__MUL16X16`` are
|
||||
relabelled to ``$__soft_mul`` before `chtype` changes them back to `$mul`.
|
||||
|
||||
During the mul2dsp conversion, some of the intermediate signals are marked with
|
||||
the attribute ``mul2dsp``. By calling :yoscrypt:`select a:mul2dsp` we restrict
|
||||
the following commands to only operate on the cells and wires used for these
|
||||
signals. :cmd:ref:`setattr` removes the now unnecessary ``mul2dsp`` attribute.
|
||||
:cmd:ref:`opt_expr` we've already come across for const folding and simple
|
||||
expression rewriting, the ``-fine`` option just enables more fine-grain
|
||||
optimizations. Then we perform width reduction a final time and clear the
|
||||
selection.
|
||||
signals. `setattr` removes the now unnecessary ``mul2dsp`` attribute.
|
||||
`opt_expr` we've already come across for const folding and simple expression
|
||||
rewriting, the ``-fine`` option just enables more fine-grain optimizations.
|
||||
Then we perform width reduction a final time and clear the selection.
|
||||
|
||||
.. todo:: ``ice40_dsp`` is pmgen
|
||||
|
||||
Finally we have :cmd:ref:`ice40_dsp`: similar to the :cmd:ref:`memory_dff`
|
||||
command we saw in the previous section, this merges any surrounding registers
|
||||
into the ``SB_MAC16`` cell. This includes not just the input/output registers,
|
||||
but also pipeline registers and even a post-adder where applicable: turning a
|
||||
multiply + add into a single multiply-accumulate.
|
||||
Finally we have `ice40_dsp`: similar to the `memory_dff` command we saw in the
|
||||
previous section, this merges any surrounding registers into the ``SB_MAC16``
|
||||
cell. This includes not just the input/output registers, but also pipeline
|
||||
registers and even a post-adder where applicable: turning a multiply + add into
|
||||
a single multiply-accumulate.
|
||||
|
||||
.. seealso:: Advanced usage docs for
|
||||
:doc:`/using_yosys/synthesis/techmap_synth`
|
||||
|
@ -522,44 +514,43 @@ That brings us to the fourth and final part for the iCE40 synthesis flow:
|
|||
:caption: ``coarse`` section (part 4)
|
||||
:name: synth_coarse4
|
||||
|
||||
Where before each type of arithmetic operation had its own cell, e.g. ``$add``,
|
||||
we now want to extract these into ``$alu`` and ``$macc`` cells which can help
|
||||
identify opportunities for reusing logic. We do this by running
|
||||
:cmd:ref:`alumacc`, which we can see produce the following changes in our
|
||||
example design:
|
||||
Where before each type of arithmetic operation had its own cell, e.g. `$add`, we
|
||||
now want to extract these into `$alu` and `$macc` cells which can help identify
|
||||
opportunities for reusing logic. We do this by running `alumacc`, which we can
|
||||
see produce the following changes in our example design:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.out
|
||||
:language: doscon
|
||||
:start-at: yosys> alumacc
|
||||
:end-before: yosys> select
|
||||
:caption: output of :cmd:ref:`alumacc`
|
||||
:caption: output of `alumacc`
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_alumacc.*
|
||||
:class: width-helper invert-helper
|
||||
:name: rdata_alumacc
|
||||
|
||||
``rdata`` output after :cmd:ref:`alumacc`
|
||||
``rdata`` output after `alumacc`
|
||||
|
||||
Once these cells have been inserted, the call to :cmd:ref:`opt` can combine
|
||||
cells which are now identical but may have been missed due to e.g. the
|
||||
difference between ``$add`` and ``$sub``.
|
||||
Once these cells have been inserted, the call to `opt` can combine cells which
|
||||
are now identical but may have been missed due to e.g. the difference between
|
||||
`$add` and `$sub`.
|
||||
|
||||
The other new command in this part is :doc:`/cmd/memory`. :cmd:ref:`memory` is
|
||||
another macro command which we examine in more detail in
|
||||
The other new command in this part is :doc:`/cmd/memory`. `memory` is another
|
||||
macro command which we examine in more detail in
|
||||
:doc:`/using_yosys/synthesis/memory`. For this document, let us focus just on
|
||||
the step most relevant to our example: :cmd:ref:`memory_collect`. Up until this
|
||||
point, our memory reads and our memory writes have been totally disjoint cells;
|
||||
operating on the same memory only in the abstract. :cmd:ref:`memory_collect`
|
||||
combines all of the reads and writes for a memory block into a single cell.
|
||||
the step most relevant to our example: `memory_collect`. Up until this point,
|
||||
our memory reads and our memory writes have been totally disjoint cells;
|
||||
operating on the same memory only in the abstract. `memory_collect` combines all
|
||||
of the reads and writes for a memory block into a single cell.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_coarse.*
|
||||
:class: width-helper invert-helper
|
||||
:name: rdata_coarse
|
||||
|
||||
``rdata`` output after :cmd:ref:`memory_collect`
|
||||
``rdata`` output after `memory_collect`
|
||||
|
||||
Looking at the schematic after running :cmd:ref:`memory_collect` we see that our
|
||||
``$memrd_v2`` cell has been replaced with a ``$mem_v2`` cell named ``data``, the
|
||||
Looking at the schematic after running `memory_collect` we see that our
|
||||
`$memrd_v2` cell has been replaced with a `$mem_v2` cell named ``data``, the
|
||||
same name that we used in :ref:`fifo-v`. Where before we had a single set of
|
||||
signals for address and enable, we now have one set for reading (``RD_*``) and
|
||||
one for writing (``WR_*``), as well as both ``WR_DATA`` input and ``RD_DATA``
|
||||
|
@ -592,8 +583,8 @@ If you skipped calling :yoscrypt:`read_verilog -D ICE40_HX -lib -specify
|
|||
Memory blocks
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Mapping to hard memory blocks uses a combination of :cmd:ref:`memory_libmap` and
|
||||
:cmd:ref:`techmap`.
|
||||
Mapping to hard memory blocks uses a combination of `memory_libmap` and
|
||||
`techmap`.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -609,28 +600,28 @@ Mapping to hard memory blocks uses a combination of :cmd:ref:`memory_libmap` and
|
|||
|
||||
``rdata`` output after :ref:`map_ram`
|
||||
|
||||
The :ref:`map_ram` converts the generic ``$mem_v2`` into the iCE40
|
||||
``SB_RAM40_4K`` (highlighted). We can also see the memory address has been
|
||||
remapped, and the data bits have been reordered (or swizzled). There is also
|
||||
now a ``$mux`` cell controlling the value of ``rdata``. In :ref:`fifo-v` we
|
||||
wrote our memory as read-before-write, however the ``SB_RAM40_4K`` has undefined
|
||||
behaviour when reading from and writing to the same address in the same cycle.
|
||||
As a result, extra logic is added so that the generated circuit matches the
|
||||
behaviour of the verilog. :ref:`no_rw_check` describes how we could change our
|
||||
verilog to match our hardware instead.
|
||||
The :ref:`map_ram` converts the generic `$mem_v2` into the iCE40 ``SB_RAM40_4K``
|
||||
(highlighted). We can also see the memory address has been remapped, and the
|
||||
data bits have been reordered (or swizzled). There is also now a `$mux` cell
|
||||
controlling the value of ``rdata``. In :ref:`fifo-v` we wrote our memory as
|
||||
read-before-write, however the ``SB_RAM40_4K`` has undefined behaviour when
|
||||
reading from and writing to the same address in the same cycle. As a result,
|
||||
extra logic is added so that the generated circuit matches the behaviour of the
|
||||
verilog. :ref:`no_rw_check` describes how we could change our verilog to match
|
||||
our hardware instead.
|
||||
|
||||
If we run :cmd:ref:`memory_libmap` under the :cmd:ref:`debug` command we can see
|
||||
candidates which were identified for mapping, along with the costs of each and
|
||||
what logic requires emulation.
|
||||
If we run `memory_libmap` under the `debug` command we can see candidates which
|
||||
were identified for mapping, along with the costs of each and what logic
|
||||
requires emulation.
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.libmap
|
||||
:language: doscon
|
||||
:lines: 2, 6-
|
||||
|
||||
The ``$__ICE40_RAM4K_`` cell is defined in the file |techlibs/ice40/brams.txt|_,
|
||||
with the mapping to ``SB_RAM40_4K`` done by :cmd:ref:`techmap` using
|
||||
with the mapping to ``SB_RAM40_4K`` done by `techmap` using
|
||||
|techlibs/ice40/brams_map.v|_. Any leftover memory cells are then converted
|
||||
into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`.
|
||||
into flip flops (the ``logic fallback``) with `memory_map`.
|
||||
|
||||
.. |techlibs/ice40/brams.txt| replace:: :file:`techlibs/ice40/brams.txt`
|
||||
.. _techlibs/ice40/brams.txt: https://github.com/YosysHQ/yosys/tree/main/techlibs/ice40/brams.txt
|
||||
|
@ -654,8 +645,8 @@ into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`.
|
|||
.. note::
|
||||
|
||||
The visual clutter on the ``RDATA`` output port (highlighted) is an
|
||||
unfortunate side effect of :cmd:ref:`opt_clean` on the swizzled data bits. In
|
||||
connecting the ``$mux`` input port directly to ``RDATA`` to reduce the number
|
||||
unfortunate side effect of `opt_clean` on the swizzled data bits. In
|
||||
connecting the `$mux` input port directly to ``RDATA`` to reduce the number
|
||||
of wires, the ``$techmap579\data.0.0.RDATA`` wire becomes more visually
|
||||
complex.
|
||||
|
||||
|
@ -667,11 +658,10 @@ into flip flops (the ``logic fallback``) with :cmd:ref:`memory_map`.
|
|||
Arithmetic
|
||||
^^^^^^^^^^
|
||||
|
||||
Uses :cmd:ref:`techmap` to map basic arithmetic logic to hardware. This sees
|
||||
somewhat of an explosion in cells as multi-bit ``$mux`` and ``$adffe`` are
|
||||
replaced with single-bit ``$_MUX_`` and ``$_DFFE_PP0P_`` cells, while the
|
||||
``$alu`` is replaced with primitive ``$_OR_`` and ``$_NOT_`` gates and a
|
||||
``$lut`` cell.
|
||||
Uses `techmap` to map basic arithmetic logic to hardware. This sees somewhat of
|
||||
an explosion in cells as multi-bit `$mux` and `$adffe` are replaced with
|
||||
single-bit `$_MUX_` and `$_DFFE_PP0P_` cells, while the `$alu` is replaced with
|
||||
primitive `$_OR_` and `$_NOT_` gates and a `$lut` cell.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -693,14 +683,14 @@ replaced with single-bit ``$_MUX_`` and ``$_DFFE_PP0P_`` cells, while the
|
|||
Flip-flops
|
||||
^^^^^^^^^^
|
||||
|
||||
Convert FFs to the types supported in hardware with :cmd:ref:`dfflegalize`, and
|
||||
then use :cmd:ref:`techmap` to map them. In our example, this converts the
|
||||
``$_DFFE_PP0P_`` cells to ``SB_DFFER``.
|
||||
Convert FFs to the types supported in hardware with `dfflegalize`, and then use
|
||||
`techmap` to map them. In our example, this converts the `$_DFFE_PP0P_` cells
|
||||
to ``SB_DFFER``.
|
||||
|
||||
We also run :cmd:ref:`simplemap` here to convert any remaining cells which could
|
||||
not be mapped to hardware into gate-level primitives. This includes optimizing
|
||||
``$_MUX_`` cells where one of the inputs is a constant ``1'0``, replacing it
|
||||
instead with an ``$_AND_`` cell.
|
||||
We also run `simplemap` here to convert any remaining cells which could not be
|
||||
mapped to hardware into gate-level primitives. This includes optimizing
|
||||
`$_MUX_` cells where one of the inputs is a constant ``1'0``, replacing it
|
||||
instead with an `$_AND_` cell.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -722,11 +712,10 @@ instead with an ``$_AND_`` cell.
|
|||
LUTs
|
||||
^^^^
|
||||
|
||||
:cmd:ref:`abc` and :cmd:ref:`techmap` are used to map LUTs; converting primitive
|
||||
cell types to use ``$lut`` and ``SB_CARRY`` cells. Note that the iCE40 flow
|
||||
uses :cmd:ref:`abc9` rather than :cmd:ref:`abc`. For more on what these do, and
|
||||
what the difference between these two commands are, refer to
|
||||
:doc:`/using_yosys/synthesis/abc`.
|
||||
`abc` and `techmap` are used to map LUTs; converting primitive cell types to use
|
||||
`$lut` and ``SB_CARRY`` cells. Note that the iCE40 flow uses `abc9` rather than
|
||||
`abc`. For more on what these do, and what the difference between these two
|
||||
commands are, refer to :doc:`/using_yosys/synthesis/abc`.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -742,8 +731,8 @@ what the difference between these two commands are, refer to
|
|||
|
||||
``rdata`` output after :ref:`map_luts`
|
||||
|
||||
Finally we use :cmd:ref:`techmap` to map the generic ``$lut`` cells to iCE40
|
||||
``SB_LUT4`` cells.
|
||||
Finally we use `techmap` to map the generic `$lut` cells to iCE40 ``SB_LUT4``
|
||||
cells.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -769,12 +758,12 @@ Other cells
|
|||
|
||||
The following commands may also be used for mapping other cells:
|
||||
|
||||
:cmd:ref:`hilomap`
|
||||
`hilomap`
|
||||
Some architectures require special driver cells for driving a constant hi or
|
||||
lo value. This command replaces simple constants with instances of such
|
||||
driver cells.
|
||||
|
||||
:cmd:ref:`iopadmap`
|
||||
`iopadmap`
|
||||
Top-level input/outputs must usually be implemented using special I/O-pad
|
||||
cells. This command inserts such cells to the design.
|
||||
|
||||
|
@ -801,28 +790,27 @@ The new commands here are:
|
|||
- :doc:`/cmd/stat`, and
|
||||
- :doc:`/cmd/blackbox`.
|
||||
|
||||
The output from :cmd:ref:`stat` is useful for checking resource utilization;
|
||||
providing a list of cells used in the design and the number of each, as well as
|
||||
the number of other resources used such as wires and processes. For this
|
||||
design, the final call to :cmd:ref:`stat` should look something like the
|
||||
following:
|
||||
The output from `stat` is useful for checking resource utilization; providing a
|
||||
list of cells used in the design and the number of each, as well as the number
|
||||
of other resources used such as wires and processes. For this design, the final
|
||||
call to `stat` should look something like the following:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.stat
|
||||
:language: doscon
|
||||
:start-at: yosys> stat -top fifo
|
||||
|
||||
Note that the :yoscrypt:`-top fifo` here is optional. :cmd:ref:`stat` will
|
||||
automatically use the module with the ``top`` attribute set, which ``fifo`` was
|
||||
when we called :cmd:ref:`hierarchy`. If no module is marked ``top``, then stats
|
||||
will be shown for each module selected.
|
||||
Note that the :yoscrypt:`-top fifo` here is optional. `stat` will automatically
|
||||
use the module with the ``top`` attribute set, which ``fifo`` was when we called
|
||||
`hierarchy`. If no module is marked ``top``, then stats will be shown for each
|
||||
module selected.
|
||||
|
||||
The :cmd:ref:`stat` output is also useful as a kind of sanity-check: Since we
|
||||
have already run :cmd:ref:`proc`, we wouldn't expect there to be any processes.
|
||||
We also expect ``data`` to use hard memory; if instead of an ``SB_RAM40_4K`` saw
|
||||
a high number of flip-flops being used we might suspect something was wrong.
|
||||
The `stat` output is also useful as a kind of sanity-check: Since we have
|
||||
already run `proc`, we wouldn't expect there to be any processes. We also expect
|
||||
``data`` to use hard memory; if instead of an ``SB_RAM40_4K`` saw a high number
|
||||
of flip-flops being used we might suspect something was wrong.
|
||||
|
||||
If we instead called :cmd:ref:`stat` immediately after :yoscrypt:`read_verilog
|
||||
fifo.v` we would see something very different:
|
||||
If we instead called `stat` immediately after :yoscrypt:`read_verilog fifo.v` we
|
||||
would see something very different:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.stat
|
||||
:language: doscon
|
||||
|
@ -845,10 +833,10 @@ The iCE40 synthesis flow has the following output modes available:
|
|||
|
||||
As an example, if we called :yoscrypt:`synth_ice40 -top fifo -json fifo.json`,
|
||||
our synthesized ``fifo`` design will be output as :file:`fifo.json`. We can
|
||||
then read the design back into Yosys with :cmd:ref:`read_json`, but make sure
|
||||
you use :yoscrypt:`design -reset` or open a new interactive terminal first. The
|
||||
JSON output we get can also be loaded into `nextpnr`_ to do place and route; but
|
||||
that is beyond the scope of this documentation.
|
||||
then read the design back into Yosys with `read_json`, but make sure you use
|
||||
:yoscrypt:`design -reset` or open a new interactive terminal first. The JSON
|
||||
output we get can also be loaded into `nextpnr`_ to do place and route; but that
|
||||
is beyond the scope of this documentation.
|
||||
|
||||
.. _nextpnr: https://github.com/YosysHQ/nextpnr
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ A C++ compiler with C++17 support is required as well as some standard tools
|
|||
such as GNU Flex, GNU Bison, Make and Python. Some additional tools: readline,
|
||||
libffi, Tcl and zlib; are optional but enabled by default (see
|
||||
:makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the
|
||||
:cmd:ref:`show` command to display schematics.
|
||||
`show` command to display schematics.
|
||||
|
||||
Installing all prerequisites for Ubuntu 20.04:
|
||||
|
||||
|
@ -109,7 +109,7 @@ Installing all prerequisites for macOS 11 (with Homebrew):
|
|||
Running the build system
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
From the root `yosys` directory, call the following commands:
|
||||
From the root ``yosys`` directory, call the following commands:
|
||||
|
||||
.. code:: console
|
||||
|
||||
|
@ -117,7 +117,7 @@ From the root `yosys` directory, call the following commands:
|
|||
sudo make install
|
||||
|
||||
This will build and then install Yosys, making it available on the command line
|
||||
as `yosys`. Note that this also downloads, builds, and installs `ABC`_ (using
|
||||
as ``yosys``. Note that this also downloads, builds, and installs `ABC`_ (using
|
||||
:program:`yosys-abc` as the executable name).
|
||||
|
||||
.. _ABC: https://github.com/berkeley-abc/abc
|
||||
|
@ -184,9 +184,8 @@ directories:
|
|||
|
||||
``passes/``
|
||||
This directory contains a subdirectory for each pass or group of passes. For
|
||||
example as of this writing the directory :file:`passes/hierarchy/` contains the
|
||||
code for three passes: :cmd:ref:`hierarchy`, :cmd:ref:`submod`, and
|
||||
:cmd:ref:`uniquify`.
|
||||
example as of this writing the directory :file:`passes/hierarchy/` contains
|
||||
the code for three passes: `hierarchy`, `submod`, and `uniquify`.
|
||||
|
||||
``techlibs/``
|
||||
This directory contains simulation models and standard implementations for
|
||||
|
|
|
@ -7,8 +7,7 @@ file format and how you can make your own synthesis scripts.
|
|||
|
||||
Yosys script files typically use the :file:`.ys` extension and contain a set of
|
||||
commands for Yosys to run sequentially. These commands are the same ones we
|
||||
were using on the previous page like :cmd:ref:`read_verilog` and
|
||||
:cmd:ref:`hierarchy`.
|
||||
were using on the previous page like `read_verilog` and `hierarchy`.
|
||||
|
||||
Script parsing
|
||||
~~~~~~~~~~~~~~
|
||||
|
@ -39,9 +38,9 @@ Another special character that can be used in Yosys scripts is the bang ``!``.
|
|||
Anything after the bang will be executed as a shell command. This can only be
|
||||
terminated with a new line. Any semicolons, hashes, or other special characters
|
||||
will be passed to the shell. If an error code is returned from the shell it
|
||||
will be raised by Yosys. :cmd:ref:`exec` provides a much more flexible way of
|
||||
executing commands, allowing the output to be logged and more control over when
|
||||
to generate errors.
|
||||
will be raised by Yosys. `exec` provides a much more flexible way of executing
|
||||
commands, allowing the output to be logged and more control over when to
|
||||
generate errors.
|
||||
|
||||
The synthesis starter script
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -62,24 +61,23 @@ already, let's take a look at some of those script files now.
|
|||
:caption: A section of :file:`fifo.ys`, generating the images used for :ref:`addr_gen_example`
|
||||
:name: fifo-ys
|
||||
|
||||
The first command there, :yoscrypt:`echo on`, uses :cmd:ref:`echo` to enable
|
||||
command echoes on. This is how we generated the code listing for
|
||||
The first command there, :yoscrypt:`echo on`, uses `echo` to enable command
|
||||
echoes on. This is how we generated the code listing for
|
||||
:ref:`hierarchy_output`. Turning command echoes on prints the ``yosys>
|
||||
hierarchy -top addr_gen`` line, making the output look the same as if it were an
|
||||
interactive terminal. :yoscrypt:`hierarchy -top addr_gen` is of course the
|
||||
command we were demonstrating, including the output text and an image of the
|
||||
design schematic after running it.
|
||||
|
||||
We briefly touched on :cmd:ref:`select` when it came up in
|
||||
:cmd:ref:`synth_ice40`, but let's look at it more now.
|
||||
We briefly touched on `select` when it came up in `synth_ice40`, but let's look
|
||||
at it more now.
|
||||
|
||||
.. _select_intro:
|
||||
|
||||
Selections intro
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
The :cmd:ref:`select` command is used to modify and view the list of selected
|
||||
objects:
|
||||
The `select` command is used to modify and view the list of selected objects:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.out
|
||||
:language: doscon
|
||||
|
@ -99,7 +97,7 @@ signifies we are matching on the *cell type*, and the ``*`` means to match
|
|||
anything. For this (very simple) selection, we are trying to find all of the
|
||||
cells, regardless of their type. The active selection is now shown as
|
||||
``[addr_gen]*``, indicating some sub-selection of the ``addr_gen`` module. This
|
||||
gives us the ``$add`` and ``$eq`` cells, which we want to highlight for the
|
||||
gives us the `$add` and `$eq` cells, which we want to highlight for the
|
||||
:ref:`addr_gen_hier` image.
|
||||
|
||||
.. _select_new_cells:
|
||||
|
@ -111,15 +109,16 @@ by referring to it as ``@new_cells``, which we will see later. Then we clear
|
|||
the selection so that the following commands can operate on the full design.
|
||||
While we split that out for this document, we could have done the same thing in
|
||||
a single line by calling :yoscrypt:`select -set new_cells addr_gen/t:*`. If we
|
||||
know we only have the one module in our design, we can even skip the `addr_gen/`
|
||||
part. Looking further down :ref:`the fifo.ys code <fifo-ys>` we can see this
|
||||
with :yoscrypt:`select -set new_cells t:$mux t:*dff`. We can also see in that
|
||||
command that selections don't have to be limited to a single statement.
|
||||
know we only have the one module in our design, we can even skip the
|
||||
``addr_gen/`` part. Looking further down :ref:`the fifo.ys code <fifo-ys>` we
|
||||
can see this with :yoscrypt:`select -set new_cells t:$mux t:*dff`. We can also
|
||||
see in that command that selections don't have to be limited to a single
|
||||
statement.
|
||||
|
||||
Many commands also support an optional ``[selection]`` argument which can be
|
||||
used to override the currently selected objects. We could, for example, call
|
||||
:yoscrypt:`clean addr_gen` to have :cmd:ref:`clean` operate on *just* the
|
||||
``addr_gen`` module.
|
||||
:yoscrypt:`clean addr_gen` to have `clean` operate on *just* the ``addr_gen``
|
||||
module.
|
||||
|
||||
Detailed documentation of the select framework can be found under
|
||||
:doc:`/using_yosys/more_scripting/selections` or in the command reference at
|
||||
|
@ -130,23 +129,23 @@ Detailed documentation of the select framework can be found under
|
|||
Displaying schematics
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
While the :cmd:ref:`select` command is very useful, sometimes nothing beats
|
||||
being able to see a design for yourself. This is where :cmd:ref:`show` comes
|
||||
in. Note that this document is just an introduction to the :cmd:ref:`show`
|
||||
command, only covering the basics. For more information, including a guide on
|
||||
what the different symbols represent, see :ref:`interactive_show` and the
|
||||
While the `select` command is very useful, sometimes nothing beats being able to
|
||||
see a design for yourself. This is where `show` comes in. Note that this
|
||||
document is just an introduction to the `show` command, only covering the
|
||||
basics. For more information, including a guide on what the different symbols
|
||||
represent, see :ref:`interactive_show` and the
|
||||
:doc:`/using_yosys/more_scripting/interactive_investigation` page.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/addr_gen_show.*
|
||||
:class: width-helper invert-helper
|
||||
:name: addr_gen_show
|
||||
|
||||
Calling :yoscrypt:`show addr_gen` after :cmd:ref:`hierarchy`
|
||||
Calling :yoscrypt:`show addr_gen` after `hierarchy`
|
||||
|
||||
.. note::
|
||||
|
||||
The :cmd:ref:`show` command requires a working installation of `GraphViz`_
|
||||
and `xdot`_ for displaying the actual circuit diagrams.
|
||||
The `show` command requires a working installation of `GraphViz`_ and `xdot`_
|
||||
for displaying the actual circuit diagrams.
|
||||
|
||||
.. _GraphViz: http://www.graphviz.org/
|
||||
.. _xdot: https://github.com/jrfonseca/xdot.py
|
||||
|
@ -160,8 +159,8 @@ we see the following:
|
|||
:start-at: -prefix addr_gen_show
|
||||
:end-before: yosys> show
|
||||
|
||||
Calling :cmd:ref:`show` with :yoscrypt:`-format dot` tells it we want to output
|
||||
a :file:`.dot` file rather than opening it for display. The :yoscrypt:`-prefix
|
||||
Calling `show` with :yoscrypt:`-format dot` tells it we want to output a
|
||||
:file:`.dot` file rather than opening it for display. The :yoscrypt:`-prefix
|
||||
addr_gen_show` option indicates we want the file to be called
|
||||
:file:`addr_gen_show.{*}`. Remember, we do this in :file:`fifo.ys` because we
|
||||
need to store the image for displaying in the documentation you're reading. But
|
||||
|
@ -184,8 +183,8 @@ like when we called :yoscrypt:`select -module addr_gen` in :ref:`select_intro`.
|
|||
That last parameter doesn't have to be a module name, it can be any valid
|
||||
selection string. Remember when we :ref:`assigned a name to a
|
||||
selection<select_new_cells>` and called it ``new_cells``? We saw in the
|
||||
:yoscrypt:`select -list` output that it contained two cells, an ``$add`` and an
|
||||
``$eq``. We can call :cmd:ref:`show` on that selection just as easily:
|
||||
:yoscrypt:`select -list` output that it contained two cells, an `$add` and an
|
||||
`$eq`. We can call `show` on that selection just as easily:
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/new_cells_show.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -207,21 +206,20 @@ the two ``PROC`` blocks. To achieve this highlight, we make use of the
|
|||
|
||||
Calling :yoscrypt:`show -color maroon3 @new_cells -color cornflowerblue p:* -notitle`
|
||||
|
||||
As described in the the :cmd:ref:`help` output for :cmd:ref:`show` (or by
|
||||
clicking on the :cmd:ref:`show` link), colors are specified as :yoscrypt:`-color
|
||||
<color> <object>`. Color names for the ``<color>`` portion can be found on the
|
||||
`GraphViz color docs`_. Unlike the final :cmd:ref:`show` parameter which can
|
||||
have be any selection string, the ``<object>`` part must be a single selection
|
||||
expression or named selection. That means while we can use ``@new_cells``, we
|
||||
couldn't use ``t:$eq t:$add``. In general, if a command lists ``[selection]``
|
||||
as its final parameter it can be any selection string. Any selections that are
|
||||
not the final parameter, such as those used in options, must be a single
|
||||
expression instead.
|
||||
As described in the the `help` output for `show` (or by clicking on the `show`
|
||||
link), colors are specified as :yoscrypt:`-color <color> <object>`. Color names
|
||||
for the ``<color>`` portion can be found on the `GraphViz color docs`_. Unlike
|
||||
the final `show` parameter which can have be any selection string, the
|
||||
``<object>`` part must be a single selection expression or named selection.
|
||||
That means while we can use ``@new_cells``, we couldn't use ``t:$eq t:$add``.
|
||||
In general, if a command lists ``[selection]`` as its final parameter it can be
|
||||
any selection string. Any selections that are not the final parameter, such as
|
||||
those used in options, must be a single expression instead.
|
||||
|
||||
.. _GraphViz color docs: https://graphviz.org/doc/info/colors
|
||||
|
||||
For all of the options available to :cmd:ref:`show`, check the command reference
|
||||
at :doc:`/cmd/show`.
|
||||
For all of the options available to `show`, check the command reference at
|
||||
:doc:`/cmd/show`.
|
||||
|
||||
.. seealso:: :ref:`interactive_show` on the
|
||||
:doc:`/using_yosys/more_scripting/interactive_investigation` page.
|
||||
|
|
|
@ -23,22 +23,32 @@ available, go to :ref:`commandindex`.
|
|||
- Search bar with live drop down suggestions for matching on title /
|
||||
autocompleting commands
|
||||
- Scroll the left sidebar to the current location on page load
|
||||
- Also the formatting/linking in pdf is broken
|
||||
- Also the formatting in pdf uses link formatting instead of code formatting
|
||||
|
||||
.. todolist::
|
||||
|
||||
.. only:: html
|
||||
|
||||
Table of contents
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:includehidden:
|
||||
|
||||
Yosys (index) <self>
|
||||
introduction
|
||||
|
||||
getting_started/index
|
||||
using_yosys/index
|
||||
yosys_internals/index
|
||||
|
||||
appendix
|
||||
.. toctree::
|
||||
:caption: Appendix
|
||||
:titlesonly:
|
||||
:includehidden:
|
||||
|
||||
appendix/primer
|
||||
appendix/rtlil_text
|
||||
appendix/auxlibs
|
||||
appendix/auxprogs
|
||||
|
||||
bib
|
||||
|
||||
cell_index
|
||||
cmd_ref
|
||||
|
|
|
@ -161,9 +161,9 @@ Benefits of open source HDL synthesis
|
|||
|
||||
- Cost (also applies to ``free as in free beer`` solutions):
|
||||
|
||||
Today the cost for a mask set in 180nm technology is far less than
|
||||
the cost for the design tools needed to design the mask layouts. Open Source
|
||||
ASIC flows are an important enabler for ASIC-level Open Source Hardware.
|
||||
Today the cost for a mask set in 180nm technology is far less than the cost
|
||||
for the design tools needed to design the mask layouts. Open Source ASIC flows
|
||||
are an important enabler for ASIC-level Open Source Hardware.
|
||||
|
||||
- Availability and Reproducibility:
|
||||
|
||||
|
@ -171,21 +171,23 @@ Benefits of open source HDL synthesis
|
|||
else can also use. Even if most universities have access to all major
|
||||
commercial tools, you usually do not have easy access to the version that was
|
||||
used in a research project a couple of years ago. With Open Source tools you
|
||||
can even release the source code of the tool you have used alongside your data.
|
||||
can even release the source code of the tool you have used alongside your
|
||||
data.
|
||||
|
||||
- Framework:
|
||||
|
||||
Yosys is not only a tool. It is a framework that can be used as basis for other
|
||||
developments, so researchers and hackers alike do not need to re-invent the
|
||||
basic functionality. Extensibility was one of Yosys' design goals.
|
||||
Yosys is not only a tool. It is a framework that can be used as basis for
|
||||
other developments, so researchers and hackers alike do not need to re-invent
|
||||
the basic functionality. Extensibility was one of Yosys' design goals.
|
||||
|
||||
- All-in-one:
|
||||
|
||||
Because of the framework characteristics of Yosys, an increasing number of features
|
||||
become available in one tool. Yosys not only can be used for circuit synthesis but
|
||||
also for formal equivalence checking, SAT solving, and for circuit analysis, to
|
||||
name just a few other application domains. With proprietary software one needs to
|
||||
learn a new tool for each of these applications.
|
||||
Because of the framework characteristics of Yosys, an increasing number of
|
||||
features become available in one tool. Yosys not only can be used for circuit
|
||||
synthesis but also for formal equivalence checking, SAT solving, and for
|
||||
circuit analysis, to name just a few other application domains. With
|
||||
proprietary software one needs to learn a new tool for each of these
|
||||
applications.
|
||||
|
||||
- Educational Tool:
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
furo
|
||||
furo-ys @ git+https://github.com/YosysHQ/furo-ys
|
||||
sphinxcontrib-bibtex
|
||||
rtds-action
|
||||
|
|
|
@ -13,9 +13,9 @@ A look at the show command
|
|||
|
||||
.. TODO:: merge into :doc:`/getting_started/scripting_intro` show section
|
||||
|
||||
This section explores the :cmd:ref:`show` command and explains the symbols used
|
||||
in the circuit diagrams generated by it. The code used is included in the Yosys
|
||||
code base under |code_examples/show|_.
|
||||
This section explores the `show` command and explains the symbols used in the
|
||||
circuit diagrams generated by it. The code used is included in the Yosys code
|
||||
base under |code_examples/show|_.
|
||||
|
||||
.. |code_examples/show| replace:: :file:`docs/source/code_examples/show`
|
||||
.. _code_examples/show: https://github.com/YosysHQ/yosys/tree/main/docs/source/code_examples/show
|
||||
|
@ -24,7 +24,7 @@ A simple circuit
|
|||
^^^^^^^^^^^^^^^^
|
||||
|
||||
:ref:`example_v` below provides the Verilog code for a simple circuit which we
|
||||
will use to demonstrate the usage of :cmd:ref:`show` in a simple setting.
|
||||
will use to demonstrate the usage of `show` in a simple setting.
|
||||
|
||||
.. literalinclude:: /code_examples/show/example.v
|
||||
:language: Verilog
|
||||
|
@ -32,11 +32,10 @@ will use to demonstrate the usage of :cmd:ref:`show` in a simple setting.
|
|||
:name: example_v
|
||||
|
||||
The Yosys synthesis script we will be running is included as
|
||||
:numref:`example_ys`. Note that :cmd:ref:`show` is called with the ``-pause``
|
||||
option, that halts execution of the Yosys script until the user presses the
|
||||
Enter key. Using :yoscrypt:`show -pause` also allows the user to enter an
|
||||
interactive shell to further investigate the circuit before continuing
|
||||
synthesis.
|
||||
:numref:`example_ys`. Note that `show` is called with the ``-pause`` option,
|
||||
that halts execution of the Yosys script until the user presses the Enter key.
|
||||
Using :yoscrypt:`show -pause` also allows the user to enter an interactive shell
|
||||
to further investigate the circuit before continuing synthesis.
|
||||
|
||||
.. literalinclude:: /code_examples/show/example_show.ys
|
||||
:language: yoscrypt
|
||||
|
@ -58,7 +57,7 @@ is shown.
|
|||
.. figure:: /_images/code_examples/show/example_first.*
|
||||
:class: width-helper invert-helper
|
||||
|
||||
Output of the first :cmd:ref:`show` command in :numref:`example_ys`
|
||||
Output of the first `show` command in :numref:`example_ys`
|
||||
|
||||
The first output shows the design directly after being read by the Verilog
|
||||
front-end. Input and output ports are displayed as octagonal shapes. Cells are
|
||||
|
@ -66,7 +65,7 @@ displayed as rectangles with inputs on the left and outputs on the right side.
|
|||
The cell labels are two lines long: The first line contains a unique identifier
|
||||
for the cell and the second line contains the cell type. Internal cell types are
|
||||
prefixed with a dollar sign. For more details on the internal cell library, see
|
||||
:doc:`/yosys_internals/formats/cell_library`.
|
||||
:doc:`/cell_index`.
|
||||
|
||||
Constants are shown as ellipses with the constant value as label. The syntax
|
||||
``<bit_width>'<bits>`` is used for constants that are not 32-bit wide and/or
|
||||
|
@ -81,43 +80,43 @@ internal representation of the decision-trees and synchronization events
|
|||
modelled in a Verilog ``always``-block. The label reads ``PROC`` followed by a
|
||||
unique identifier in the first line and contains the source code location of the
|
||||
original ``always``-block in the second line. Note how the multiplexer from the
|
||||
``?:``-expression is represented as a ``$mux`` cell but the multiplexer from the
|
||||
``?:``-expression is represented as a `$mux` cell but the multiplexer from the
|
||||
``if``-statement is yet still hidden within the process.
|
||||
|
||||
The :cmd:ref:`proc` command transforms the process from the first diagram into a
|
||||
The `proc` command transforms the process from the first diagram into a
|
||||
multiplexer and a d-type flip-flop, which brings us to the second diagram:
|
||||
|
||||
.. figure:: /_images/code_examples/show/example_second.*
|
||||
:class: width-helper invert-helper
|
||||
|
||||
Output of the second :cmd:ref:`show` command in :numref:`example_ys`
|
||||
Output of the second `show` command in :numref:`example_ys`
|
||||
|
||||
The Rhombus shape to the right is a dangling wire. (Wire nodes are only shown if
|
||||
they are dangling or have "public" names, for example names assigned from the
|
||||
Verilog input.) Also note that the design now contains two instances of a
|
||||
``BUF``-node. These are artefacts left behind by the :cmd:ref:`proc` command. It
|
||||
is quite usual to see such artefacts after calling commands that perform changes
|
||||
in the design, as most commands only care about doing the transformation in the
|
||||
least complicated way, not about cleaning up after them. The next call to
|
||||
:cmd:ref:`clean` (or :cmd:ref:`opt`, which includes :cmd:ref:`clean` as one of
|
||||
its operations) will clean up these artefacts. This operation is so common in
|
||||
Yosys scripts that it can simply be abbreviated with the ``;;`` token, which
|
||||
doubles as separator for commands. Unless one wants to specifically analyze this
|
||||
artefacts left behind some operations, it is therefore recommended to always
|
||||
call :cmd:ref:`clean` before calling :cmd:ref:`show`.
|
||||
``BUF``-node. These are artefacts left behind by the `proc` command. It is quite
|
||||
usual to see such artefacts after calling commands that perform changes in the
|
||||
design, as most commands only care about doing the transformation in the least
|
||||
complicated way, not about cleaning up after them. The next call to `clean` (or
|
||||
`opt`, which includes `clean` as one of its operations) will clean up these
|
||||
artefacts. This operation is so common in Yosys scripts that it can simply be
|
||||
abbreviated with the ``;;`` token, which doubles as separator for commands.
|
||||
Unless one wants to specifically analyze this artefacts left behind some
|
||||
operations, it is therefore recommended to always call `clean` before calling
|
||||
`show`.
|
||||
|
||||
In this script we directly call :cmd:ref:`opt` as the next step, which finally
|
||||
leads us to the third diagram:
|
||||
In this script we directly call `opt` as the next step, which finally leads us
|
||||
to the third diagram:
|
||||
|
||||
.. figure:: /_images/code_examples/show/example_third.*
|
||||
:class: width-helper invert-helper
|
||||
:name: example_out
|
||||
|
||||
Output of the third :cmd:ref:`show` command in :ref:`example_ys`
|
||||
Output of the third `show` command in :ref:`example_ys`
|
||||
|
||||
Here we see that the :cmd:ref:`opt` command not only has removed the artifacts
|
||||
left behind by :cmd:ref:`proc`, but also determined correctly that it can remove
|
||||
the first ``$mux`` cell without changing the behavior of the circuit.
|
||||
Here we see that the `opt` command not only has removed the artifacts left
|
||||
behind by `proc`, but also determined correctly that it can remove the first
|
||||
`$mux` cell without changing the behavior of the circuit.
|
||||
|
||||
Break-out boxes for signal vectors
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -129,7 +128,7 @@ accesses.
|
|||
:caption: :file:`splice.v`
|
||||
:name: splice_src
|
||||
|
||||
Notice how the output for this circuit from the :cmd:ref:`show` command
|
||||
Notice how the output for this circuit from the `show` command
|
||||
(:numref:`splice_dia`) appears quite complex. This is an unfortunate side effect
|
||||
of the way Yosys handles signal vectors (aka. multi-bit wires or buses) as
|
||||
native objects. While this provides great advantages when analyzing circuits
|
||||
|
@ -169,7 +168,7 @@ mapped to a cell library:
|
|||
:name: first_pitfall
|
||||
|
||||
A half-adder built from simple CMOS gates, demonstrating common pitfalls when
|
||||
using :cmd:ref:`show`
|
||||
using `show`
|
||||
|
||||
.. literalinclude:: /code_examples/show/cmos.ys
|
||||
:language: yoscrypt
|
||||
|
@ -188,8 +187,8 @@ individual bits, resulting in an unnecessary complex diagram.
|
|||
:class: width-helper invert-helper
|
||||
:name: second_pitfall
|
||||
|
||||
Effects of :cmd:ref:`splitnets` command and of providing a cell library on
|
||||
design in :numref:`first_pitfall`
|
||||
Effects of `splitnets` command and of providing a cell library on design in
|
||||
:numref:`first_pitfall`
|
||||
|
||||
.. literalinclude:: /code_examples/show/cmos.ys
|
||||
:language: yoscrypt
|
||||
|
@ -201,11 +200,11 @@ individual bits, resulting in an unnecessary complex diagram.
|
|||
For :numref:`second_pitfall`, Yosys has been given a description of the cell
|
||||
library as Verilog file containing blackbox modules. There are two ways to load
|
||||
cell descriptions into Yosys: First the Verilog file for the cell library can be
|
||||
passed directly to the :cmd:ref:`show` command using the ``-lib <filename>``
|
||||
option. Secondly it is possible to load cell libraries into the design with the
|
||||
passed directly to the `show` command using the ``-lib <filename>`` option.
|
||||
Secondly it is possible to load cell libraries into the design with the
|
||||
:yoscrypt:`read_verilog -lib <filename>` command. The second method has the
|
||||
great advantage that the library only needs to be loaded once and can then be
|
||||
used in all subsequent calls to the :cmd:ref:`show` command.
|
||||
used in all subsequent calls to the `show` command.
|
||||
|
||||
In addition to that, :numref:`second_pitfall` was generated after
|
||||
:yoscrypt:`splitnet -ports` was run on the design. This command splits all
|
||||
|
@ -216,22 +215,22 @@ module ports. Per default the command only operates on interior signals.
|
|||
Miscellaneous notes
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Per default the :cmd:ref:`show` command outputs a temporary dot file and
|
||||
launches ``xdot`` to display it. The options ``-format``, ``-viewer`` and
|
||||
``-prefix`` can be used to change format, viewer and filename prefix. Note that
|
||||
the ``pdf`` and ``ps`` format are the only formats that support plotting
|
||||
multiple modules in one run. The ``dot`` format can be used to output multiple
|
||||
modules, however ``xdot`` will raise an error when trying to read them.
|
||||
Per default the `show` command outputs a temporary dot file and launches
|
||||
``xdot`` to display it. The options ``-format``, ``-viewer`` and ``-prefix`` can
|
||||
be used to change format, viewer and filename prefix. Note that the ``pdf`` and
|
||||
``ps`` format are the only formats that support plotting multiple modules in one
|
||||
run. The ``dot`` format can be used to output multiple modules, however
|
||||
``xdot`` will raise an error when trying to read them.
|
||||
|
||||
In densely connected circuits it is sometimes hard to keep track of the
|
||||
individual signal wires. For these cases it can be useful to call
|
||||
:cmd:ref:`show` with the ``-colors <integer>`` argument, which randomly assigns
|
||||
colors to the nets. The integer (> 0) is used as seed value for the random color
|
||||
assignments. Sometimes it is necessary it try some values to find an assignment
|
||||
of colors that looks good.
|
||||
individual signal wires. For these cases it can be useful to call `show` with
|
||||
the ``-colors <integer>`` argument, which randomly assigns colors to the nets.
|
||||
The integer (> 0) is used as seed value for the random color assignments.
|
||||
Sometimes it is necessary it try some values to find an assignment of colors
|
||||
that looks good.
|
||||
|
||||
The command :yoscrypt:`help show` prints a complete listing of all options
|
||||
supported by the :cmd:ref:`show` command.
|
||||
supported by the `show` command.
|
||||
|
||||
Navigating the design
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -244,10 +243,10 @@ relevant portions of the circuit.
|
|||
In addition to *what* to display one also needs to carefully decide *when* to
|
||||
display it, with respect to the synthesis flow. In general it is a good idea to
|
||||
troubleshoot a circuit in the earliest state in which a problem can be
|
||||
reproduced. So if, for example, the internal state before calling the
|
||||
:cmd:ref:`techmap` command already fails to verify, it is better to troubleshoot
|
||||
the coarse-grain version of the circuit before :cmd:ref:`techmap` than the
|
||||
gate-level circuit after :cmd:ref:`techmap`.
|
||||
reproduced. So if, for example, the internal state before calling the `techmap`
|
||||
command already fails to verify, it is better to troubleshoot the coarse-grain
|
||||
version of the circuit before `techmap` than the gate-level circuit after
|
||||
`techmap`.
|
||||
|
||||
.. Note::
|
||||
|
||||
|
@ -260,31 +259,29 @@ Interactive navigation
|
|||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once the right state within the synthesis flow for debugging the circuit has
|
||||
been identified, it is recommended to simply add the :cmd:ref:`shell` command to
|
||||
the matching place in the synthesis script. This command will stop the synthesis
|
||||
at the specified moment and go to shell mode, where the user can interactively
|
||||
been identified, it is recommended to simply add the `shell` command to the
|
||||
matching place in the synthesis script. This command will stop the synthesis at
|
||||
the specified moment and go to shell mode, where the user can interactively
|
||||
enter commands.
|
||||
|
||||
For most cases, the shell will start with the whole design selected (i.e. when
|
||||
the synthesis script does not already narrow the selection). The command
|
||||
:cmd:ref:`ls` can now be used to create a list of all modules. The command
|
||||
:cmd:ref:`cd` can be used to switch to one of the modules (type ``cd ..`` to
|
||||
switch back). Now the :cmd:ref:`ls` command lists the objects within that
|
||||
module. This is demonstrated below using :file:`example.v` from `A simple
|
||||
circuit`_:
|
||||
the synthesis script does not already narrow the selection). The command `ls`
|
||||
can now be used to create a list of all modules. The command `cd` can be used to
|
||||
switch to one of the modules (type ``cd ..`` to switch back). Now the `ls`
|
||||
command lists the objects within that module. This is demonstrated below using
|
||||
:file:`example.v` from `A simple circuit`_:
|
||||
|
||||
.. literalinclude:: /code_examples/show/example.out
|
||||
:language: doscon
|
||||
:start-at: yosys> ls
|
||||
:end-before: yosys [example]> dump
|
||||
:caption: Output of :cmd:ref:`ls` and :cmd:ref:`cd` after running :file:`yosys example.v`
|
||||
:caption: Output of `ls` and `cd` after running :file:`yosys example.v`
|
||||
:name: lscd
|
||||
|
||||
When a module is selected using the :cmd:ref:`cd` command, all commands (with a
|
||||
few exceptions, such as the ``read_`` and ``write_`` commands) operate only on
|
||||
the selected module. This can also be useful for synthesis scripts where
|
||||
different synthesis strategies should be applied to different modules in the
|
||||
design.
|
||||
When a module is selected using the `cd` command, all commands (with a few
|
||||
exceptions, such as the ``read_`` and ``write_`` commands) operate only on the
|
||||
selected module. This can also be useful for synthesis scripts where different
|
||||
synthesis strategies should be applied to different modules in the design.
|
||||
|
||||
We can see that the cell names from :numref:`example_out` are just abbreviations
|
||||
of the actual cell names, namely the part after the last dollar-sign. Most
|
||||
|
@ -292,15 +289,14 @@ auto-generated names (the ones starting with a dollar sign) are rather long and
|
|||
contains some additional information on the origin of the named object. But in
|
||||
most cases those names can simply be abbreviated using the last part.
|
||||
|
||||
Usually all interactive work is done with one module selected using the
|
||||
:cmd:ref:`cd` command. But it is also possible to work from the design-context
|
||||
(``cd ..``). In this case all object names must be prefixed with
|
||||
``<module_name>/``. For example ``a*/b*`` would refer to all objects whose names
|
||||
start with ``b`` from all modules whose names start with ``a``.
|
||||
Usually all interactive work is done with one module selected using the `cd`
|
||||
command. But it is also possible to work from the design-context (``cd ..``). In
|
||||
this case all object names must be prefixed with ``<module_name>/``. For example
|
||||
``a*/b*`` would refer to all objects whose names start with ``b`` from all
|
||||
modules whose names start with ``a``.
|
||||
|
||||
The :cmd:ref:`dump` command can be used to print all information about an
|
||||
object. For example, calling :yoscrypt:`dump $2` after the :yoscrypt:`cd
|
||||
example` above:
|
||||
The `dump` command can be used to print all information about an object. For
|
||||
example, calling :yoscrypt:`dump $2` after the :yoscrypt:`cd example` above:
|
||||
|
||||
.. literalinclude:: /code_examples/show/example.out
|
||||
:language: RTLIL
|
||||
|
@ -323,11 +319,10 @@ tools).
|
|||
|
||||
- The selection mechanism, especially patterns such as ``%ci`` and ``%co``, can
|
||||
be used to figure out how parts of the design are connected.
|
||||
- Commands such as :cmd:ref:`submod`, :cmd:ref:`expose`, and :cmd:ref:`splice`
|
||||
can be used to transform the design into an equivalent design that is easier
|
||||
to analyse.
|
||||
- Commands such as :cmd:ref:`eval` and :cmd:ref:`sat` can be used to investigate
|
||||
the behavior of the circuit.
|
||||
- Commands such as `submod`, `expose`, and `splice` can be used to transform the
|
||||
design into an equivalent design that is easier to analyse.
|
||||
- Commands such as `eval` and `sat` can be used to investigate the behavior of
|
||||
the circuit.
|
||||
- :doc:`/cmd/show`.
|
||||
- :doc:`/cmd/dump`.
|
||||
- :doc:`/cmd/add` and :doc:`/cmd/delete` can be used to modify and reorganize a
|
||||
|
@ -342,10 +337,10 @@ The code used is included in the Yosys code base under
|
|||
Changing design hierarchy
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Commands such as :cmd:ref:`flatten` and :cmd:ref:`submod` can be used to change
|
||||
the design hierarchy, i.e. flatten the hierarchy or moving parts of a module to
|
||||
a submodule. This has applications in synthesis scripts as well as in reverse
|
||||
engineering and analysis. An example using :cmd:ref:`submod` is shown below for
|
||||
Commands such as `flatten` and `submod` can be used to change the design
|
||||
hierarchy, i.e. flatten the hierarchy or moving parts of a module to a
|
||||
submodule. This has applications in synthesis scripts as well as in reverse
|
||||
engineering and analysis. An example using `submod` is shown below for
|
||||
reorganizing a module in Yosys and checking the resulting circuit.
|
||||
|
||||
.. literalinclude:: /code_examples/scrambler/scrambler.v
|
||||
|
@ -388,10 +383,10 @@ Analyzing the resulting circuit with :doc:`/cmd/eval`:
|
|||
Behavioral changes
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Commands such as :cmd:ref:`techmap` can be used to make behavioral changes to
|
||||
the design, for example changing asynchronous resets to synchronous resets. This
|
||||
has applications in design space exploration (evaluation of various
|
||||
architectures for one circuit).
|
||||
Commands such as `techmap` can be used to make behavioral changes to the design,
|
||||
for example changing asynchronous resets to synchronous resets. This has
|
||||
applications in design space exploration (evaluation of various architectures
|
||||
for one circuit).
|
||||
|
||||
The following techmap map file replaces all positive-edge async reset flip-flops
|
||||
with positive-edge sync reset flip-flops. The code is taken from the example
|
||||
|
@ -425,7 +420,7 @@ Yosys script for ASIC synthesis of the Amber ARMv2 CPU.
|
|||
|
||||
endmodule
|
||||
|
||||
For more on the :cmd:ref:`techmap` command, see the page on
|
||||
For more on the `techmap` command, see the page on
|
||||
:doc:`/yosys_internals/techmap`.
|
||||
|
||||
Advanced investigation techniques
|
||||
|
@ -448,12 +443,12 @@ Recall the ``memdemo`` design from :ref:`advanced_logic_cones`:
|
|||
|
||||
Because this produces a rather large circuit, it can be useful to split it into
|
||||
smaller parts for viewing and working with. :numref:`submod` does exactly that,
|
||||
utilising the :cmd:ref:`submod` command to split the circuit into three
|
||||
sections: ``outstage``, ``selstage``, and ``scramble``.
|
||||
utilising the `submod` command to split the circuit into three sections:
|
||||
``outstage``, ``selstage``, and ``scramble``.
|
||||
|
||||
.. literalinclude:: /code_examples/selections/submod.ys
|
||||
:language: yoscrypt
|
||||
:caption: Using :cmd:ref:`submod` to break up the circuit from :file:`memdemo.v`
|
||||
:caption: Using `submod` to break up the circuit from :file:`memdemo.v`
|
||||
:start-after: cd memdemo
|
||||
:end-before: cd ..
|
||||
:name: submod
|
||||
|
@ -481,9 +476,9 @@ below.
|
|||
Evaluation of combinatorial circuits
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The :cmd:ref:`eval` command can be used to evaluate combinatorial circuits. As
|
||||
an example, we will use the ``selstage`` subnet of ``memdemo`` which we found
|
||||
above and is shown in :numref:`selstage`.
|
||||
The `eval` command can be used to evaluate combinatorial circuits. As an
|
||||
example, we will use the ``selstage`` subnet of ``memdemo`` which we found above
|
||||
and is shown in :numref:`selstage`.
|
||||
|
||||
.. todo:: replace inline code
|
||||
|
||||
|
@ -526,21 +521,21 @@ The ``-table`` option can be used to create a truth table. For example:
|
|||
|
||||
Assumed undef (x) value for the following signals: \s2
|
||||
|
||||
Note that the :cmd:ref:`eval` command (as well as the :cmd:ref:`sat` command
|
||||
discussed in the next sections) does only operate on flattened modules. It can
|
||||
not analyze signals that are passed through design hierarchy levels. So the
|
||||
:cmd:ref:`flatten` command must be used on modules that instantiate other
|
||||
modules before these commands can be applied.
|
||||
Note that the `eval` command (as well as the `sat` command discussed in the next
|
||||
sections) does only operate on flattened modules. It can not analyze signals
|
||||
that are passed through design hierarchy levels. So the `flatten` command must
|
||||
be used on modules that instantiate other modules before these commands can be
|
||||
applied.
|
||||
|
||||
Solving combinatorial SAT problems
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Often the opposite of the :cmd:ref:`eval` command is needed, i.e. the circuits
|
||||
output is given and we want to find the matching input signals. For small
|
||||
circuits with only a few input bits this can be accomplished by trying all
|
||||
possible input combinations, as it is done by the ``eval -table`` command. For
|
||||
larger circuits however, Yosys provides the :cmd:ref:`sat` command that uses a
|
||||
`SAT`_ solver, `MiniSAT`_, to solve this kind of problems.
|
||||
Often the opposite of the `eval` command is needed, i.e. the circuits output is
|
||||
given and we want to find the matching input signals. For small circuits with
|
||||
only a few input bits this can be accomplished by trying all possible input
|
||||
combinations, as it is done by the ``eval -table`` command. For larger circuits
|
||||
however, Yosys provides the `sat` command that uses a `SAT`_ solver, `MiniSAT`_,
|
||||
to solve this kind of problems.
|
||||
|
||||
.. _SAT: http://en.wikipedia.org/wiki/Circuit_satisfiability
|
||||
|
||||
|
@ -551,9 +546,9 @@ larger circuits however, Yosys provides the :cmd:ref:`sat` command that uses a
|
|||
While it is possible to perform model checking directly in Yosys, it
|
||||
is highly recommended to use SBY or EQY for formal hardware verification.
|
||||
|
||||
The :cmd:ref:`sat` command works very similar to the :cmd:ref:`eval` command.
|
||||
The main difference is that it is now also possible to set output values and
|
||||
find the corresponding input values. For Example:
|
||||
The `sat` command works very similar to the `eval` command. The main difference
|
||||
is that it is now also possible to set output values and find the corresponding
|
||||
input values. For Example:
|
||||
|
||||
.. todo:: replace inline code
|
||||
|
||||
|
@ -580,8 +575,8 @@ find the corresponding input values. For Example:
|
|||
\s1 0 0 00
|
||||
\s2 0 0 00
|
||||
|
||||
Note that the :cmd:ref:`sat` command supports signal names in both arguments to
|
||||
the ``-set`` option. In the above example we used ``-set s1 s2`` to constraint
|
||||
Note that the `sat` command supports signal names in both arguments to the
|
||||
``-set`` option. In the above example we used ``-set s1 s2`` to constraint
|
||||
``s1`` and ``s2`` to be equal. When more complex constraints are needed, a
|
||||
wrapper circuit must be constructed that checks the constraints and signals if
|
||||
the constraint was met using an extra output port, which then can be forced to a
|
||||
|
@ -642,8 +637,8 @@ of course be to perform the test in 32 bits, for example by replacing ``p !=
|
|||
a*b`` in the miter with ``p != {16'd0,a}b``, or by using a temporary variable
|
||||
for the 32 bit product ``a*b``. But as 31 fits well into 8 bits (and as the
|
||||
purpose of this document is to show off Yosys features) we can also simply force
|
||||
the upper 8 bits of ``a`` and ``b`` to zero for the :cmd:ref:`sat` call, as is
|
||||
done below.
|
||||
the upper 8 bits of ``a`` and ``b`` to zero for the `sat` call, as is done
|
||||
below.
|
||||
|
||||
.. todo:: replace inline code
|
||||
|
||||
|
@ -705,18 +700,18 @@ command:
|
|||
sat -seq 6 -show y -show d -set-init-undef \
|
||||
-max_undef -set-at 4 y 1 -set-at 5 y 2 -set-at 6 y 3
|
||||
|
||||
The ``-seq 6`` option instructs the :cmd:ref:`sat` command to solve a sequential
|
||||
problem in 6 time steps. (Experiments with lower number of steps have show that
|
||||
at least 3 cycles are necessary to bring the circuit in a state from which the
|
||||
sequence 1, 2, 3 can be produced.)
|
||||
The ``-seq 6`` option instructs the `sat` command to solve a sequential problem
|
||||
in 6 time steps. (Experiments with lower number of steps have show that at least
|
||||
3 cycles are necessary to bring the circuit in a state from which the sequence
|
||||
1, 2, 3 can be produced.)
|
||||
|
||||
The ``-set-init-undef`` option tells the :cmd:ref:`sat` command to initialize
|
||||
all registers to the undef (``x``) state. The way the ``x`` state is treated in
|
||||
The ``-set-init-undef`` option tells the `sat` command to initialize all
|
||||
registers to the undef (``x``) state. The way the ``x`` state is treated in
|
||||
Verilog will ensure that the solution will work for any initial state.
|
||||
|
||||
The ``-max_undef`` option instructs the :cmd:ref:`sat` command to find a
|
||||
solution with a maximum number of undefs. This way we can see clearly which
|
||||
inputs bits are relevant to the solution.
|
||||
The ``-max_undef`` option instructs the `sat` command to find a solution with a
|
||||
maximum number of undefs. This way we can see clearly which inputs bits are
|
||||
relevant to the solution.
|
||||
|
||||
Finally the three ``-set-at`` options add constraints for the ``y`` signal to
|
||||
play the 1, 2, 3 sequence, starting with time step 4.
|
||||
|
@ -807,7 +802,7 @@ is the only way of setting the ``s1`` and ``s2`` registers to a known value. The
|
|||
input values for the other steps are a bit harder to work out manually, but the
|
||||
SAT solver finds the correct solution in an instant.
|
||||
|
||||
There is much more to write about the :cmd:ref:`sat` command. For example, there
|
||||
is a set of options that can be used to performs sequential proofs using
|
||||
temporal induction :cite:p:`een2003temporal`. The command ``help sat`` can be
|
||||
used to print a list of all options with short descriptions of their functions.
|
||||
There is much more to write about the `sat` command. For example, there is a set
|
||||
of options that can be used to performs sequential proofs using temporal
|
||||
induction :cite:p:`een2003temporal`. The command ``help sat`` can be used to
|
||||
print a list of all options with short descriptions of their functions.
|
||||
|
|
|
@ -17,8 +17,7 @@ passes in Yosys.
|
|||
|
||||
Other applications include checking if a module conforms to interface standards.
|
||||
|
||||
The :cmd:ref:`sat` command in Yosys can be used to perform Symbolic Model
|
||||
Checking.
|
||||
The `sat` command in Yosys can be used to perform Symbolic Model Checking.
|
||||
|
||||
Checking techmap
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -9,33 +9,33 @@ The selection framework
|
|||
|
||||
.. todo:: reduce overlap with :doc:`/getting_started/scripting_intro` select section
|
||||
|
||||
The :cmd:ref:`select` command can be used to create a selection for subsequent
|
||||
commands. For example:
|
||||
The `select` command can be used to create a selection for subsequent commands.
|
||||
For example:
|
||||
|
||||
.. code:: yoscrypt
|
||||
|
||||
select foobar # select the module foobar
|
||||
delete # delete selected objects
|
||||
|
||||
Normally the :cmd:ref:`select` command overwrites a previous selection. The
|
||||
commands :yoscrypt:`select -add` and :yoscrypt:`select -del` can be used to add
|
||||
or remove objects from the current selection.
|
||||
Normally the `select` command overwrites a previous selection. The commands
|
||||
:yoscrypt:`select -add` and :yoscrypt:`select -del` can be used to add or remove
|
||||
objects from the current selection.
|
||||
|
||||
The command :yoscrypt:`select -clear` can be used to reset the selection to the
|
||||
default, which is a complete selection of everything in the current module.
|
||||
|
||||
This selection framework can also be used directly in many other commands.
|
||||
Whenever a command has ``[selection]`` as last argument in its usage help, this
|
||||
means that it will use the engine behind the :cmd:ref:`select` command to
|
||||
evaluate additional arguments and use the resulting selection instead of the
|
||||
selection created by the last :cmd:ref:`select` command.
|
||||
means that it will use the engine behind the `select` command to evaluate
|
||||
additional arguments and use the resulting selection instead of the selection
|
||||
created by the last `select` command.
|
||||
|
||||
For example, the command :cmd:ref:`delete` will delete everything in the current
|
||||
For example, the command `delete` will delete everything in the current
|
||||
selection; while :yoscrypt:`delete foobar` will only delete the module foobar.
|
||||
If no :cmd:ref:`select` command has been made, then the "current selection" will
|
||||
be the whole design.
|
||||
If no `select` command has been made, then the "current selection" will be the
|
||||
whole design.
|
||||
|
||||
.. note:: Many of the examples on this page make use of the :cmd:ref:`show`
|
||||
.. note:: Many of the examples on this page make use of the `show`
|
||||
command to visually demonstrate the effect of selections. For a more
|
||||
detailed look at this command, refer to :ref:`interactive_show`.
|
||||
|
||||
|
@ -59,8 +59,8 @@ Module and design context
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Commands can be executed in *module/* or *design/* context. Until now, all
|
||||
commands have been executed in design context. The :cmd:ref:`cd` command can be
|
||||
used to switch to module context.
|
||||
commands have been executed in design context. The `cd` command can be used to
|
||||
switch to module context.
|
||||
|
||||
In module context, all commands only effect the active module. Objects in the
|
||||
module are selected without the ``<module_name>/`` prefix. For example:
|
||||
|
@ -91,7 +91,7 @@ Special patterns can be used to select by object property or type. For example:
|
|||
a:foobar=42`
|
||||
- select all modules with the attribute ``blabla`` set: :yoscrypt:`select
|
||||
A:blabla`
|
||||
- select all $add cells from the module foo: :yoscrypt:`select foo/t:$add`
|
||||
- select all `$add` cells from the module foo: :yoscrypt:`select foo/t:$add`
|
||||
|
||||
A complete list of pattern expressions can be found in :doc:`/cmd/select`.
|
||||
|
||||
|
@ -101,12 +101,12 @@ Operations on selections
|
|||
Combining selections
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The :cmd:ref:`select` command is actually much more powerful than it might seem
|
||||
at first glance. When it is called with multiple arguments, each argument is
|
||||
evaluated and pushed separately on a stack. After all arguments have been
|
||||
processed it simply creates the union of all elements on the stack. So
|
||||
:yoscrypt:`select t:$add a:foo` will select all ``$add`` cells and all objects
|
||||
with the ``foo`` attribute set:
|
||||
The `select` command is actually much more powerful than it might seem at first
|
||||
glance. When it is called with multiple arguments, each argument is evaluated
|
||||
and pushed separately on a stack. After all arguments have been processed it
|
||||
simply creates the union of all elements on the stack. So :yoscrypt:`select
|
||||
t:$add a:foo` will select all `$add` cells and all objects with the ``foo``
|
||||
attribute set:
|
||||
|
||||
.. literalinclude:: /code_examples/selections/foobaraddsub.v
|
||||
:caption: Test module for operations on selections
|
||||
|
@ -126,7 +126,7 @@ ineffective way of selecting the interesting part of the design. Special
|
|||
arguments can be used to combine the elements on the stack. For example the
|
||||
``%i`` arguments pops the last two elements from the stack, intersects them, and
|
||||
pushes the result back on the stack. So :yoscrypt:`select t:$add a:foo %i` will
|
||||
select all ``$add`` cells that have the ``foo`` attribute set:
|
||||
select all `$add` cells that have the ``foo`` attribute set:
|
||||
|
||||
.. code-block::
|
||||
:caption: Output for command ``select t:$add a:foo %i -list`` on :numref:`foobaraddsub`
|
||||
|
@ -190,7 +190,7 @@ Selecting logic cones
|
|||
:numref:`sumprod_01` shows what is called the ``input cone`` of ``sum``, i.e.
|
||||
all cells and signals that are used to generate the signal ``sum``. The ``%ci``
|
||||
action can be used to select the input cones of all object in the top selection
|
||||
in the stack maintained by the :cmd:ref:`select` command.
|
||||
in the stack maintained by the `select` command.
|
||||
|
||||
As with the ``%x`` action, these commands broaden the selection by one "step".
|
||||
But this time the operation only works against the direction of data flow. That
|
||||
|
@ -220,11 +220,11 @@ The following sequence of diagrams demonstrates this step-wise expansion:
|
|||
Output of :yoscrypt:`show prod %ci %ci %ci` on :numref:`sumprod`
|
||||
|
||||
Notice the subtle difference between :yoscrypt:`show prod %ci` and
|
||||
:yoscrypt:`show prod %ci %ci`. Both images show the ``$mul`` cell driven by
|
||||
some inputs ``$3_Y`` and ``c``. However it is not until the second image,
|
||||
having called ``%ci`` the second time, that :cmd:ref:`show` is able to
|
||||
distinguish between ``$3_Y`` being a wire and ``c`` being an input. We can see
|
||||
this better with the :cmd:ref:`dump` command instead:
|
||||
:yoscrypt:`show prod %ci %ci`. Both images show the `$mul` cell driven by some
|
||||
inputs ``$3_Y`` and ``c``. However it is not until the second image, having
|
||||
called ``%ci`` the second time, that `show` is able to distinguish between
|
||||
``$3_Y`` being a wire and ``c`` being an input. We can see this better with the
|
||||
`dump` command instead:
|
||||
|
||||
.. literalinclude:: /code_examples/selections/sumprod.out
|
||||
:language: RTLIL
|
||||
|
@ -241,8 +241,8 @@ be a bit dull. So there is a shortcut for that: the number of iterations can be
|
|||
appended to the action. So for example the action ``%ci3`` is identical to
|
||||
performing the ``%ci`` action three times.
|
||||
|
||||
The action ``%ci*`` performs the ``%ci`` action over and over again until it
|
||||
has no effect anymore.
|
||||
The action ``%ci*`` performs the ``%ci`` action over and over again until it has
|
||||
no effect anymore.
|
||||
|
||||
.. _advanced_logic_cones:
|
||||
|
||||
|
@ -264,8 +264,8 @@ source repository.
|
|||
:name: memdemo_src
|
||||
:language: verilog
|
||||
|
||||
The script :file:`memdemo.ys` is used to generate the images included here. Let's
|
||||
look at the first section:
|
||||
The script :file:`memdemo.ys` is used to generate the images included here.
|
||||
Let's look at the first section:
|
||||
|
||||
.. literalinclude:: /code_examples/selections/memdemo.ys
|
||||
:caption: Synthesizing :ref:`memdemo_src`
|
||||
|
@ -276,8 +276,8 @@ look at the first section:
|
|||
This loads :numref:`memdemo_src` and synthesizes the included module. Note that
|
||||
this code can be copied and run directly in a Yosys command line session,
|
||||
provided :file:`memdemo.v` is in the same directory. We can now change to the
|
||||
``memdemo`` module with ``cd memdemo``, and call :cmd:ref:`show` to see the
|
||||
diagram in :numref:`memdemo_00`.
|
||||
``memdemo`` module with ``cd memdemo``, and call `show` to see the diagram in
|
||||
:numref:`memdemo_00`.
|
||||
|
||||
.. figure:: /_images/code_examples/selections/memdemo_00.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -296,7 +296,7 @@ cones`_ from above, we can use :yoscrypt:`show y %ci2`:
|
|||
|
||||
Output of :yoscrypt:`show y %ci2`
|
||||
|
||||
From this we would learn that ``y`` is driven by a ``$dff cell``, that ``y`` is
|
||||
From this we would learn that ``y`` is driven by a `$dff` cell, that ``y`` is
|
||||
connected to the output port ``Q``, that the ``clk`` signal goes into the
|
||||
``CLK`` input port of the cell, and that the data comes from an auto-generated
|
||||
wire into the input ``D`` of the flip-flop cell (indicated by the ``$`` at the
|
||||
|
@ -313,7 +313,7 @@ inputs. To add a pattern we add a colon followed by the pattern to the ``%ci``
|
|||
action. The pattern itself starts with ``-`` or ``+``, indicating if it is an
|
||||
include or exclude pattern, followed by an optional comma separated list of cell
|
||||
types, followed by an optional comma separated list of port names in square
|
||||
brackets. In this case, we want to exclude the ``S`` port of the ``$mux`` cell
|
||||
brackets. In this case, we want to exclude the ``S`` port of the `$mux` cell
|
||||
type with :yoscrypt:`show y %ci5:-$mux[S]`:
|
||||
|
||||
.. figure:: /_images/code_examples/selections/memdemo_03.*
|
||||
|
@ -334,7 +334,7 @@ multiplexer select inputs and flip-flop cells:
|
|||
Output of ``show y %ci2:+$dff[Q,D] %ci*:-$mux[S]:-$dff``
|
||||
|
||||
Or we could use :yoscrypt:`show y %ci*:-[CLK,S]:+$dff:+$mux` instead, following
|
||||
the input cone all the way but only following ``$dff`` and ``$mux`` cells, and
|
||||
the input cone all the way but only following `$dff` and `$mux` cells, and
|
||||
ignoring any ports named ``CLK`` or ``S``:
|
||||
|
||||
.. TODO:: pending discussion on whether rule ordering is a bug or a feature
|
||||
|
@ -371,8 +371,8 @@ selection instead of overwriting it.
|
|||
select -del reg_42 # but not this one
|
||||
select -add state %ci # and add more stuff
|
||||
|
||||
Within a select expression the token ``%`` can be used to push the previous selection
|
||||
on the stack.
|
||||
Within a select expression the token ``%`` can be used to push the previous
|
||||
selection on the stack.
|
||||
|
||||
.. code:: yoscrypt
|
||||
|
||||
|
@ -387,16 +387,16 @@ Storing and recalling selections
|
|||
The current selection can be stored in memory with the command ``select -set
|
||||
<name>``. It can later be recalled using ``select @<name>``. In fact, the
|
||||
``@<name>`` expression pushes the stored selection on the stack maintained by
|
||||
the :cmd:ref:`select` command. So for example :yoscrypt:`select @foo @bar %i`
|
||||
will select the intersection between the stored selections ``foo`` and ``bar``.
|
||||
the `select` command. So for example :yoscrypt:`select @foo @bar %i` will select
|
||||
the intersection between the stored selections ``foo`` and ``bar``.
|
||||
|
||||
In larger investigation efforts it is highly recommended to maintain a script
|
||||
that sets up relevant selections, so they can easily be recalled, for example
|
||||
when Yosys needs to be re-run after a design or source code change.
|
||||
|
||||
The :cmd:ref:`history` command can be used to list all recent interactive
|
||||
commands. This feature can be useful for creating such a script from the
|
||||
commands used in an interactive session.
|
||||
The `history` command can be used to list all recent interactive commands. This
|
||||
feature can be useful for creating such a script from the commands used in an
|
||||
interactive session.
|
||||
|
||||
Remember that select expressions can also be used directly as arguments to most
|
||||
commands. Some commands also accept a single select argument to some options. In
|
||||
|
|
|
@ -10,20 +10,19 @@ fine-grained optimisation and LUT mapping.
|
|||
Yosys has two different commands, which both use this logic toolbox, but use it
|
||||
in different ways.
|
||||
|
||||
The :cmd:ref:`abc` pass can be used for both ASIC (e.g. :yoscrypt:`abc
|
||||
-liberty`) and FPGA (:yoscrypt:`abc -lut`) mapping, but this page will focus on
|
||||
FPGA mapping.
|
||||
The `abc` pass can be used for both ASIC (e.g. :yoscrypt:`abc -liberty`) and
|
||||
FPGA (:yoscrypt:`abc -lut`) mapping, but this page will focus on FPGA mapping.
|
||||
|
||||
The :cmd:ref:`abc9` pass generally provides superior mapping quality due to
|
||||
being aware of combination boxes and DFF and LUT timings, giving it a more
|
||||
global view of the mapping problem.
|
||||
The `abc9` pass generally provides superior mapping quality due to being aware
|
||||
of combination boxes and DFF and LUT timings, giving it a more 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:
|
||||
The `abc` pass uses a highly simplified view of an FPGA:
|
||||
|
||||
- An FPGA is made up of a network of inputs that connect through LUTs to a
|
||||
network of outputs. These inputs may actually be I/O pins, D flip-flops,
|
||||
|
@ -126,7 +125,7 @@ guide to the syntax:
|
|||
|
||||
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.
|
||||
to `read_verilog` so that they aren't skipped.
|
||||
|
||||
LUTs
|
||||
^^^^
|
||||
|
@ -145,9 +144,9 @@ 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).
|
||||
zero (consider using `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
|
||||
|
@ -158,9 +157,9 @@ 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.
|
||||
which qualifies as an ``(* abc9_flop *)``, ran through `abc9`, and then mapped
|
||||
back to the original flop. This is used in `synth_intel_alm` and
|
||||
`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.
|
||||
|
|
|
@ -54,7 +54,7 @@ Our circuit now looks like this:
|
|||
:class: width-helper invert-helper
|
||||
:name: counter-hierarchy
|
||||
|
||||
``counter`` after :cmd:ref:`hierarchy`
|
||||
``counter`` after `hierarchy`
|
||||
|
||||
Coarse-grain representation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -82,7 +82,7 @@ Logic gate mapping
|
|||
.. figure:: /_images/code_examples/intro/counter_02.*
|
||||
:class: width-helper invert-helper
|
||||
|
||||
``counter`` after :cmd:ref:`techmap`
|
||||
``counter`` after `techmap`
|
||||
|
||||
Mapping to hardware
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -98,11 +98,11 @@ our internal cell library will be mapped to:
|
|||
:name: mycells-lib
|
||||
:caption: :file:`mycells.lib`
|
||||
|
||||
Recall that the Yosys built-in logic gate types are ``$_NOT_``, ``$_AND_``,
|
||||
``$_OR_``, ``$_XOR_``, and ``$_MUX_`` with an assortment of dff memory types.
|
||||
Recall that the Yosys built-in logic gate types are `$_NOT_`, `$_AND_`, `$_OR_`,
|
||||
`$_XOR_`, and `$_MUX_` with an assortment of dff memory types.
|
||||
:ref:`mycells-lib` defines our target cells as ``BUF``, ``NOT``, ``NAND``,
|
||||
``NOR``, and ``DFF``. Mapping between these is performed with the commands
|
||||
:cmd:ref:`dfflibmap` and :cmd:ref:`abc` as follows:
|
||||
`dfflibmap` and `abc` as follows:
|
||||
|
||||
.. literalinclude:: /code_examples/intro/counter.ys
|
||||
:language: yoscrypt
|
||||
|
@ -117,8 +117,8 @@ The final version of our ``counter`` module looks like this:
|
|||
|
||||
``counter`` after hardware cell mapping
|
||||
|
||||
Before finally being output as a verilog file with :cmd:ref:`write_verilog`,
|
||||
which can then be loaded into another tool:
|
||||
Before finally being output as a verilog file with `write_verilog`, which can
|
||||
then be loaded into another tool:
|
||||
|
||||
.. literalinclude:: /code_examples/intro/counter.ys
|
||||
:language: yoscrypt
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
The extract pass
|
||||
----------------
|
||||
|
||||
- Like the :cmd:ref:`techmap` pass, the :cmd:ref:`extract` pass is called with a
|
||||
map file. It compares the circuits inside the modules of the map file with the
|
||||
design and looks for sub-circuits in the design that match any of the modules
|
||||
in the map file.
|
||||
- If a match is found, the :cmd:ref:`extract` pass will replace the matching
|
||||
subcircuit with an instance of the module from the map file.
|
||||
- In a way the :cmd:ref:`extract` pass is the inverse of the techmap pass.
|
||||
- Like the `techmap` pass, the `extract` pass is called with a map file. It
|
||||
compares the circuits inside the modules of the map file with the design and
|
||||
looks for sub-circuits in the design that match any of the modules in the map
|
||||
file.
|
||||
- If a match is found, the `extract` pass will replace the matching subcircuit
|
||||
with an instance of the module from the map file.
|
||||
- In a way the `extract` pass is the inverse of the techmap pass.
|
||||
|
||||
.. todo:: add/expand supporting text, also mention custom pattern matching and
|
||||
pmgen
|
||||
|
@ -25,7 +25,7 @@ Example code can be found in |code_examples/macc|_.
|
|||
.. figure:: /_images/code_examples/macc/macc_simple_test_00a.*
|
||||
:class: width-helper invert-helper
|
||||
|
||||
before :cmd:ref:`extract`
|
||||
before `extract`
|
||||
|
||||
.. literalinclude:: /code_examples/macc/macc_simple_test.ys
|
||||
:language: yoscrypt
|
||||
|
@ -34,7 +34,7 @@ Example code can be found in |code_examples/macc|_.
|
|||
.. figure:: /_images/code_examples/macc/macc_simple_test_00b.*
|
||||
:class: width-helper invert-helper
|
||||
|
||||
after :cmd:ref:`extract`
|
||||
after `extract`
|
||||
|
||||
.. literalinclude:: /code_examples/macc/macc_simple_test.v
|
||||
:language: verilog
|
||||
|
@ -68,26 +68,26 @@ The wrap-extract-unwrap method
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Often a coarse-grain element has a constant bit-width, but can be used to
|
||||
implement operations with a smaller bit-width. For example, a 18x25-bit multiplier
|
||||
can also be used to implement 16x20-bit multiplication.
|
||||
implement operations with a smaller bit-width. For example, a 18x25-bit
|
||||
multiplier can also be used to implement 16x20-bit multiplication.
|
||||
|
||||
A way of mapping such elements in coarse grain synthesis is the
|
||||
wrap-extract-unwrap method:
|
||||
|
||||
wrap
|
||||
Identify candidate-cells in the circuit and wrap them in a cell with a
|
||||
constant wider bit-width using :cmd:ref:`techmap`. The wrappers use the same
|
||||
parameters as the original cell, so the information about the original width
|
||||
of the ports is preserved. Then use the :cmd:ref:`connwrappers` command to
|
||||
connect up the bit-extended in- and outputs of the wrapper cells.
|
||||
constant wider bit-width using `techmap`. The wrappers use the same parameters
|
||||
as the original cell, so the information about the original width of the ports
|
||||
is preserved. Then use the `connwrappers` command to connect up the
|
||||
bit-extended in- and outputs of the wrapper cells.
|
||||
|
||||
extract
|
||||
Now all operations are encoded using the same bit-width as the coarse grain
|
||||
element. The :cmd:ref:`extract` command can be used to replace circuits with
|
||||
cells of the target architecture.
|
||||
element. The `extract` command can be used to replace circuits with cells of
|
||||
the target architecture.
|
||||
|
||||
unwrap
|
||||
The remaining wrapper cell can be unwrapped using :cmd:ref:`techmap`.
|
||||
The remaining wrapper cell can be unwrapped using `techmap`.
|
||||
|
||||
Example: DSP48_MACC
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -127,7 +127,7 @@ Extract: :file:`macc_xilinx_xmap.v`
|
|||
:caption: :file:`macc_xilinx_xmap.v`
|
||||
|
||||
... simply use the same wrapping commands on this module as on the design to
|
||||
create a template for the :cmd:ref:`extract` command.
|
||||
create a template for the `extract` command.
|
||||
|
||||
Unwrapping multipliers: :file:`macc_xilinx_unwrap_map.v`
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
FSM handling
|
||||
============
|
||||
|
||||
The :cmd:ref:`fsm` command identifies, extracts, optimizes (re-encodes), and
|
||||
The `fsm` command identifies, extracts, optimizes (re-encodes), and
|
||||
re-synthesizes finite state machines. It again is a macro that calls a series of
|
||||
other commands:
|
||||
|
||||
.. literalinclude:: /code_examples/macro_commands/fsm.ys
|
||||
:language: yoscrypt
|
||||
:start-after: #end:
|
||||
:caption: Passes called by :cmd:ref:`fsm`
|
||||
:caption: Passes called by `fsm`
|
||||
|
||||
See also :doc:`/cmd/fsm`.
|
||||
|
||||
|
@ -18,34 +18,33 @@ general reported technique :cite:p:`fsmextract`.
|
|||
FSM detection
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The :cmd:ref:`fsm_detect` pass identifies FSM state registers. It sets the
|
||||
``\fsm_encoding = "auto"`` attribute on any (multi-bit) wire that matches the
|
||||
The `fsm_detect` pass identifies FSM state registers. It sets the
|
||||
``fsm_encoding = "auto"`` attribute on any (multi-bit) wire that matches the
|
||||
following description:
|
||||
|
||||
- Does not already have the ``\fsm_encoding`` attribute.
|
||||
- Does not already have the ``fsm_encoding`` attribute.
|
||||
- Is not an output of the containing module.
|
||||
- Is driven by single ``$dff`` or ``$adff`` cell.
|
||||
- The ``\D``-Input of this ``$dff`` or ``$adff`` cell is driven by a
|
||||
multiplexer tree that only has constants or the old state value on its
|
||||
leaves.
|
||||
- Is driven by single `$dff` or `$adff` cell.
|
||||
- The ``D``-Input of this `$dff` or `$adff` cell is driven by a multiplexer
|
||||
tree that only has constants or the old state value on its leaves.
|
||||
- The state value is only used in the said multiplexer tree or by simple
|
||||
relational cells that compare the state value to a constant (usually ``$eq``
|
||||
relational cells that compare the state value to a constant (usually `$eq`
|
||||
cells).
|
||||
|
||||
This heuristic has proven to work very well. It is possible to overwrite it by
|
||||
setting ``\fsm_encoding = "auto"`` on registers that should be considered FSM
|
||||
state registers and setting ``\fsm_encoding = "none"`` on registers that match
|
||||
setting ``fsm_encoding = "auto"`` on registers that should be considered FSM
|
||||
state registers and setting ``fsm_encoding = "none"`` on registers that match
|
||||
the above criteria but should not be considered FSM state registers.
|
||||
|
||||
Note however that marking state registers with ``\fsm_encoding`` that are not
|
||||
Note however that marking state registers with ``fsm_encoding`` that are not
|
||||
suitable for FSM recoding can cause synthesis to fail or produce invalid
|
||||
results.
|
||||
|
||||
FSM extraction
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The :cmd:ref:`fsm_extract` pass operates on all state signals marked with the
|
||||
(``\fsm_encoding != "none"``) attribute. For each state signal the following
|
||||
The `fsm_extract` pass operates on all state signals marked with the
|
||||
(``fsm_encoding != "none"``) attribute. For each state signal the following
|
||||
information is determined:
|
||||
|
||||
- The state registers
|
||||
|
@ -64,10 +63,10 @@ information is determined:
|
|||
The state registers (and asynchronous reset state, if applicable) is simply
|
||||
determined by identifying the driver for the state signal.
|
||||
|
||||
From there the ``$mux-tree`` driving the state register inputs is recursively
|
||||
traversed. All select inputs are control signals and the leaves of the
|
||||
``$mux-tree`` are the states. The algorithm fails if a non-constant leaf that is
|
||||
not the state signal itself is found.
|
||||
From there the `$mux`\ -tree driving the state register inputs is recursively
|
||||
traversed. All select inputs are control signals and the leaves of the `$mux`\
|
||||
-tree are the states. The algorithm fails if a non-constant leaf that is not the
|
||||
state signal itself is found.
|
||||
|
||||
The list of control outputs is initialized with the bits from the state signal.
|
||||
It is then extended by adding all values that are calculated by cells that
|
||||
|
@ -85,8 +84,8 @@ given set of result signals using a set of signal-value assignments. It can also
|
|||
be passed a list of stop-signals that abort the ConstEval algorithm if the value
|
||||
of a stop-signal is needed in order to calculate the result signals.
|
||||
|
||||
The :cmd:ref:`fsm_extract` pass uses the ConstEval class in the following way to
|
||||
create a transition table. For each state:
|
||||
The `fsm_extract` pass uses the ConstEval class in the following way to create a
|
||||
transition table. For each state:
|
||||
|
||||
1. Create a ConstEval object for the module containing the FSM
|
||||
2. Add all control inputs to the list of stop signals
|
||||
|
@ -99,20 +98,19 @@ create a transition table. For each state:
|
|||
|
||||
6. If step 4 was successful: Emit transition
|
||||
|
||||
Finally a ``$fsm`` cell is created with the generated transition table and added
|
||||
Finally a `$fsm` cell is created with the generated transition table and added
|
||||
to the module. This new cell is connected to the control signals and the old
|
||||
drivers for the control outputs are disconnected.
|
||||
|
||||
FSM optimization
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The :cmd:ref:`fsm_opt` pass performs basic optimizations on ``$fsm`` cells (not
|
||||
including state recoding). The following optimizations are performed (in this
|
||||
order):
|
||||
The `fsm_opt` pass performs basic optimizations on `$fsm` cells (not including
|
||||
state recoding). The following optimizations are performed (in this order):
|
||||
|
||||
- Unused control outputs are removed from the ``$fsm`` cell. The attribute
|
||||
``\unused_bits`` (that is usually set by the :cmd:ref:`opt_clean` pass) is
|
||||
used to determine which control outputs are unused.
|
||||
- Unused control outputs are removed from the `$fsm` cell. The attribute
|
||||
``unused_bits`` (that is usually set by the `opt_clean` pass) is used to
|
||||
determine which control outputs are unused.
|
||||
|
||||
- Control inputs that are connected to the same driver are merged.
|
||||
|
||||
|
@ -132,11 +130,10 @@ order):
|
|||
FSM recoding
|
||||
~~~~~~~~~~~~
|
||||
|
||||
The :cmd:ref:`fsm_recode` pass assigns new bit pattern to the states. Usually
|
||||
this also implies a change in the width of the state signal. At the moment of
|
||||
this writing only one-hot encoding with all-zero for the reset state is
|
||||
supported.
|
||||
The `fsm_recode` pass assigns new bit pattern to the states. Usually this also
|
||||
implies a change in the width of the state signal. At the moment of this writing
|
||||
only one-hot encoding with all-zero for the reset state is supported.
|
||||
|
||||
The :cmd:ref:`fsm_recode` pass can also write a text file with the changes
|
||||
performed by it that can be used when verifying designs synthesized by Yosys
|
||||
using Synopsys Formality.
|
||||
The `fsm_recode` pass can also write a text file with the changes performed by
|
||||
it that can be used when verifying designs synthesized by Yosys using Synopsys
|
||||
Formality.
|
||||
|
|
|
@ -8,17 +8,16 @@ coarse-grain optimizations before being mapped to hard blocks and fine-grain
|
|||
cells. Most commands in Yosys will target either coarse-grain representation or
|
||||
fine-grain representation, with only a select few compatible with both states.
|
||||
|
||||
Commands such as :cmd:ref:`proc`, :cmd:ref:`fsm`, and :cmd:ref:`memory` rely on
|
||||
the additional information in the coarse-grain representation, along with a
|
||||
number of optimizations such as :cmd:ref:`wreduce`, :cmd:ref:`share`, and
|
||||
:cmd:ref:`alumacc`. :cmd:ref:`opt` provides optimizations which are useful in
|
||||
both states, while :cmd:ref:`techmap` is used to convert coarse-grain cells
|
||||
to the corresponding fine-grain representation.
|
||||
Commands such as `proc`, `fsm`, and `memory` rely on the additional information
|
||||
in the coarse-grain representation, along with a number of optimizations such as
|
||||
`wreduce`, `share`, and `alumacc`. `opt` provides optimizations which are
|
||||
useful in both states, while `techmap` is used to convert coarse-grain cells to
|
||||
the corresponding fine-grain representation.
|
||||
|
||||
Single-bit cells (logic gates, FFs) as well as LUTs, half-adders, and
|
||||
full-adders make up the bulk of the fine-grain representation and are necessary
|
||||
for commands such as :cmd:ref:`abc`\ /:cmd:ref:`abc9`, :cmd:ref:`simplemap`,
|
||||
:cmd:ref:`dfflegalize`, and :cmd:ref:`memory_map`.
|
||||
for commands such as `abc`\ /`abc9`, `simplemap`, `dfflegalize`, and
|
||||
`memory_map`.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
Memory handling
|
||||
===============
|
||||
|
||||
The :cmd:ref:`memory` command
|
||||
The `memory` command
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In the RTL netlist, memory reads and writes are individual cells. This makes
|
||||
consolidating the number of ports for a memory easier. The :cmd:ref:`memory`
|
||||
pass transforms memories to an implementation. Per default that is logic for
|
||||
address decoders and registers. It also is a macro command that calls the other
|
||||
common ``memory_*`` passes in a sensible order:
|
||||
consolidating the number of ports for a memory easier. The `memory` pass
|
||||
transforms memories to an implementation. Per default that is logic for address
|
||||
decoders and registers. It also is a macro command that calls the other common
|
||||
``memory_*`` passes in a sensible order:
|
||||
|
||||
.. literalinclude:: /code_examples/macro_commands/memory.ys
|
||||
:language: yoscrypt
|
||||
:start-after: #end:
|
||||
:caption: Passes called by :cmd:ref:`memory`
|
||||
:caption: Passes called by `memory`
|
||||
|
||||
.. todo:: Make ``memory_*`` notes less quick
|
||||
|
||||
Some quick notes:
|
||||
|
||||
- :cmd:ref:`memory_dff` merges registers into the memory read- and write cells.
|
||||
- :cmd:ref:`memory_collect` collects all read and write cells for a memory and
|
||||
- `memory_dff` merges registers into the memory read- and write cells.
|
||||
- `memory_collect` collects all read and write cells for a memory and
|
||||
transforms them into one multi-port memory cell.
|
||||
- :cmd:ref:`memory_map` takes the multi-port memory cell and transforms it to
|
||||
address decoder logic and registers.
|
||||
- `memory_map` takes the multi-port memory cell and transforms it to address
|
||||
decoder logic and registers.
|
||||
|
||||
For more information about :cmd:ref:`memory`, such as disabling certain sub
|
||||
commands, see :doc:`/cmd/memory`.
|
||||
For more information about `memory`, such as disabling certain sub commands, see
|
||||
:doc:`/cmd/memory`.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
@ -75,22 +75,22 @@ For example:
|
|||
techmap -map my_memory_map.v
|
||||
memory_map
|
||||
|
||||
:cmd:ref:`memory_libmap` attempts to convert memory cells (``$mem_v2`` etc) into
|
||||
hardware supported memory using a provided library (:file:`my_memory_map.txt` in the
|
||||
`memory_libmap` attempts to convert memory cells (`$mem_v2` etc) into hardware
|
||||
supported memory using a provided library (:file:`my_memory_map.txt` in the
|
||||
example above). Where necessary, emulation logic is added to ensure functional
|
||||
equivalence before and after this conversion. :yoscrypt:`techmap -map
|
||||
my_memory_map.v` then uses :cmd:ref:`techmap` to map to hardware primitives. Any
|
||||
leftover memory cells unable to be converted are then picked up by
|
||||
:cmd:ref:`memory_map` and mapped to DFFs and address decoders.
|
||||
my_memory_map.v` then uses `techmap` to map to hardware primitives. Any leftover
|
||||
memory cells unable to be converted are then picked up by `memory_map` and
|
||||
mapped to DFFs and address decoders.
|
||||
|
||||
.. note::
|
||||
|
||||
More information about what mapping options are available and associated
|
||||
costs of each can be found by enabling debug outputs. This can be done with
|
||||
the :cmd:ref:`debug` command, or by using the ``-g`` flag when calling Yosys
|
||||
to globally enable debug messages.
|
||||
the `debug` command, or by using the ``-g`` flag when calling Yosys to
|
||||
globally enable debug messages.
|
||||
|
||||
For more on the lib format for :cmd:ref:`memory_libmap`, see
|
||||
For more on the lib format for `memory_libmap`, see
|
||||
`passes/memory/memlib.md
|
||||
<https://github.com/YosysHQ/yosys/blob/main/passes/memory/memlib.md>`_
|
||||
|
||||
|
@ -110,13 +110,15 @@ Notes
|
|||
Memory kind selection
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The memory inference code will automatically pick target memory primitive based on memory geometry
|
||||
and features used. Depending on the target, there can be up to four memory primitive classes
|
||||
available for selection:
|
||||
The memory inference code will automatically pick target memory primitive based
|
||||
on memory geometry and features used. Depending on the target, there can be up
|
||||
to four memory primitive classes available for selection:
|
||||
|
||||
- FF RAM (aka logic): no hardware primitive used, memory lowered to a bunch of FFs and multiplexers
|
||||
- FF RAM (aka logic): no hardware primitive used, memory lowered to a bunch of
|
||||
FFs and multiplexers
|
||||
|
||||
- Can handle arbitrary number of write ports, as long as all write ports are in the same clock domain
|
||||
- Can handle arbitrary number of write ports, as long as all write ports are
|
||||
in the same clock domain
|
||||
- Can handle arbitrary number and kind of read ports
|
||||
|
||||
- LUT RAM (aka distributed RAM): uses LUT storage as RAM
|
||||
|
@ -131,7 +133,8 @@ available for selection:
|
|||
- Supported on basically all FPGAs
|
||||
- Supports only synchronous reads
|
||||
- Two ports with separate clocks
|
||||
- Usually supports true dual port (with notable exception of ice40 that only supports SDP)
|
||||
- Usually supports true dual port (with notable exception of ice40 that only
|
||||
supports SDP)
|
||||
- Usually supports asymmetric memories and per-byte write enables
|
||||
- Several kilobits in size
|
||||
|
||||
|
@ -155,38 +158,43 @@ available for selection:
|
|||
- Two ports, both with mutually exclusive synchronous read and write
|
||||
- Single clock
|
||||
|
||||
- Will not be automatically selected by memory inference code, needs explicit opt-in via
|
||||
ram_style attribute
|
||||
- Will not be automatically selected by memory inference code, needs explicit
|
||||
opt-in via ram_style attribute
|
||||
|
||||
In general, you can expect the automatic selection process to work roughly like this:
|
||||
In general, you can expect the automatic selection process to work roughly like
|
||||
this:
|
||||
|
||||
- If any read port is asynchronous, only LUT RAM (or FF RAM) can be used.
|
||||
- If there is more than one write port, only block RAM can be used, and this needs to be a
|
||||
hardware-supported true dual port pattern
|
||||
- If there is more than one write port, only block RAM can be used, and this
|
||||
needs to be a hardware-supported true dual port pattern
|
||||
|
||||
- … unless all write ports are in the same clock domain, in which case FF RAM can also be used,
|
||||
but this is generally not what you want for anything but really small memories
|
||||
- … unless all write ports are in the same clock domain, in which case FF RAM
|
||||
can also be used, but this is generally not what you want for anything but
|
||||
really small memories
|
||||
|
||||
- Otherwise, either FF RAM, LUT RAM, or block RAM will be used, depending on memory size
|
||||
- Otherwise, either FF RAM, LUT RAM, or block RAM will be used, depending on
|
||||
memory size
|
||||
|
||||
This process can be overridden by attaching a ram_style attribute to the memory:
|
||||
|
||||
- `(* ram_style = "logic" *)` selects FF RAM
|
||||
- `(* ram_style = "distributed" *)` selects LUT RAM
|
||||
- `(* ram_style = "block" *)` selects block RAM
|
||||
- `(* ram_style = "huge" *)` selects huge RAM
|
||||
- ``(* ram_style = "logic" *)`` selects FF RAM
|
||||
- ``(* ram_style = "distributed" *)`` selects LUT RAM
|
||||
- ``(* ram_style = "block" *)`` selects block RAM
|
||||
- ``(* ram_style = "huge" *)`` selects huge RAM
|
||||
|
||||
It is an error if this override cannot be realized for the given target.
|
||||
|
||||
Many alternate spellings of the attribute are also accepted, for compatibility with other software.
|
||||
Many alternate spellings of the attribute are also accepted, for compatibility
|
||||
with other software.
|
||||
|
||||
Initial data
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Most FPGA targets support initializing all kinds of memory to user-provided values. If explicit
|
||||
initialization is not used the initial memory value is undefined. Initial data can be provided by
|
||||
either initial statements writing memory cells one by one of ``$readmemh`` or ``$readmemb`` system
|
||||
tasks. For an example pattern, see `sr_init`_.
|
||||
Most FPGA targets support initializing all kinds of memory to user-provided
|
||||
values. If explicit initialization is not used the initial memory value is
|
||||
undefined. Initial data can be provided by either initial statements writing
|
||||
memory cells one by one of ``$readmemh`` or ``$readmemb`` system tasks. For an
|
||||
example pattern, see `sr_init`_.
|
||||
|
||||
.. _wbe:
|
||||
|
||||
|
@ -194,12 +202,13 @@ Write port with byte enables
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Byte enables can be used with any supported pattern
|
||||
- To ensure that multiple writes will be merged into one port, they need to have disjoint bit
|
||||
ranges, have the same address, and the same clock
|
||||
- Any write enable granularity will be accepted (down to per-bit write enables), but using smaller
|
||||
granularity than natively supported by the target is very likely to be inefficient (eg. using
|
||||
4-bit bytes on ECP5 will result in either padding the bytes with 5 dummy bits to native 9-bit
|
||||
units or splitting the RAM into two block RAMs)
|
||||
- To ensure that multiple writes will be merged into one port, they need to have
|
||||
disjoint bit ranges, have the same address, and the same clock
|
||||
- Any write enable granularity will be accepted (down to per-bit write enables),
|
||||
but using smaller granularity than natively supported by the target is very
|
||||
likely to be inefficient (eg. using 4-bit bytes on ECP5 will result in either
|
||||
padding the bytes with 5 dummy bits to native 9-bit units or splitting the RAM
|
||||
into two block RAMs)
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -240,7 +249,8 @@ Synchronous SDP with clock domain crossing
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Will result in block RAM or LUT RAM depending on size
|
||||
- No behavior guarantees in case of simultaneous read and write to the same address
|
||||
- No behavior guarantees in case of simultaneous read and write to the same
|
||||
address
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -261,9 +271,9 @@ Synchronous SDP read first
|
|||
|
||||
- The read and write parts can be in the same or different processes.
|
||||
- Will result in block RAM or LUT RAM depending on size
|
||||
- As long as the same clock is used for both, yosys will ensure read-first behavior. This may
|
||||
require extra circuitry on some targets for block RAM. If this is not necessary, use one of the
|
||||
patterns below.
|
||||
- As long as the same clock is used for both, yosys will ensure read-first
|
||||
behavior. This may require extra circuitry on some targets for block RAM. If
|
||||
this is not necessary, use one of the patterns below.
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -281,8 +291,8 @@ Synchronous SDP read first
|
|||
Synchronous SDP with undefined collision behavior
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Like above, but the read value is undefined when read and write ports target the same address in
|
||||
the same cycle
|
||||
- Like above, but the read value is undefined when read and write ports target
|
||||
the same address in the same cycle
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -322,8 +332,8 @@ Synchronous SDP with write-first behavior
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Will result in block RAM or LUT RAM depending on size
|
||||
- May use additional circuitry for block RAM if write-first is not natively supported. Will always
|
||||
use additional circuitry for LUT RAM.
|
||||
- May use additional circuitry for block RAM if write-first is not natively
|
||||
supported. Will always use additional circuitry for LUT RAM.
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -343,7 +353,8 @@ Synchronous SDP with write-first behavior
|
|||
Synchronous SDP with write-first behavior (alternate pattern)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- This pattern is supported for compatibility, but is much less flexible than the above
|
||||
- This pattern is supported for compatibility, but is much less flexible than
|
||||
the above
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -378,8 +389,10 @@ Synchronous single-port RAM with mutually exclusive read/write
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Will result in single-port block RAM or LUT RAM depending on size
|
||||
- This is the correct pattern to infer ice40 SPRAM (with manual ram_style selection)
|
||||
- On targets that don't support read/write block RAM ports (eg. ice40), will result in SDP block RAM instead
|
||||
- This is the correct pattern to infer ice40 SPRAM (with manual ram_style
|
||||
selection)
|
||||
- On targets that don't support read/write block RAM ports (eg. ice40), will
|
||||
result in SDP block RAM instead
|
||||
- For block RAM, will use "NO_CHANGE" mode if available
|
||||
|
||||
.. code:: verilog
|
||||
|
@ -396,12 +409,14 @@ Synchronous single-port RAM with mutually exclusive read/write
|
|||
Synchronous single-port RAM with read-first behavior
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Will only result in single-port block RAM when read-first behavior is natively supported;
|
||||
otherwise, SDP RAM with additional circuitry will be used
|
||||
- Many targets (Xilinx, ECP5, …) can only natively support read-first/write-first single-port RAM
|
||||
(or TDP RAM) where the write_enable signal implies the read_enable signal (ie. can never write
|
||||
without reading). The memory inference code will run a simple SAT solver on the control signals to
|
||||
determine if this is the case, and insert emulation circuitry if it cannot be easily proven.
|
||||
- Will only result in single-port block RAM when read-first behavior is natively
|
||||
supported; otherwise, SDP RAM with additional circuitry will be used
|
||||
- Many targets (Xilinx, ECP5, …) can only natively support
|
||||
read-first/write-first single-port RAM (or TDP RAM) where the write_enable
|
||||
signal implies the read_enable signal (ie. can never write without reading).
|
||||
The memory inference code will run a simple SAT solver on the control signals
|
||||
to determine if this is the case, and insert emulation circuitry if it cannot
|
||||
be easily proven.
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -418,7 +433,8 @@ Synchronous single-port RAM with write-first behavior
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Will result in single-port block RAM or LUT RAM when supported
|
||||
- Block RAMs will require extra circuitry if write-first behavior not natively supported
|
||||
- Block RAMs will require extra circuitry if write-first behavior not natively
|
||||
supported
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -440,8 +456,8 @@ Synchronous read port with initial value
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Initial read port values can be combined with any other supported pattern
|
||||
- If block RAM is used and initial read port values are not natively supported by the target, small
|
||||
emulation circuit will be inserted
|
||||
- If block RAM is used and initial read port values are not natively supported
|
||||
by the target, small emulation circuit will be inserted
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -459,10 +475,11 @@ Synchronous read port with initial value
|
|||
Read register reset patterns
|
||||
----------------------------
|
||||
|
||||
Resets can be combined with any other supported pattern (except that synchronous reset and
|
||||
asynchronous reset cannot both be used on a single read port). If block RAM is used and the
|
||||
selected reset (synchronous or asynchronous) is used but not natively supported by the target, small
|
||||
emulation circuitry will be inserted.
|
||||
Resets can be combined with any other supported pattern (except that synchronous
|
||||
reset and asynchronous reset cannot both be used on a single read port). If
|
||||
block RAM is used and the selected reset (synchronous or asynchronous) is used
|
||||
but not natively supported by the target, small emulation circuitry will be
|
||||
inserted.
|
||||
|
||||
Synchronous reset, reset priority over enable
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -520,22 +537,26 @@ Synchronous read port with asynchronous reset
|
|||
Asymmetric memory patterns
|
||||
--------------------------
|
||||
|
||||
To construct an asymmetric memory (memory with read/write ports of differing widths):
|
||||
To construct an asymmetric memory (memory with read/write ports of differing
|
||||
widths):
|
||||
|
||||
- Declare the memory with the width of the narrowest intended port
|
||||
- Split all wide ports into multiple narrow ports
|
||||
- To ensure the wide ports will be correctly merged:
|
||||
|
||||
- For the address, use a concatenation of actual address in the high bits and a constant in the
|
||||
low bits
|
||||
- Ensure the actual address is identical for all ports belonging to the wide port
|
||||
- For the address, use a concatenation of actual address in the high bits and
|
||||
a constant in the low bits
|
||||
- Ensure the actual address is identical for all ports belonging to the wide
|
||||
port
|
||||
- Ensure that clock is identical
|
||||
- For read ports, ensure that enable/reset signals are identical (for write ports, the enable
|
||||
signal may vary — this will result in using the byte enable functionality)
|
||||
- For read ports, ensure that enable/reset signals are identical (for write
|
||||
ports, the enable signal may vary — this will result in using the byte
|
||||
enable functionality)
|
||||
|
||||
Asymmetric memory is supported on all targets, but may require emulation circuitry where not
|
||||
natively supported. Note that when the memory is larger than the underlying block RAM primitive,
|
||||
hardware asymmetric memory support is likely not to be used even if present as it is more expensive.
|
||||
Asymmetric memory is supported on all targets, but may require emulation
|
||||
circuitry where not natively supported. Note that when the memory is larger
|
||||
than the underlying block RAM primitive, hardware asymmetric memory support is
|
||||
likely not to be used even if present as it is more expensive.
|
||||
|
||||
.. _wide_sr:
|
||||
|
||||
|
@ -615,20 +636,25 @@ Wide write port
|
|||
True dual port (TDP) patterns
|
||||
-----------------------------
|
||||
|
||||
- Many different variations of true dual port memory can be created by combining two single-port RAM
|
||||
patterns on the same memory
|
||||
- When TDP memory is used, memory inference code has much less maneuver room to create requested
|
||||
semantics compared to individual single-port patterns (which can end up lowered to SDP memory
|
||||
where necessary) — supported patterns depend strongly on the target
|
||||
- In particular, when both ports have the same clock, it's likely that "undefined collision" mode
|
||||
needs to be manually selected to enable TDP memory inference
|
||||
- The examples below are non-exhaustive — many more combinations of port types are possible
|
||||
- Note: if two write ports are in the same process, this defines a priority relation between them
|
||||
(if both ports are active in the same clock, the later one wins). On almost all targets, this will
|
||||
result in a bit of extra circuitry to ensure the priority semantics. If this is not what you want,
|
||||
put them in separate processes.
|
||||
- Many different variations of true dual port memory can be created by combining
|
||||
two single-port RAM patterns on the same memory
|
||||
- When TDP memory is used, memory inference code has much less maneuver room to
|
||||
create requested semantics compared to individual single-port patterns (which
|
||||
can end up lowered to SDP memory where necessary) — supported patterns depend
|
||||
strongly on the target
|
||||
- In particular, when both ports have the same clock, it's likely that
|
||||
"undefined collision" mode needs to be manually selected to enable TDP memory
|
||||
inference
|
||||
- The examples below are non-exhaustive — many more combinations of port types
|
||||
are possible
|
||||
- Note: if two write ports are in the same process, this defines a priority
|
||||
relation between them (if both ports are active in the same clock, the later
|
||||
one wins). On almost all targets, this will result in a bit of extra circuitry
|
||||
to ensure the priority semantics. If this is not what you want, put them in
|
||||
separate processes.
|
||||
|
||||
- Priority is not supported when using the verific front end and any priority semantics are ignored.
|
||||
- Priority is not supported when using the verific front end and any priority
|
||||
semantics are ignored.
|
||||
|
||||
TDP with different clocks, exclusive read/write
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -654,7 +680,8 @@ TDP with different clocks, exclusive read/write
|
|||
TDP with same clock, read-first behavior
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- This requires hardware inter-port read-first behavior, and will only work on some targets (Xilinx, Nexus)
|
||||
- This requires hardware inter-port read-first behavior, and will only work on
|
||||
some targets (Xilinx, Nexus)
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
@ -677,9 +704,10 @@ TDP with same clock, read-first behavior
|
|||
TDP with multiple read ports
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- The combination of a single write port with an arbitrary amount of read ports is supported on all
|
||||
targets — if a multi-read port primitive is available (like Xilinx RAM64M), it'll be used as
|
||||
appropriate. Otherwise, the memory will be automatically split into multiple primitives.
|
||||
- The combination of a single write port with an arbitrary amount of read ports
|
||||
is supported on all targets — if a multi-read port primitive is available
|
||||
(like Xilinx RAM64M), it'll be used as appropriate. Otherwise, the memory
|
||||
will be automatically split into multiple primitives.
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue