mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-03 01:40:23 +00:00
Merge branch 'main' of https://github.com/YosysHQ/yosys
This commit is contained in:
commit
ddc99a3b97
690 changed files with 39993 additions and 13636 deletions
|
@ -10,3 +10,7 @@ insert_final_newline = true
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.yml]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
5
.github/actions/setup-build-env/action.yml
vendored
5
.github/actions/setup-build-env/action.yml
vendored
|
@ -8,13 +8,14 @@ runs:
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
sudo apt-get install gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev
|
||||||
|
|
||||||
- name: Install macOS Dependencies
|
- name: Install macOS Dependencies
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
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
|
- name: Linux runtime environment
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
|
|
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
|
@ -16,7 +16,9 @@ jobs:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
|
|
9
.github/workflows/extra-builds.yml
vendored
9
.github/workflows/extra-builds.yml
vendored
|
@ -25,7 +25,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
- name: Build
|
- name: Build
|
||||||
run: make vcxsrc YOSYS_VER=latest
|
run: make vcxsrc YOSYS_VER=latest
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
|
@ -35,7 +36,7 @@ jobs:
|
||||||
|
|
||||||
vs-build:
|
vs-build:
|
||||||
name: Visual Studio build
|
name: Visual Studio build
|
||||||
runs-on: windows-2019
|
runs-on: windows-latest
|
||||||
needs: [vs-prep, pre_job]
|
needs: [vs-prep, pre_job]
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: needs.pre_job.outputs.should_skip != 'true'
|
||||||
steps:
|
steps:
|
||||||
|
@ -59,7 +60,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
WASI_SDK=wasi-sdk-19.0
|
WASI_SDK=wasi-sdk-19.0
|
||||||
|
@ -95,6 +97,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
- uses: cachix/install-nix-action@v26
|
- uses: cachix/install-nix-action@v26
|
||||||
with:
|
with:
|
||||||
install_url: https://releases.nixos.org/nix/nix-2.18.1/install
|
install_url: https://releases.nixos.org/nix/nix-2.18.1/install
|
||||||
|
|
39
.github/workflows/prepare-docs.yml
vendored
39
.github/workflows/prepare-docs.yml
vendored
|
@ -1,12 +1,32 @@
|
||||||
name: Build docs artifact with Verific
|
name: Build docs artifact with Verific
|
||||||
|
|
||||||
on: push
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
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=${docs_export}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
prepare-docs:
|
prepare-docs:
|
||||||
# docs builds are needed for anything on main, any tagged versions, and any tag
|
# docs builds are needed for anything on main, any tagged versions, and any tag
|
||||||
# or branch starting with docs-preview
|
# 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]
|
runs-on: [self-hosted, linux, x64, fast]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
|
@ -27,12 +47,12 @@ jobs:
|
||||||
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
||||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
||||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||||
make -j${{ env.procs }} ENABLE_LTO=1
|
make -j$procs ENABLE_LTO=1
|
||||||
|
|
||||||
- name: Prepare docs
|
- name: Prepare docs
|
||||||
shell: bash
|
shell: bash
|
||||||
run:
|
run:
|
||||||
make docs/prep TARGETS= EXTRA_TARGETS=
|
make docs/prep -j$procs TARGETS= EXTRA_TARGETS=
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
@ -44,7 +64,18 @@ jobs:
|
||||||
docs/source/_images
|
docs/source/_images
|
||||||
docs/source/code_examples
|
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$procs TARGETS= EXTRA_TARGETS=
|
||||||
|
|
||||||
- name: Trigger RTDs build
|
- name: Trigger RTDs build
|
||||||
|
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' }}
|
||||||
uses: dfm/rtds-action@v1.1.0
|
uses: dfm/rtds-action@v1.1.0
|
||||||
with:
|
with:
|
||||||
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
|
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
|
||||||
|
|
34
.github/workflows/source-vendor.yml
vendored
Normal file
34
.github/workflows/source-vendor.yml
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
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'
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- 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
|
74
.github/workflows/test-build.yml
vendored
74
.github/workflows/test-build.yml
vendored
|
@ -40,12 +40,14 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest]
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
sanitizer: [undefined, address]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
@ -56,6 +58,7 @@ jobs:
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
make -f ../Makefile config-$CC
|
make -f ../Makefile config-$CC
|
||||||
|
echo 'SANITIZER = ${{ matrix.sanitizer }}' >> Makefile.conf
|
||||||
make -f ../Makefile -j$procs ENABLE_LTO=1
|
make -f ../Makefile -j$procs ENABLE_LTO=1
|
||||||
|
|
||||||
- name: Log yosys-config output
|
- name: Log yosys-config output
|
||||||
|
@ -71,7 +74,7 @@ jobs:
|
||||||
- name: Store build artifact
|
- name: Store build artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
|
||||||
path: build.tar
|
path: build.tar
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
|
@ -82,13 +85,18 @@ jobs:
|
||||||
if: needs.pre_job.outputs.should_skip != 'true'
|
if: needs.pre_job.outputs.should_skip != 'true'
|
||||||
env:
|
env:
|
||||||
CC: clang
|
CC: clang
|
||||||
|
ASAN_OPTIONS: halt_on_error=1
|
||||||
|
UBSAN_OPTIONS: halt_on_error=1
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest]
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
sanitizer: [undefined, address]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
@ -100,12 +108,22 @@ jobs:
|
||||||
cd iverilog
|
cd iverilog
|
||||||
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
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
|
- name: Cache iverilog
|
||||||
id: cache-iverilog
|
id: cache-iverilog
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: .local/
|
path: .local/
|
||||||
key: ${{ matrix.os }}-${{ env.IVERILOG_GIT }}
|
key: ${{ matrix.os }}-${IVERILOG_GIT}
|
||||||
|
|
||||||
- name: Build iverilog
|
- name: Build iverilog
|
||||||
if: steps.cache-iverilog.outputs.cache-hit != 'true'
|
if: steps.cache-iverilog.outputs.cache-hit != 'true'
|
||||||
|
@ -121,7 +139,7 @@ jobs:
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
|
||||||
|
|
||||||
- name: Uncompress build
|
- name: Uncompress build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -153,10 +171,13 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
|
sanitizer: [undefined, address]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
@ -164,7 +185,7 @@ jobs:
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: build-${{ matrix.os }}
|
name: build-${{ matrix.os }}-${{ matrix.sanitizer }}
|
||||||
|
|
||||||
- name: Uncompress build
|
- name: Uncompress build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -178,4 +199,47 @@ jobs:
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make -C docs test -j${{ env.procs }}
|
make -C docs test -j$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
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Runtime environment
|
||||||
|
run: |
|
||||||
|
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build Yosys
|
||||||
|
run: |
|
||||||
|
make config-clang
|
||||||
|
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||||
|
make -j$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$procs
|
||||||
|
|
||||||
|
- name: Store docs build artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docs-build-${{ matrix.docs-target }}
|
||||||
|
path: docs/build/
|
||||||
|
retention-days: 7
|
||||||
|
|
14
.github/workflows/test-compile.yml
vendored
14
.github/workflows/test-compile.yml
vendored
|
@ -30,24 +30,22 @@ jobs:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
compiler:
|
compiler:
|
||||||
# oldest supported
|
# oldest supported
|
||||||
- 'clang-14'
|
- 'clang-10'
|
||||||
- 'gcc-10'
|
- 'gcc-10'
|
||||||
# newest
|
# newest, make sure to update maximum standard step to match
|
||||||
- 'clang'
|
- 'clang-19'
|
||||||
- 'gcc'
|
- 'gcc-13'
|
||||||
include:
|
include:
|
||||||
# macOS
|
# macOS
|
||||||
- os: macos-13
|
- os: macos-13
|
||||||
compiler: 'clang'
|
compiler: 'clang'
|
||||||
# oldest clang not available on ubuntu-latest
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
compiler: 'clang-10'
|
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Yosys
|
- name: Checkout Yosys
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
@ -72,7 +70,7 @@ jobs:
|
||||||
|
|
||||||
# maximum standard, only on newest compilers
|
# maximum standard, only on newest compilers
|
||||||
- name: Build C++20
|
- name: Build C++20
|
||||||
if: ${{ matrix.compiler == 'clang' || matrix.compiler == 'gcc'}}
|
if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-13' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
make config-$CC_SHORT
|
make config-$CC_SHORT
|
||||||
|
|
5
.github/workflows/test-verific.yml
vendored
5
.github/workflows/test-verific.yml
vendored
|
@ -40,7 +40,7 @@ jobs:
|
||||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
||||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||||
echo "ENABLE_FUNCTIONAL_TESTS := 1" >> Makefile.conf
|
echo "ENABLE_FUNCTIONAL_TESTS := 1" >> Makefile.conf
|
||||||
make -j${{ env.procs }} ENABLE_LTO=1
|
make -j$procs ENABLE_LTO=1
|
||||||
|
|
||||||
- name: Install Yosys
|
- name: Install Yosys
|
||||||
run: |
|
run: |
|
||||||
|
@ -51,6 +51,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
repository: 'YosysHQ/sby'
|
repository: 'YosysHQ/sby'
|
||||||
path: 'sby'
|
path: 'sby'
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Build SBY
|
- name: Build SBY
|
||||||
run: |
|
run: |
|
||||||
|
@ -58,7 +59,7 @@ jobs:
|
||||||
|
|
||||||
- name: Run Yosys tests
|
- name: Run Yosys tests
|
||||||
run: |
|
run: |
|
||||||
make -j${{ env.procs }} test
|
make -j$procs test
|
||||||
|
|
||||||
- name: Run Verific specific Yosys tests
|
- name: Run Verific specific Yosys tests
|
||||||
run: |
|
run: |
|
||||||
|
|
2
.github/workflows/update-flake-lock.yml
vendored
2
.github/workflows/update-flake-lock.yml
vendored
|
@ -10,6 +10,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@main
|
||||||
- name: Update flake.lock
|
- name: Update flake.lock
|
||||||
|
|
1
.github/workflows/version.yml
vendored
1
.github/workflows/version.yml
vendored
|
@ -14,6 +14,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
submodules: true
|
||||||
|
persist-credentials: false
|
||||||
- name: Take last commit
|
- name: Take last commit
|
||||||
id: log
|
id: log
|
||||||
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
|
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
|
||||||
|
|
137
.github/workflows/wheels.yml
vendored
Normal file
137
.github/workflows/wheels.yml
vendored
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
name: Build Wheels for PyPI
|
||||||
|
|
||||||
|
# run every Sunday at 10 AM
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 10 * * 0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_wheels:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [
|
||||||
|
{
|
||||||
|
name: "Ubuntu 22.04",
|
||||||
|
family: "linux",
|
||||||
|
runner: "ubuntu-22.04",
|
||||||
|
archs: "x86_64",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ubuntu 22.04",
|
||||||
|
family: "linux",
|
||||||
|
runner: "ubuntu-22.04-arm",
|
||||||
|
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
|
||||||
|
persist-credentials: false
|
||||||
|
- 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
|
70
.gitignore
vendored
70
.gitignore
vendored
|
@ -1,24 +1,19 @@
|
||||||
|
## user config
|
||||||
|
/Makefile.conf
|
||||||
|
|
||||||
|
## build artifacts
|
||||||
|
# compiler intermediate files
|
||||||
*.o
|
*.o
|
||||||
*.d
|
*.d
|
||||||
*.dwo
|
*.dwo
|
||||||
.*.swp
|
|
||||||
*.gch
|
*.gch
|
||||||
*.gcda
|
*.gcda
|
||||||
*.gcno
|
*.gcno
|
||||||
*~
|
*.so.dSYM/
|
||||||
__pycache__
|
|
||||||
/.cproject
|
# compiler output files
|
||||||
/.project
|
/kernel/version_*.cc
|
||||||
/.settings
|
/share
|
||||||
/qtcreator.files
|
|
||||||
/qtcreator.includes
|
|
||||||
/qtcreator.config
|
|
||||||
/qtcreator.creator
|
|
||||||
/qtcreator.creator.user
|
|
||||||
/coverage.info
|
|
||||||
/coverage_html
|
|
||||||
/Makefile.conf
|
|
||||||
/viz.js
|
|
||||||
/yosys
|
/yosys
|
||||||
/yosys.exe
|
/yosys.exe
|
||||||
/yosys.js
|
/yosys.js
|
||||||
|
@ -34,15 +29,50 @@ __pycache__
|
||||||
/yosys-witness-script.py
|
/yosys-witness-script.py
|
||||||
/yosys-filterlib
|
/yosys-filterlib
|
||||||
/yosys-filterlib.exe
|
/yosys-filterlib.exe
|
||||||
/kernel/*.pyh
|
|
||||||
/kernel/python_wrappers.cc
|
|
||||||
/kernel/version_*.cc
|
|
||||||
/share
|
|
||||||
/yosys-win32-mxebin-*
|
/yosys-win32-mxebin-*
|
||||||
/yosys-win32-vcxsrc-*
|
/yosys-win32-vcxsrc-*
|
||||||
/yosysjs-*
|
/yosysjs-*
|
||||||
/libyosys.so
|
/libyosys.so
|
||||||
|
|
||||||
|
# build directories
|
||||||
/tests/unit/bintest/
|
/tests/unit/bintest/
|
||||||
/tests/unit/objtest/
|
/tests/unit/objtest/
|
||||||
/tests/ystests
|
/tests/ystests
|
||||||
/result
|
/build
|
||||||
|
/result
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# pyosys
|
||||||
|
/kernel/*.pyh
|
||||||
|
/kernel/python_wrappers.cc
|
||||||
|
/boost
|
||||||
|
/ffi
|
||||||
|
/venv
|
||||||
|
/*.whl
|
||||||
|
/*.egg-info
|
||||||
|
|
||||||
|
# yosysjs dependency
|
||||||
|
/viz.js
|
||||||
|
|
||||||
|
# other
|
||||||
|
/coverage.info
|
||||||
|
/coverage_html
|
||||||
|
|
||||||
|
|
||||||
|
# these really belong in global gitignore since they're not specific to this project but rather to user tool choice
|
||||||
|
# but too many people don't have a global gitignore configured:
|
||||||
|
# https://docs.github.com/en/get-started/git-basics/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer
|
||||||
|
__pycache__
|
||||||
|
*~
|
||||||
|
.*.swp
|
||||||
|
/.cache
|
||||||
|
/.vscode
|
||||||
|
/.cproject
|
||||||
|
/.project
|
||||||
|
/.settings
|
||||||
|
/qtcreator.files
|
||||||
|
/qtcreator.includes
|
||||||
|
/qtcreator.config
|
||||||
|
/qtcreator.creator
|
||||||
|
/qtcreator.creator.user
|
||||||
|
/compile_commands.json
|
||||||
|
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -1,3 +1,7 @@
|
||||||
[submodule "abc"]
|
[submodule "abc"]
|
||||||
path = abc
|
path = abc
|
||||||
url = https://github.com/YosysHQ/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
|
||||||
|
|
6
.mailmap
6
.mailmap
|
@ -1,6 +1,6 @@
|
||||||
Marcelina Kościelnicka <mwk@0x04.net>
|
Wanda Phinode <wanda@phinode.net> <mwk@0x04.net>
|
||||||
Marcelina Kościelnicka <mwk@0x04.net> <koriakin@0x04.net>
|
Wanda Phinode <wanda@phinode.net> <koriakin@0x04.net>
|
||||||
Marcelina Kościelnicka <mwk@0x04.net> <marcin@symbioticeda.com>
|
Wanda Phinode <wanda@phinode.net> <marcin@symbioticeda.com>
|
||||||
Claire Xenia Wolf <claire@yosyshq.com> <claire@clairexen.net>
|
Claire Xenia Wolf <claire@yosyshq.com> <claire@clairexen.net>
|
||||||
Claire Xenia Wolf <claire@yosyshq.com> <claire@symbioticeda.com>
|
Claire Xenia Wolf <claire@yosyshq.com> <claire@symbioticeda.com>
|
||||||
Claire Xenia Wolf <claire@yosyshq.com> <clifford@symbioticeda.com>
|
Claire Xenia Wolf <claire@yosyshq.com> <clifford@symbioticeda.com>
|
||||||
|
|
1
Brewfile
1
Brewfile
|
@ -11,3 +11,4 @@ brew "xdot"
|
||||||
brew "bash"
|
brew "bash"
|
||||||
brew "boost-python3"
|
brew "boost-python3"
|
||||||
brew "llvm"
|
brew "llvm"
|
||||||
|
brew "lld"
|
||||||
|
|
159
CHANGELOG
159
CHANGELOG
|
@ -2,9 +2,166 @@
|
||||||
List of major changes and improvements between releases
|
List of major changes and improvements between releases
|
||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
Yosys 0.45 .. Yosys 0.46-dev
|
Yosys 0.55 .. Yosys 0.56-dev
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
Yosys 0.54 .. Yosys 0.55
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- read_verilog: Implemented SystemVerilog unique/priority if.
|
||||||
|
- "attrmap" pass is able to alter memory attributes.
|
||||||
|
- verific: Support SVA followed-by operator in cover mode.
|
||||||
|
|
||||||
|
Yosys 0.53 .. Yosys 0.54
|
||||||
|
--------------------------
|
||||||
|
* New commands and options
|
||||||
|
- Added "-genlib" option to "abc_new" and "abc9_exe" passes.
|
||||||
|
- Added "-verbose" and "-quiet" options to "libcache" pass.
|
||||||
|
- Added "-no-sort" option to "write_aiger" pass.
|
||||||
|
|
||||||
|
* Various
|
||||||
|
- Added "muldiv_c" peepopt.
|
||||||
|
- Accept (and ignore) SystemVerilog unique/priority if.
|
||||||
|
- "read_verilog" copy inout ports in and out of functions/tasks.
|
||||||
|
- Enable single-bit vector wires in RTLIL.
|
||||||
|
|
||||||
|
* Xilinx support
|
||||||
|
- Single-port URAM mapping to support memories 2048 x 144b
|
||||||
|
|
||||||
|
Yosys 0.52 .. Yosys 0.53
|
||||||
|
--------------------------
|
||||||
|
* New commands and options
|
||||||
|
- Added "constmap" pass for technology mapping of coarse constant value.
|
||||||
|
- Added "timeest" pass to estimate the critical path in clock domain.
|
||||||
|
- Added "-blackbox" option to "cutpoint" pass to cut all instances of
|
||||||
|
blackboxes.
|
||||||
|
- Added "-noscopeinfo" option to "cutpoint" pass.
|
||||||
|
- Added "-nocleanup" option to "flatten" pass to prevent removal of
|
||||||
|
unused submodules.
|
||||||
|
- Added "-declockgate" option to "formalff" pass that turns clock
|
||||||
|
gating into clock enables.
|
||||||
|
|
||||||
|
* Various
|
||||||
|
- Added "$scopeinfo" cells to preserve information during "cutpoint" pass.
|
||||||
|
- Added dataflow tracking documentation.
|
||||||
|
- share: Restrict activation patterns to potentially relevant signal.
|
||||||
|
- liberty: More robust parsing.
|
||||||
|
- verific: bit blast RAM if using mem2reg attribute.
|
||||||
|
|
||||||
|
Yosys 0.51 .. Yosys 0.52
|
||||||
|
--------------------------
|
||||||
|
* New commands and options
|
||||||
|
- Added "-pattern-limit" option to "share" pass to limit analysis effort.
|
||||||
|
- Added "libcache" pass to control caching of technology library
|
||||||
|
data parsed from liberty files.
|
||||||
|
- Added "read_verilog_file_list" to parse verilog file list.
|
||||||
|
|
||||||
|
* Various
|
||||||
|
- Added $macc_v2 cell.
|
||||||
|
- Improve lexer performance and zlib support for "read_liberty".
|
||||||
|
- opt_expr: optimize pow of 2 cells.
|
||||||
|
|
||||||
|
|
||||||
|
Yosys 0.50 .. Yosys 0.51
|
||||||
|
--------------------------
|
||||||
|
* New commands and options
|
||||||
|
- Added "abstract" pass to allow reducing and never increasing
|
||||||
|
the constraints on a circuit's behavior in a formal verification setting.
|
||||||
|
|
||||||
|
* Various
|
||||||
|
- "splitcells" pass now splits "aldff" cells.
|
||||||
|
- FunctionalIR documentation
|
||||||
|
|
||||||
|
* QuickLogic support
|
||||||
|
- Added IOFF inference for qlf_k6n10f
|
||||||
|
|
||||||
|
* Intel support
|
||||||
|
- Fixed RAM and DSP support.
|
||||||
|
- Overall performance improvement for "synth_intel".
|
||||||
|
|
||||||
|
Yosys 0.49 .. Yosys 0.50
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- "write_verilog" emits "$check" cell names as labels.
|
||||||
|
|
||||||
|
Yosys 0.48 .. Yosys 0.49
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- "$scopeinfo" cells are now part of JSON export by default.
|
||||||
|
- Added option to specify hierarchical separator for "flatten".
|
||||||
|
- Improved "wreduce" to handle more cases of operator size reduction.
|
||||||
|
- Updated hashing interface, see docs/source/yosys_internals/hashing.rst
|
||||||
|
for breaking API changes.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "-noscopeinfo" option to "json" and "write_json" pass.
|
||||||
|
|
||||||
|
Yosys 0.47 .. Yosys 0.48
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- Removed "read_ilang" deprecated pass.
|
||||||
|
- Enhanced boxing features in the experimental "abc_new" command.
|
||||||
|
- Added new Tcl methods for design inspection.
|
||||||
|
- Added clock enable inference to "dfflibmap".
|
||||||
|
- Added a Han-Carlson and Sklansky option for $lcu mapping.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "-nopeepopt" option to "clk2fflogic" pass.
|
||||||
|
- Added "-liberty" and "-dont_use" options to "clockgate" pass.
|
||||||
|
- Added "-ignore_buses" option to "read_liberty" pass.
|
||||||
|
- Added "-dont_map" option to "techmap" pass.
|
||||||
|
- Added "-selected" option to "write_json" pass.
|
||||||
|
- Added "wrapcell" command for creating wrapper modules
|
||||||
|
around selected cells.
|
||||||
|
- Added "portarcs" command for deriving propagation timing arcs.
|
||||||
|
- Added "setenv" command for setting environment variables.
|
||||||
|
|
||||||
|
* Gowin support
|
||||||
|
- Added "-family" option to "synth_gowin" pass.
|
||||||
|
- Cell definitions split by family.
|
||||||
|
|
||||||
|
* Verific support
|
||||||
|
- Improved blackbox support.
|
||||||
|
|
||||||
|
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
|
Yosys 0.44 .. Yosys 0.45
|
||||||
--------------------------
|
--------------------------
|
||||||
* Various
|
* Various
|
||||||
|
|
|
@ -20,6 +20,7 @@ passes/opt/opt_lut.cc @whitequark
|
||||||
passes/techmap/abc9*.cc @eddiehung @Ravenslofty
|
passes/techmap/abc9*.cc @eddiehung @Ravenslofty
|
||||||
backends/aiger/xaiger.cc @eddiehung
|
backends/aiger/xaiger.cc @eddiehung
|
||||||
docs/ @KrystalDelusion
|
docs/ @KrystalDelusion
|
||||||
|
docs/source/using_yosys/synthesis/abc.rst @KrystalDelusion @Ravenslofty
|
||||||
.github/workflows/*.yml @mmicko
|
.github/workflows/*.yml @mmicko
|
||||||
|
|
||||||
## External Contributors
|
## External Contributors
|
||||||
|
|
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at contact@yosyshq.com and/or
|
||||||
|
claire@clairexen.net.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
73
CONTRIBUTING.md
Normal file
73
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
Thanks for thinking about contributing to the Yosys project. If this is your
|
||||||
|
first time contributing to an open source project, please take a look at the
|
||||||
|
following guide:
|
||||||
|
https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project.
|
||||||
|
|
||||||
|
Information about the Yosys coding style is available on our Read the Docs:
|
||||||
|
https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html.
|
||||||
|
|
||||||
|
# Using the issue tracker
|
||||||
|
|
||||||
|
The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for
|
||||||
|
tracking bugs or other problems with Yosys or its documentation. It is also the
|
||||||
|
place to go for requesting new features.
|
||||||
|
When [creating a new issue](https://github.com/YosysHQ/yosys/issues/new/choose),
|
||||||
|
we have a few templates available. Please make use of these! It will make it
|
||||||
|
much easier for someone to respond and help.
|
||||||
|
|
||||||
|
### Bug reports
|
||||||
|
|
||||||
|
Before you submit an issue, please have a search of the existing issues in case
|
||||||
|
one already exists. Making sure that you have a minimal, complete and
|
||||||
|
verifiable example (MVCE) is a great way to quickly check an existing issue
|
||||||
|
against a new one. Stack overflow has a guide on [how to create an
|
||||||
|
MVCE](https://stackoverflow.com/help/minimal-reproducible-example). The
|
||||||
|
[`bugpoint`
|
||||||
|
command](https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/bugpoint.html)
|
||||||
|
in Yosys can be helpful for this process.
|
||||||
|
|
||||||
|
|
||||||
|
# Using pull requests
|
||||||
|
|
||||||
|
If you are working on something to add to Yosys, or fix something that isn't
|
||||||
|
working quite right, make a [PR](https://github.com/YosysHQ/yosys/pulls)! An
|
||||||
|
open PR, even as a draft, tells everyone that you're working on it and they
|
||||||
|
don't have to. It can also be a useful way to solicit feedback on in-progress
|
||||||
|
changes. See below to find the best way to [ask us
|
||||||
|
questions](#asking-questions).
|
||||||
|
|
||||||
|
In general, all changes to the code are done as a PR, with [Continuous
|
||||||
|
Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools that
|
||||||
|
automatically run the full suite of tests compiling and running Yosys. Please
|
||||||
|
make use of this! If you're adding a feature: add a test! Not only does it
|
||||||
|
verify that your feature is working as expected, but it can also be a handy way
|
||||||
|
for people to see how the feature is used. If you're fixing a bug: add a test!
|
||||||
|
If you can, do this first; it's okay if the test starts off failing - you
|
||||||
|
already know there is a bug. CI also helps to make sure that your changes still
|
||||||
|
work under a range of compilers, settings, and targets.
|
||||||
|
|
||||||
|
|
||||||
|
### Labels
|
||||||
|
|
||||||
|
We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise
|
||||||
|
issues and PRs. If a label seems relevant to your work, please do add it; this
|
||||||
|
also includes the labels beggining with 'status-'. The 'merge-' labels are used
|
||||||
|
by maintainers for tracking and communicating which PRs are ready and pending
|
||||||
|
merge; please do not use these labels if you are not a maintainer.
|
||||||
|
|
||||||
|
|
||||||
|
# Asking questions
|
||||||
|
|
||||||
|
If you have a question about how to use Yosys, please ask on our [discussions
|
||||||
|
page](https://github.com/YosysHQ/yosys/discussions) or in our [community
|
||||||
|
slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA).
|
||||||
|
The slack is also a great place to ask questions about developing or
|
||||||
|
contributing to Yosys.
|
||||||
|
|
||||||
|
We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the
|
||||||
|
community come together to discuss open issues and PRs. This is also a good
|
||||||
|
place to talk to us about how to implement larger PRs. Please join the
|
||||||
|
community slack if you would like to join the next meeting, the link is
|
||||||
|
available in the description of the #devel-discuss channel.
|
2
COPYING
2
COPYING
|
@ -1,6 +1,6 @@
|
||||||
ISC License
|
ISC License
|
||||||
|
|
||||||
Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.com>
|
Copyright (C) 2012 - 2025 Claire Xenia Wolf <claire@yosyshq.com>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|
398
Makefile
398
Makefile
|
@ -2,9 +2,7 @@
|
||||||
CONFIG := none
|
CONFIG := none
|
||||||
# CONFIG := clang
|
# CONFIG := clang
|
||||||
# CONFIG := gcc
|
# CONFIG := gcc
|
||||||
# CONFIG := afl-gcc
|
|
||||||
# CONFIG := wasi
|
# CONFIG := wasi
|
||||||
# CONFIG := mxe
|
|
||||||
# CONFIG := msys2-32
|
# CONFIG := msys2-32
|
||||||
# CONFIG := msys2-64
|
# CONFIG := msys2-64
|
||||||
|
|
||||||
|
@ -104,6 +102,7 @@ LIBS := $(LIBS) -lstdc++ -lm
|
||||||
PLUGIN_LINKFLAGS :=
|
PLUGIN_LINKFLAGS :=
|
||||||
PLUGIN_LIBS :=
|
PLUGIN_LIBS :=
|
||||||
EXE_LINKFLAGS :=
|
EXE_LINKFLAGS :=
|
||||||
|
EXE_LIBS :=
|
||||||
ifeq ($(OS), MINGW)
|
ifeq ($(OS), MINGW)
|
||||||
EXE_LINKFLAGS := -Wl,--export-all-symbols -Wl,--out-implib,libyosys_exe.a
|
EXE_LINKFLAGS := -Wl,--export-all-symbols -Wl,--out-implib,libyosys_exe.a
|
||||||
PLUGIN_LINKFLAGS += -L"$(LIBDIR)"
|
PLUGIN_LINKFLAGS += -L"$(LIBDIR)"
|
||||||
|
@ -116,16 +115,23 @@ BISON ?= bison
|
||||||
STRIP ?= strip
|
STRIP ?= strip
|
||||||
AWK ?= awk
|
AWK ?= awk
|
||||||
|
|
||||||
|
ifneq ($(shell :; command -v rsync),)
|
||||||
|
RSYNC_CP ?= rsync -rc
|
||||||
|
else
|
||||||
|
RSYNC_CP ?= cp -ru
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(OS), Darwin)
|
ifeq ($(OS), Darwin)
|
||||||
PLUGIN_LINKFLAGS += -undefined dynamic_lookup
|
PLUGIN_LINKFLAGS += -undefined dynamic_lookup
|
||||||
|
LINKFLAGS += -rdynamic
|
||||||
|
|
||||||
# homebrew search paths
|
# homebrew search paths
|
||||||
ifneq ($(shell :; command -v brew),)
|
ifneq ($(shell :; command -v brew),)
|
||||||
BREW_PREFIX := $(shell brew --prefix)/opt
|
BREW_PREFIX := $(shell brew --prefix)/opt
|
||||||
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
|
CXXFLAGS += -I$(BREW_PREFIX)/boost/include
|
||||||
LINKFLAGS += -L$(BREW_PREFIX)/boost/lib
|
LINKFLAGS += -L$(BREW_PREFIX)/boost/lib -L$(BREW_PREFIX)/boost-python3/lib
|
||||||
endif
|
endif
|
||||||
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
|
||||||
LINKFLAGS += -L$(BREW_PREFIX)/readline/lib
|
LINKFLAGS += -L$(BREW_PREFIX)/readline/lib
|
||||||
|
@ -154,7 +160,14 @@ ifeq ($(OS), Haiku)
|
||||||
CXXFLAGS += -D_DEFAULT_SOURCE
|
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
YOSYS_VER := 0.45+106
|
YOSYS_VER := 0.55+146
|
||||||
|
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
||||||
|
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
|
||||||
|
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
|
||||||
|
CXXFLAGS += -DYOSYS_VER=\\"$(YOSYS_VER)\\" \
|
||||||
|
-DYOSYS_MAJOR=$(YOSYS_MAJOR) \
|
||||||
|
-DYOSYS_MINOR=$(YOSYS_MINOR) \
|
||||||
|
-DYOSYS_COMMIT=$(YOSYS_COMMIT)
|
||||||
|
|
||||||
# Note: We arrange for .gitcommit to contain the (short) commit hash in
|
# Note: We arrange for .gitcommit to contain the (short) commit hash in
|
||||||
# tarballs generated with git-archive(1) using .gitattributes. The git repo
|
# tarballs generated with git-archive(1) using .gitattributes. The git repo
|
||||||
|
@ -170,7 +183,7 @@ endif
|
||||||
OBJS = kernel/version_$(GIT_REV).o
|
OBJS = kernel/version_$(GIT_REV).o
|
||||||
|
|
||||||
bumpversion:
|
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 60f126c.. | wc -l`/;" Makefile
|
||||||
|
|
||||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
|
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
|
||||||
|
|
||||||
|
@ -191,17 +204,17 @@ endif
|
||||||
include Makefile.conf
|
include Makefile.conf
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
|
PYTHON_EXECUTABLE ?= $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
|
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
|
||||||
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
|
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
|
||||||
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
|
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
|
||||||
|
|
||||||
ENABLE_PYTHON_CONFIG_EMBED ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1)
|
|
||||||
ifeq ($(ENABLE_PYTHON_CONFIG_EMBED),1)
|
|
||||||
PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config --embed
|
|
||||||
else
|
|
||||||
PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config
|
PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config
|
||||||
|
PYTHON_CONFIG_FOR_EXE := $(PYTHON_CONFIG)
|
||||||
|
PYTHON_CONFIG_EMBED_AVAILABLE ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1)
|
||||||
|
ifeq ($(PYTHON_CONFIG_EMBED_AVAILABLE),1)
|
||||||
|
PYTHON_CONFIG_FOR_EXE := $(PYTHON_CONFIG) --embed
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PYTHON_DESTDIR := $(shell $(PYTHON_EXECUTABLE) -c "import site; print(site.getsitepackages()[-1]);")
|
PYTHON_DESTDIR := $(shell $(PYTHON_EXECUTABLE) -c "import site; print(site.getsitepackages()[-1]);")
|
||||||
|
@ -264,16 +277,6 @@ ifeq ($(DISABLE_ABC_THREADS),1)
|
||||||
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
|
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
else ifeq ($(CONFIG),afl-gcc)
|
|
||||||
CXX = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
|
|
||||||
CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL)
|
|
||||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
|
||||||
|
|
||||||
else ifeq ($(CONFIG),cygwin)
|
|
||||||
CXX = g++
|
|
||||||
CXXFLAGS += -std=gnu++11 $(OPT_LEVEL)
|
|
||||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
|
|
||||||
|
|
||||||
else ifeq ($(CONFIG),wasi)
|
else ifeq ($(CONFIG),wasi)
|
||||||
ifeq ($(WASI_SDK),)
|
ifeq ($(WASI_SDK),)
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
|
@ -301,25 +304,13 @@ LINK_ABC := 1
|
||||||
DISABLE_ABC_THREADS := 1
|
DISABLE_ABC_THREADS := 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
else ifeq ($(CONFIG),mxe)
|
|
||||||
PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config
|
|
||||||
CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
|
|
||||||
CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) -D_POSIX_SOURCE -DYOSYS_MXE_HACKS -Wno-attributes
|
|
||||||
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
|
||||||
LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s
|
|
||||||
LIBS := $(filter-out -lrt,$(LIBS))
|
|
||||||
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
|
||||||
# TODO: Try to solve pthread linking issue in more appropriate way
|
|
||||||
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LINKFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
|
|
||||||
EXE = .exe
|
|
||||||
|
|
||||||
else ifeq ($(CONFIG),msys2-32)
|
else ifeq ($(CONFIG),msys2-32)
|
||||||
CXX = i686-w64-mingw32-g++
|
CXX = i686-w64-mingw32-g++
|
||||||
CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
|
CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
|
||||||
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
||||||
LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s
|
LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s
|
||||||
LIBS := $(filter-out -lrt,$(LIBS))
|
LIBS := $(filter-out -lrt,$(LIBS))
|
||||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DWIN32 -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||||
ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
|
ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
|
||||||
EXE = .exe
|
EXE = .exe
|
||||||
|
|
||||||
|
@ -329,7 +320,7 @@ CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
|
||||||
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
|
||||||
LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s
|
LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s
|
||||||
LIBS := $(filter-out -lrt,$(LIBS))
|
LIBS := $(filter-out -lrt,$(LIBS))
|
||||||
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DWIN32 -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
|
||||||
ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
|
ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
|
||||||
EXE = .exe
|
EXE = .exe
|
||||||
|
|
||||||
|
@ -339,7 +330,7 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H $(ABC_ARCHFLAGS)"
|
||||||
LTOFLAGS =
|
LTOFLAGS =
|
||||||
|
|
||||||
else
|
else
|
||||||
$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, mxe, msys2-32, msys2-64, none)
|
$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, msys2-32, msys2-64, none)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -353,8 +344,14 @@ TARGETS += libyosys.so
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
|
# python-config --ldflags includes -l and -L, but LINKFLAGS is only -L
|
||||||
|
LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags))
|
||||||
|
LIBS += $(shell $(PYTHON_CONFIG) --libs)
|
||||||
|
EXE_LIBS += $(filter-out $(LIBS),$(shell $(PYTHON_CONFIG_FOR_EXE) --libs))
|
||||||
|
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
|
||||||
|
|
||||||
# Detect name of boost_python library. Some distros use boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
|
# Detect name of boost_python library. Some distros use boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
|
||||||
CHECK_BOOST_PYTHON = (echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -l$(1) - > /dev/null 2>&1 && echo "-l$(1)")
|
CHECK_BOOST_PYTHON = (echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(LINKFLAGS) $(EXE_LIBS) $(LIBS) -l$(1) - > /dev/null 2>&1 && echo "-l$(1)")
|
||||||
BOOST_PYTHON_LIB ?= $(shell \
|
BOOST_PYTHON_LIB ?= $(shell \
|
||||||
$(call CHECK_BOOST_PYTHON,boost_python-py$(subst .,,$(PYTHON_VERSION))) || \
|
$(call CHECK_BOOST_PYTHON,boost_python-py$(subst .,,$(PYTHON_VERSION))) || \
|
||||||
$(call CHECK_BOOST_PYTHON,boost_python-py$(PYTHON_MAJOR_VERSION)) || \
|
$(call CHECK_BOOST_PYTHON,boost_python-py$(PYTHON_MAJOR_VERSION)) || \
|
||||||
|
@ -366,15 +363,11 @@ ifeq ($(BOOST_PYTHON_LIB),)
|
||||||
$(error BOOST_PYTHON_LIB could not be detected. Please define manually)
|
$(error BOOST_PYTHON_LIB could not be detected. Please define manually)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
LIBS += $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
|
||||||
# python-config --ldflags includes LIBS for some reason
|
|
||||||
LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags))
|
|
||||||
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
|
|
||||||
|
|
||||||
PY_WRAPPER_FILE = kernel/python_wrappers
|
PY_WRAPPER_FILE = kernel/python_wrappers
|
||||||
OBJS += $(PY_WRAPPER_FILE).o
|
OBJS += $(PY_WRAPPER_FILE).o
|
||||||
PY_GEN_SCRIPT= py_wrap_generator
|
PY_GEN_SCRIPT= py_wrap_generator
|
||||||
PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
|
PY_WRAP_INCLUDES := $(shell $(PYTHON_EXECUTABLE) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
|
||||||
endif # ENABLE_PYOSYS
|
endif # ENABLE_PYOSYS
|
||||||
|
|
||||||
ifeq ($(ENABLE_READLINE),1)
|
ifeq ($(ENABLE_READLINE),1)
|
||||||
|
@ -391,22 +384,22 @@ ifeq ($(LINK_TERMCAP),1)
|
||||||
LIBS += -ltermcap
|
LIBS += -ltermcap
|
||||||
ABCMKARGS += "ABC_READLINE_LIBRARIES=-lreadline -ltermcap"
|
ABCMKARGS += "ABC_READLINE_LIBRARIES=-lreadline -ltermcap"
|
||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG),mxe)
|
|
||||||
LIBS += -ltermcap
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
ifeq ($(ENABLE_EDITLINE),1)
|
ifeq ($(ENABLE_EDITLINE),1)
|
||||||
CXXFLAGS += -DYOSYS_ENABLE_EDITLINE
|
CXXFLAGS += -DYOSYS_ENABLE_EDITLINE
|
||||||
LIBS += -ledit -ltinfo -lbsd
|
LIBS += -ledit
|
||||||
else
|
|
||||||
ABCMKARGS += "ABC_USE_NO_READLINE=1"
|
|
||||||
endif
|
endif
|
||||||
|
ABCMKARGS += "ABC_USE_NO_READLINE=1"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(DISABLE_ABC_THREADS),1)
|
ifeq ($(DISABLE_ABC_THREADS),1)
|
||||||
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
|
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(LINK_ABC),1)
|
||||||
|
ABCMKARGS += "ABC_USE_PIC=1"
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(DISABLE_SPAWN),1)
|
ifeq ($(DISABLE_SPAWN),1)
|
||||||
CXXFLAGS += -DYOSYS_DISABLE_SPAWN
|
CXXFLAGS += -DYOSYS_DISABLE_SPAWN
|
||||||
endif
|
endif
|
||||||
|
@ -443,12 +436,10 @@ TCL_INCLUDE ?= /usr/include/$(TCL_VERSION)
|
||||||
TCL_LIBS ?= -l$(TCL_VERSION)
|
TCL_LIBS ?= -l$(TCL_VERSION)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG),mxe)
|
|
||||||
CXXFLAGS += -DYOSYS_ENABLE_TCL
|
|
||||||
LIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
|
|
||||||
else
|
|
||||||
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
|
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
|
||||||
LIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo $(TCL_LIBS))
|
LIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo $(TCL_LIBS))
|
||||||
|
ifneq (,$(findstring TCL_WITH_EXTERNAL_TOMMATH,$(CXXFLAGS)))
|
||||||
|
LIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libtommath || echo)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -464,6 +455,7 @@ endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_DEBUG),1)
|
ifeq ($(ENABLE_DEBUG),1)
|
||||||
CXXFLAGS := -Og -DDEBUG $(filter-out $(OPT_LEVEL),$(CXXFLAGS))
|
CXXFLAGS := -Og -DDEBUG $(filter-out $(OPT_LEVEL),$(CXXFLAGS))
|
||||||
|
STRIP :=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_ABC),1)
|
ifeq ($(ENABLE_ABC),1)
|
||||||
|
@ -607,7 +599,9 @@ $(eval $(call add_include_file,kernel/fmt.h))
|
||||||
ifeq ($(ENABLE_ZLIB),1)
|
ifeq ($(ENABLE_ZLIB),1)
|
||||||
$(eval $(call add_include_file,kernel/fstdata.h))
|
$(eval $(call add_include_file,kernel/fstdata.h))
|
||||||
endif
|
endif
|
||||||
|
$(eval $(call add_include_file,kernel/gzip.h))
|
||||||
$(eval $(call add_include_file,kernel/hashlib.h))
|
$(eval $(call add_include_file,kernel/hashlib.h))
|
||||||
|
$(eval $(call add_include_file,kernel/io.h))
|
||||||
$(eval $(call add_include_file,kernel/json.h))
|
$(eval $(call add_include_file,kernel/json.h))
|
||||||
$(eval $(call add_include_file,kernel/log.h))
|
$(eval $(call add_include_file,kernel/log.h))
|
||||||
$(eval $(call add_include_file,kernel/macc.h))
|
$(eval $(call add_include_file,kernel/macc.h))
|
||||||
|
@ -633,13 +627,14 @@ endif
|
||||||
$(eval $(call add_include_file,libs/sha1/sha1.h))
|
$(eval $(call add_include_file,libs/sha1/sha1.h))
|
||||||
$(eval $(call add_include_file,libs/json11/json11.hpp))
|
$(eval $(call add_include_file,libs/json11/json11.hpp))
|
||||||
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
|
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
|
||||||
|
$(eval $(call add_include_file,passes/techmap/libparse.h))
|
||||||
$(eval $(call add_include_file,frontends/ast/ast.h))
|
$(eval $(call add_include_file,frontends/ast/ast.h))
|
||||||
$(eval $(call add_include_file,frontends/ast/ast_binding.h))
|
$(eval $(call add_include_file,frontends/ast/ast_binding.h))
|
||||||
$(eval $(call add_include_file,frontends/blif/blifparse.h))
|
$(eval $(call add_include_file,frontends/blif/blifparse.h))
|
||||||
$(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))
|
$(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))
|
||||||
|
|
||||||
OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o
|
OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o kernel/io.o kernel/gzip.o
|
||||||
OBJS += kernel/binding.o
|
OBJS += kernel/binding.o kernel/tclapi.o
|
||||||
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o
|
OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o
|
||||||
OBJS += kernel/drivertools.o kernel/functional.o
|
OBJS += kernel/drivertools.o kernel/functional.o
|
||||||
ifeq ($(ENABLE_ZLIB),1)
|
ifeq ($(ENABLE_ZLIB),1)
|
||||||
|
@ -680,6 +675,9 @@ OBJS += libs/fst/fastlz.o
|
||||||
OBJS += libs/fst/lz4.o
|
OBJS += libs/fst/lz4.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
techlibs/%_pm.h: passes/pmgen/pmgen.py techlibs/%.pmg
|
||||||
|
$(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^)
|
||||||
|
|
||||||
ifneq ($(SMALL),1)
|
ifneq ($(SMALL),1)
|
||||||
|
|
||||||
OBJS += libs/subcircuit/subcircuit.o
|
OBJS += libs/subcircuit/subcircuit.o
|
||||||
|
@ -737,12 +735,18 @@ compile-only: $(OBJS) $(GENFILES) $(EXTRA_TARGETS)
|
||||||
@echo " Compile successful."
|
@echo " Compile successful."
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
|
.PHONY: share
|
||||||
|
share: $(EXTRA_TARGETS)
|
||||||
|
@echo ""
|
||||||
|
@echo " Share directory created."
|
||||||
|
@echo ""
|
||||||
|
|
||||||
$(PROGRAM_PREFIX)yosys$(EXE): $(OBJS)
|
$(PROGRAM_PREFIX)yosys$(EXE): $(OBJS)
|
||||||
$(P) $(CXX) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LINKFLAGS) $(LINKFLAGS) $(OBJS) $(LIBS) $(LIBS_VERIFIC)
|
$(P) $(CXX) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LINKFLAGS) $(LINKFLAGS) $(OBJS) $(EXE_LIBS) $(LIBS) $(LIBS_VERIFIC)
|
||||||
|
|
||||||
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
|
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
|
||||||
ifeq ($(OS), Darwin)
|
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
|
else
|
||||||
$(P) $(CXX) -o libyosys.so -shared -Wl,-soname,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC)
|
$(P) $(CXX) -o libyosys.so -shared -Wl,-soname,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC)
|
||||||
endif
|
endif
|
||||||
|
@ -758,7 +762,7 @@ endif
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
|
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
|
||||||
$(Q) mkdir -p $(dir $@)
|
$(Q) mkdir -p $(dir $@)
|
||||||
$(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
|
$(P) $(PYTHON_EXECUTABLE) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
|
@ -789,7 +793,7 @@ $(PROGRAM_PREFIX)yosys-config: misc/yosys-config.in $(YOSYS_SRC)/Makefile
|
||||||
.PHONY: check-git-abc
|
.PHONY: check-git-abc
|
||||||
|
|
||||||
check-git-abc:
|
check-git-abc:
|
||||||
@if [ ! -d "$(YOSYS_SRC)/abc" ]; then \
|
@if [ ! -d "$(YOSYS_SRC)/abc" ] && git -C "$(YOSYS_SRC)" status >/dev/null 2>&1; then \
|
||||||
echo "Error: The 'abc' directory does not exist."; \
|
echo "Error: The 'abc' directory does not exist."; \
|
||||||
echo "Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \
|
echo "Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
|
@ -798,6 +802,15 @@ check-git-abc:
|
||||||
elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && ! grep -q '\$$Format:%[hH]\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \
|
elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && ! grep -q '\$$Format:%[hH]\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \
|
||||||
echo "'abc' comes from a tarball. Continuing."; \
|
echo "'abc' comes from a tarball. Continuing."; \
|
||||||
exit 0; \
|
exit 0; \
|
||||||
|
elif git -C "$(YOSYS_SRC)" submodule status abc 2>/dev/null | grep -q '^+'; then \
|
||||||
|
echo "'abc' submodule does not match expected commit."; \
|
||||||
|
echo "Run 'git submodule update' to check out the correct version."; \
|
||||||
|
echo "Note: If testing a different version of abc, call 'git commit abc' in the Yosys source directory to update the expected commit."; \
|
||||||
|
exit 1; \
|
||||||
|
elif git -C "$(YOSYS_SRC)" submodule status abc 2>/dev/null | grep -q '^U'; then \
|
||||||
|
echo "'abc' submodule has merge conflicts."; \
|
||||||
|
echo "Please resolve merge conflicts before continuing."; \
|
||||||
|
exit 1; \
|
||||||
elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && grep -q '\$$Format:%[hH]\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \
|
elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && grep -q '\$$Format:%[hH]\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \
|
||||||
echo "Error: 'abc' is not configured as a git submodule."; \
|
echo "Error: 'abc' is not configured as a git submodule."; \
|
||||||
echo "To resolve this:"; \
|
echo "To resolve this:"; \
|
||||||
|
@ -806,6 +819,12 @@ check-git-abc:
|
||||||
echo "3. Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \
|
echo "3. Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \
|
||||||
echo "4. Reapply your changes: Move your saved changes back to the 'abc' directory, if necessary."; \
|
echo "4. Reapply your changes: Move your saved changes back to the 'abc' directory, if necessary."; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
|
elif ! git -C "$(YOSYS_SRC)" status >/dev/null 2>&1; then \
|
||||||
|
echo "$(realpath $(YOSYS_SRC)) is not configured as a git repository, and 'abc' folder is missing."; \
|
||||||
|
echo "If you already have ABC, set 'ABCEXTERNAL' make variable to point to ABC executable."; \
|
||||||
|
echo "Otherwise, download release archive 'yosys.tar.gz' from https://github.com/YosysHQ/yosys/releases."; \
|
||||||
|
echo " ('Source code' archive does not contain submodules.)"; \
|
||||||
|
exit 1; \
|
||||||
else \
|
else \
|
||||||
echo "Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \
|
echo "Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
|
@ -833,71 +852,104 @@ else
|
||||||
ABCOPT=""
|
ABCOPT=""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# When YOSYS_NOVERIFIC is set as a make variable, also export it to the
|
# Tests that generate .mk with tests/gen-tests-makefile.sh
|
||||||
# enviornment, so that `YOSYS_NOVERIFIC=1 make test` _and_
|
MK_TEST_DIRS =
|
||||||
# `make test YOSYS_NOVERIFIC=1` will run with verific disabled.
|
MK_TEST_DIRS += tests/arch/anlogic
|
||||||
ifeq ($(YOSYS_NOVERIFIC),1)
|
MK_TEST_DIRS += tests/arch/ecp5
|
||||||
export YOSYS_NOVERIFIC
|
MK_TEST_DIRS += tests/arch/efinix
|
||||||
|
MK_TEST_DIRS += tests/arch/gatemate
|
||||||
|
MK_TEST_DIRS += tests/arch/gowin
|
||||||
|
MK_TEST_DIRS += tests/arch/ice40
|
||||||
|
MK_TEST_DIRS += tests/arch/intel_alm
|
||||||
|
MK_TEST_DIRS += tests/arch/machxo2
|
||||||
|
MK_TEST_DIRS += tests/arch/microchip
|
||||||
|
MK_TEST_DIRS += tests/arch/nanoxplore
|
||||||
|
MK_TEST_DIRS += tests/arch/nexus
|
||||||
|
MK_TEST_DIRS += tests/arch/quicklogic/pp3
|
||||||
|
MK_TEST_DIRS += tests/arch/quicklogic/qlf_k6n10f
|
||||||
|
MK_TEST_DIRS += tests/arch/xilinx
|
||||||
|
MK_TEST_DIRS += tests/bugpoint
|
||||||
|
MK_TEST_DIRS += tests/opt
|
||||||
|
MK_TEST_DIRS += tests/sat
|
||||||
|
MK_TEST_DIRS += tests/sim
|
||||||
|
MK_TEST_DIRS += tests/svtypes
|
||||||
|
MK_TEST_DIRS += tests/techmap
|
||||||
|
MK_TEST_DIRS += tests/various
|
||||||
|
ifeq ($(ENABLE_VERIFIC),1)
|
||||||
|
ifneq ($(YOSYS_NOVERIFIC),1)
|
||||||
|
MK_TEST_DIRS += tests/verific
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
MK_TEST_DIRS += tests/verilog
|
||||||
|
|
||||||
|
# Tests that don't generate .mk
|
||||||
|
SH_TEST_DIRS =
|
||||||
|
SH_TEST_DIRS += tests/simple
|
||||||
|
SH_TEST_DIRS += tests/simple_abc9
|
||||||
|
SH_TEST_DIRS += tests/hana
|
||||||
|
SH_TEST_DIRS += tests/asicworld
|
||||||
|
# SH_TEST_DIRS += tests/realmath
|
||||||
|
SH_TEST_DIRS += tests/share
|
||||||
|
SH_TEST_DIRS += tests/opt_share
|
||||||
|
SH_TEST_DIRS += tests/fsm
|
||||||
|
SH_TEST_DIRS += tests/memlib
|
||||||
|
SH_TEST_DIRS += tests/bram
|
||||||
|
SH_TEST_DIRS += tests/svinterfaces
|
||||||
|
SH_TEST_DIRS += tests/xprop
|
||||||
|
SH_TEST_DIRS += tests/select
|
||||||
|
SH_TEST_DIRS += tests/peepopt
|
||||||
|
SH_TEST_DIRS += tests/proc
|
||||||
|
SH_TEST_DIRS += tests/blif
|
||||||
|
SH_TEST_DIRS += tests/arch
|
||||||
|
SH_TEST_DIRS += tests/rpc
|
||||||
|
SH_TEST_DIRS += tests/memfile
|
||||||
|
SH_TEST_DIRS += tests/fmt
|
||||||
|
SH_TEST_DIRS += tests/cxxrtl
|
||||||
|
SH_TEST_DIRS += tests/liberty
|
||||||
|
ifeq ($(ENABLE_FUNCTIONAL_TESTS),1)
|
||||||
|
SH_TEST_DIRS += tests/functional
|
||||||
endif
|
endif
|
||||||
|
|
||||||
test: $(TARGETS) $(EXTRA_TARGETS)
|
# Tests that don't generate .mk and need special args
|
||||||
ifeq ($(ENABLE_VERIFIC),1)
|
SH_ABC_TEST_DIRS =
|
||||||
ifeq ($(YOSYS_NOVERIFIC),1)
|
SH_ABC_TEST_DIRS += tests/memories
|
||||||
@echo
|
SH_ABC_TEST_DIRS += tests/aiger
|
||||||
@echo "Running tests without verific support due to YOSYS_NOVERIFIC=1"
|
SH_ABC_TEST_DIRS += tests/alumacc
|
||||||
@echo
|
|
||||||
else
|
# seed-tests/ is a dummy string, not a directory
|
||||||
+cd tests/verific && bash run-test.sh $(SEEDOPT)
|
.PHONY: seed-tests
|
||||||
endif
|
seed-tests: $(SH_TEST_DIRS:%=seed-tests/%)
|
||||||
endif
|
.PHONY: seed-tests/%
|
||||||
+cd tests/simple && bash run-test.sh $(SEEDOPT)
|
seed-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT)
|
+cd $* && bash run-test.sh $(SEEDOPT)
|
||||||
+cd tests/hana && bash run-test.sh $(SEEDOPT)
|
+@echo "...passed tests in $*"
|
||||||
+cd tests/asicworld && bash run-test.sh $(SEEDOPT)
|
|
||||||
# +cd tests/realmath && bash run-test.sh $(SEEDOPT)
|
# abcopt-tests/ is a dummy string, not a directory
|
||||||
+cd tests/share && bash run-test.sh $(SEEDOPT)
|
.PHONY: abcopt-tests
|
||||||
+cd tests/opt_share && bash run-test.sh $(SEEDOPT)
|
abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-tests/%)
|
||||||
+cd tests/fsm && bash run-test.sh $(SEEDOPT)
|
abcopt-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/techmap && bash run-test.sh
|
+cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT)
|
||||||
+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT)
|
+@echo "...passed tests in $*"
|
||||||
+cd tests/memlib && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/bram && bash run-test.sh $(SEEDOPT)
|
# makefile-tests/ is a dummy string, not a directory
|
||||||
+cd tests/various && bash run-test.sh
|
.PHONY: makefile-tests
|
||||||
+cd tests/select && bash run-test.sh
|
makefile-tests: $(MK_TEST_DIRS:%=makefile-tests/%)
|
||||||
+cd tests/sat && bash run-test.sh
|
# this target actually emits .mk files
|
||||||
+cd tests/sim && bash run-test.sh
|
%.mk:
|
||||||
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
|
+cd $(dir $*) && bash run-test.sh
|
||||||
+cd tests/svtypes && bash run-test.sh $(SEEDOPT)
|
# this one spawns submake on each
|
||||||
+cd tests/proc && bash run-test.sh
|
makefile-tests/%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS)
|
||||||
+cd tests/blif && bash run-test.sh
|
$(MAKE) -C $* -f run-test.mk
|
||||||
+cd tests/opt && bash run-test.sh
|
+@echo "...passed tests in $*"
|
||||||
+cd tests/aiger && bash run-test.sh $(ABCOPT)
|
|
||||||
+cd tests/arch && bash run-test.sh
|
test: makefile-tests abcopt-tests seed-tests
|
||||||
+cd tests/arch/ice40 && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/xilinx && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/ecp5 && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/machxo2 && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/efinix && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/nanoxplore && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/nexus && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/quicklogic/pp3 && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/quicklogic/qlf_k6n10f && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/gatemate && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/arch/microchip && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/rpc && bash run-test.sh
|
|
||||||
+cd tests/memfile && bash run-test.sh
|
|
||||||
+cd tests/verilog && bash run-test.sh
|
|
||||||
+cd tests/xprop && bash run-test.sh $(SEEDOPT)
|
|
||||||
+cd tests/fmt && bash run-test.sh
|
|
||||||
+cd tests/cxxrtl && bash run-test.sh
|
|
||||||
ifeq ($(ENABLE_FUNCTIONAL_TESTS),1)
|
|
||||||
+cd tests/functional && bash run-test.sh
|
|
||||||
endif
|
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " Passed \"make test\"."
|
@echo " Passed \"make test\"."
|
||||||
|
ifeq ($(ENABLE_VERIFIC),1)
|
||||||
|
ifeq ($(YOSYS_NOVERIFIC),1)
|
||||||
|
@echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1."
|
||||||
|
endif
|
||||||
|
endif
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all
|
VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all
|
||||||
|
@ -924,33 +976,43 @@ ystests: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
|
|
||||||
# Unit test
|
# Unit test
|
||||||
unit-test: libyosys.so
|
unit-test: libyosys.so
|
||||||
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" \
|
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" \
|
||||||
CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)"
|
CXXFLAGS="$(CXXFLAGS)" LINKFLAGS="$(LINKFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)"
|
||||||
|
|
||||||
clean-unit-test:
|
clean-unit-test:
|
||||||
@$(MAKE) -C $(UNITESTPATH) clean
|
@$(MAKE) -C $(UNITESTPATH) clean
|
||||||
|
|
||||||
|
install-dev: $(PROGRAM_PREFIX)yosys-config share
|
||||||
|
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
|
$(INSTALL_SUDO) cp $(PROGRAM_PREFIX)yosys-config $(DESTDIR)$(BINDIR)
|
||||||
|
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
|
||||||
|
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
|
||||||
|
|
||||||
install: $(TARGETS) $(EXTRA_TARGETS)
|
install: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
|
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
|
||||||
$(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR)
|
$(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR)
|
||||||
ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),)
|
ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),)
|
||||||
$(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys
|
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys; fi
|
||||||
endif
|
endif
|
||||||
ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),)
|
ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),)
|
||||||
$(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc
|
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc; fi
|
||||||
endif
|
endif
|
||||||
ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),)
|
ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),)
|
||||||
$(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib
|
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib; fi
|
||||||
endif
|
endif
|
||||||
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
|
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
|
||||||
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
|
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
|
||||||
ifeq ($(ENABLE_LIBYOSYS),1)
|
ifeq ($(ENABLE_LIBYOSYS),1)
|
||||||
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR)
|
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR)
|
||||||
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/
|
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/
|
||||||
$(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so
|
if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so; fi
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
|
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
|
||||||
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
|
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so
|
||||||
|
$(INSTALL_SUDO) cp -r share $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys
|
||||||
|
ifeq ($(ENABLE_ABC),1)
|
||||||
|
$(INSTALL_SUDO) cp yosys-abc $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc
|
||||||
|
endif
|
||||||
$(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
|
$(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -975,27 +1037,46 @@ endif
|
||||||
|
|
||||||
# also others, but so long as it doesn't fail this is enough to know we tried
|
# 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)
|
docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS)
|
||||||
mkdir -p docs/source/cmd
|
$(Q) mkdir -p docs/source/cmd
|
||||||
./$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual'
|
$(Q) mkdir -p temp/docs/source/cmd
|
||||||
|
$(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual'
|
||||||
|
$(Q) $(RSYNC_CP) 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_CP) temp/docs/source/cell docs/source
|
||||||
|
$(Q) rm -rf temp
|
||||||
|
|
||||||
PHONY: docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs
|
docs/source/generated/cells.json: docs/source/generated $(TARGETS) $(EXTRA_TARGETS)
|
||||||
docs/gen_examples:
|
$(Q) ./$(PROGRAM_PREFIX)yosys -p 'help -dump-cells-json $@'
|
||||||
$(Q) $(MAKE) -C docs examples
|
|
||||||
|
|
||||||
docs/gen_images:
|
docs/source/generated/%.cc: backends/%.cc
|
||||||
$(Q) $(MAKE) -C docs images
|
$(Q) mkdir -p $(@D)
|
||||||
|
$(Q) cp $< $@
|
||||||
|
|
||||||
DOCS_GUIDELINE_FILES := GettingStarted CodingStyle
|
# diff returns exit code 1 if the files are different, but it's not an error
|
||||||
docs/guidelines docs/source/generated:
|
docs/source/generated/functional/rosette.diff: backends/functional/smtlib.cc backends/functional/smtlib_rosette.cc
|
||||||
|
$(Q) mkdir -p $(@D)
|
||||||
|
$(Q) diff -U 20 $^ > $@ || exit 0
|
||||||
|
|
||||||
|
PHONY: docs/gen/functional_ir
|
||||||
|
docs/gen/functional_ir: docs/source/generated/functional/smtlib.cc docs/source/generated/functional/rosette.diff
|
||||||
|
|
||||||
|
PHONY: docs/gen docs/usage docs/reqs
|
||||||
|
docs/gen: $(TARGETS)
|
||||||
|
$(Q) $(MAKE) -C docs gen
|
||||||
|
|
||||||
|
docs/source/generated:
|
||||||
$(Q) mkdir -p docs/source/generated
|
$(Q) mkdir -p docs/source/generated
|
||||||
$(Q) cp -f $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES)) docs/source/generated
|
|
||||||
|
|
||||||
# some commands return an error and print the usage text to stderr
|
# some commands return an error and print the usage text to stderr
|
||||||
define DOC_USAGE_STDERR
|
define DOC_USAGE_STDERR
|
||||||
docs/source/generated/$(1): $(TARGETS) docs/source/generated
|
docs/source/generated/$(1): $(TARGETS) docs/source/generated FORCE
|
||||||
-$(Q) ./$(PROGRAM_PREFIX)$(1) --help 2> $$@
|
-$(Q) ./$(PROGRAM_PREFIX)$(1) --help 2> $$@
|
||||||
endef
|
endef
|
||||||
DOCS_USAGE_STDERR := yosys-config yosys-filterlib
|
DOCS_USAGE_STDERR := yosys-filterlib
|
||||||
|
|
||||||
# The in-tree ABC (yosys-abc) is only built when ABCEXTERNAL is not set.
|
# The in-tree ABC (yosys-abc) is only built when ABCEXTERNAL is not set.
|
||||||
ifeq ($(ABCEXTERNAL),)
|
ifeq ($(ABCEXTERNAL),)
|
||||||
|
@ -1007,9 +1088,9 @@ $(foreach usage,$(DOCS_USAGE_STDERR),$(eval $(call DOC_USAGE_STDERR,$(usage))))
|
||||||
# others print to stdout
|
# others print to stdout
|
||||||
define DOC_USAGE_STDOUT
|
define DOC_USAGE_STDOUT
|
||||||
docs/source/generated/$(1): $(TARGETS) docs/source/generated
|
docs/source/generated/$(1): $(TARGETS) docs/source/generated
|
||||||
$(Q) ./$(PROGRAM_PREFIX)$(1) --help > $$@
|
$(Q) ./$(PROGRAM_PREFIX)$(1) --help > $$@ || rm $$@
|
||||||
endef
|
endef
|
||||||
DOCS_USAGE_STDOUT := yosys yosys-smtbmc yosys-witness
|
DOCS_USAGE_STDOUT := yosys yosys-smtbmc yosys-witness yosys-config
|
||||||
$(foreach usage,$(DOCS_USAGE_STDOUT),$(eval $(call DOC_USAGE_STDOUT,$(usage))))
|
$(foreach usage,$(DOCS_USAGE_STDOUT),$(eval $(call DOC_USAGE_STDOUT,$(usage))))
|
||||||
|
|
||||||
docs/usage: $(addprefix docs/source/generated/,$(DOCS_USAGE_STDOUT) $(DOCS_USAGE_STDERR))
|
docs/usage: $(addprefix docs/source/generated/,$(DOCS_USAGE_STDOUT) $(DOCS_USAGE_STDERR))
|
||||||
|
@ -1018,7 +1099,7 @@ docs/reqs:
|
||||||
$(Q) $(MAKE) -C docs reqs
|
$(Q) $(MAKE) -C docs reqs
|
||||||
|
|
||||||
.PHONY: docs/prep
|
.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/usage docs/gen/functional_ir
|
||||||
|
|
||||||
DOC_TARGET ?= html
|
DOC_TARGET ?= html
|
||||||
docs: docs/prep
|
docs: docs/prep
|
||||||
|
@ -1029,6 +1110,7 @@ clean:
|
||||||
rm -rf kernel/*.pyh
|
rm -rf kernel/*.pyh
|
||||||
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) $(PY_WRAP_INCLUDES) $(PY_WRAPPER_FILE).cc
|
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) $(PY_WRAP_INCLUDES) $(PY_WRAPPER_FILE).cc
|
||||||
rm -f kernel/version_*.o kernel/version_*.cc
|
rm -f kernel/version_*.o kernel/version_*.cc
|
||||||
|
rm -f kernel/python_wrappers.o
|
||||||
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
|
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
|
||||||
rm -rf tests/asicworld/*.out tests/asicworld/*.log
|
rm -rf tests/asicworld/*.out tests/asicworld/*.log
|
||||||
rm -rf tests/hana/*.out tests/hana/*.log
|
rm -rf tests/hana/*.out tests/hana/*.log
|
||||||
|
@ -1039,9 +1121,11 @@ clean:
|
||||||
rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
|
rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
|
||||||
rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
|
rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
|
||||||
rm -f tests/tools/cmp_tbdata
|
rm -f tests/tools/cmp_tbdata
|
||||||
|
rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS))
|
||||||
-$(MAKE) -C docs clean
|
-$(MAKE) -C docs clean
|
||||||
-$(MAKE) -C docs/images clean
|
|
||||||
rm -rf docs/source/cmd docs/util/__pycache__
|
rm -rf docs/source/cmd docs/util/__pycache__
|
||||||
|
rm -f *.whl
|
||||||
|
rm -f libyosys.so
|
||||||
|
|
||||||
clean-abc:
|
clean-abc:
|
||||||
$(MAKE) -C abc DEP= clean
|
$(MAKE) -C abc DEP= clean
|
||||||
|
@ -1078,25 +1162,13 @@ vcxsrc: $(GENFILES) $(EXTRA_TARGETS)
|
||||||
rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip}
|
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 \
|
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 "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)
|
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
|
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
|
zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc
|
||||||
zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/
|
zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/
|
||||||
rm -f srcfiles.txt kernel/version.cc
|
rm -f srcfiles.txt kernel/version.cc
|
||||||
|
|
||||||
ifeq ($(CONFIG),mxe)
|
|
||||||
mxebin: $(TARGETS) $(EXTRA_TARGETS)
|
|
||||||
rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip}
|
|
||||||
mkdir -p yosys-win32-mxebin-$(YOSYS_VER)
|
|
||||||
cp -r $(PROGRAM_PREFIX)yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/
|
|
||||||
ifeq ($(ENABLE_ABC),1)
|
|
||||||
cp -r $(PROGRAM_PREFIX)yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/
|
|
||||||
endif
|
|
||||||
echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
|
|
||||||
echo -en 'Documentation at https://yosyshq.net/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
|
|
||||||
zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/
|
|
||||||
endif
|
|
||||||
|
|
||||||
config-clean: clean
|
config-clean: clean
|
||||||
rm -f Makefile.conf
|
rm -f Makefile.conf
|
||||||
|
|
||||||
|
@ -1112,9 +1184,6 @@ config-gcc-static: clean
|
||||||
echo 'ENABLE_READLINE := 0' >> Makefile.conf
|
echo 'ENABLE_READLINE := 0' >> Makefile.conf
|
||||||
echo 'ENABLE_TCL := 0' >> Makefile.conf
|
echo 'ENABLE_TCL := 0' >> Makefile.conf
|
||||||
|
|
||||||
config-afl-gcc: clean
|
|
||||||
echo 'CONFIG := afl-gcc' > Makefile.conf
|
|
||||||
|
|
||||||
config-wasi: clean
|
config-wasi: clean
|
||||||
echo 'CONFIG := wasi' > Makefile.conf
|
echo 'CONFIG := wasi' > Makefile.conf
|
||||||
echo 'ENABLE_TCL := 0' >> Makefile.conf
|
echo 'ENABLE_TCL := 0' >> Makefile.conf
|
||||||
|
@ -1123,10 +1192,6 @@ config-wasi: clean
|
||||||
echo 'ENABLE_READLINE := 0' >> Makefile.conf
|
echo 'ENABLE_READLINE := 0' >> Makefile.conf
|
||||||
echo 'ENABLE_ZLIB := 0' >> Makefile.conf
|
echo 'ENABLE_ZLIB := 0' >> Makefile.conf
|
||||||
|
|
||||||
config-mxe: clean
|
|
||||||
echo 'CONFIG := mxe' > Makefile.conf
|
|
||||||
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
|
|
||||||
|
|
||||||
config-msys2-32: clean
|
config-msys2-32: clean
|
||||||
echo 'CONFIG := msys2-32' > Makefile.conf
|
echo 'CONFIG := msys2-32' > Makefile.conf
|
||||||
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
|
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
|
||||||
|
@ -1135,9 +1200,6 @@ config-msys2-64: clean
|
||||||
echo 'CONFIG := msys2-64' > Makefile.conf
|
echo 'CONFIG := msys2-64' > Makefile.conf
|
||||||
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
|
echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf
|
||||||
|
|
||||||
config-cygwin: clean
|
|
||||||
echo 'CONFIG := cygwin' > Makefile.conf
|
|
||||||
|
|
||||||
config-gcov: clean
|
config-gcov: clean
|
||||||
echo 'CONFIG := gcc' > Makefile.conf
|
echo 'CONFIG := gcc' > Makefile.conf
|
||||||
echo 'ENABLE_GCOV := 1' >> Makefile.conf
|
echo 'ENABLE_GCOV := 1' >> Makefile.conf
|
||||||
|
@ -1166,5 +1228,7 @@ echo-cxx:
|
||||||
-include kernel/*.d
|
-include kernel/*.d
|
||||||
-include techlibs/*/*.d
|
-include techlibs/*/*.d
|
||||||
|
|
||||||
.PHONY: all top-all abc test install install-abc docs clean mrproper qtcreator coverage vcxsrc mxebin
|
FORCE:
|
||||||
.PHONY: config-clean config-clang config-gcc config-gcc-static config-afl-gcc config-gprof config-sudo
|
|
||||||
|
.PHONY: all top-all abc test install-dev install install-abc docs clean mrproper qtcreator coverage vcxsrc
|
||||||
|
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gprof config-sudo
|
||||||
|
|
477
README.md
477
README.md
|
@ -1,22 +1,3 @@
|
||||||
```
|
|
||||||
yosys -- Yosys Open SYnthesis Suite
|
|
||||||
|
|
||||||
Copyright (C) 2012 - 2024 Claire Xenia Wolf <claire@yosyshq.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
yosys – Yosys Open SYnthesis Suite
|
yosys – Yosys Open SYnthesis Suite
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
@ -33,6 +14,10 @@ Yosys is free software licensed under the ISC license (a GPL
|
||||||
compatible license that is similar in terms to the MIT license
|
compatible license that is similar in terms to the MIT license
|
||||||
or the 2-clause BSD 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
|
Web Site and Other Resources
|
||||||
============================
|
============================
|
||||||
|
@ -40,17 +25,14 @@ Web Site and Other Resources
|
||||||
More information and documentation can be found on the Yosys web site:
|
More information and documentation can be found on the Yosys web site:
|
||||||
- https://yosyshq.net/yosys/
|
- https://yosyshq.net/yosys/
|
||||||
|
|
||||||
The "Documentation" page on the web site contains links to more resources,
|
Documentation from this repository is automatically built and available on Read
|
||||||
including a manual that even describes some of the Yosys internals:
|
the Docs:
|
||||||
- https://yosyshq.net/yosys/documentation.html
|
- https://yosyshq.readthedocs.io/projects/yosys
|
||||||
|
|
||||||
The directory `guidelines` contains additional information
|
Users interested in formal verification might want to use the formal
|
||||||
for people interested in using the Yosys C++ APIs.
|
verification front-end for Yosys, SBY:
|
||||||
|
- https://yosyshq.readthedocs.io/projects/sby/
|
||||||
Users interested in formal verification might want to use the formal verification
|
- https://github.com/YosysHQ/sby
|
||||||
front-end for Yosys, SymbiYosys:
|
|
||||||
- https://symbiyosys.readthedocs.io/en/latest/
|
|
||||||
- https://github.com/YosysHQ/SymbiYosys
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
|
@ -68,9 +50,25 @@ For more information about the difference between Tabby CAD Suite and the OSS CA
|
||||||
|
|
||||||
Many Linux distributions also provide Yosys binaries, some more up to date than others. Check with your package manager!
|
Many Linux distributions also provide Yosys binaries, some more up to date than others. Check with your package manager!
|
||||||
|
|
||||||
|
|
||||||
Building from Source
|
Building from Source
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
For more details, and instructions for other platforms, check [building from
|
||||||
|
source](https://yosyshq.readthedocs.io/projects/yosys/en/latest/getting_started/installation.html#building-from-source)
|
||||||
|
on Read the Docs.
|
||||||
|
|
||||||
|
When cloning Yosys, some required libraries are included as git submodules. Make
|
||||||
|
sure to call e.g.
|
||||||
|
|
||||||
|
$ git clone --recurse-submodules https://github.com/YosysHQ/yosys.git
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
$ git clone https://github.com/YosysHQ/yosys.git
|
||||||
|
$ cd yosys
|
||||||
|
$ git submodule update --init --recursive
|
||||||
|
|
||||||
You need a C++ compiler with C++17 support (up-to-date CLANG or GCC is
|
You need a C++ compiler with C++17 support (up-to-date CLANG or GCC is
|
||||||
recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.
|
recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.
|
||||||
TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
|
TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
|
||||||
|
@ -84,52 +82,22 @@ prerequisites for building yosys:
|
||||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
graphviz xdot pkg-config python3 libboost-system-dev \
|
||||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
||||||
|
|
||||||
Similarily, on Mac OS X Homebrew can be used to install dependencies (from within cloned yosys repository):
|
|
||||||
|
|
||||||
$ brew tap Homebrew/bundle && brew bundle
|
|
||||||
|
|
||||||
or MacPorts:
|
|
||||||
|
|
||||||
$ sudo port install bison flex readline gawk libffi \
|
|
||||||
git graphviz pkgconfig python36 boost zlib tcl
|
|
||||||
|
|
||||||
On FreeBSD use the following command to install all prerequisites:
|
|
||||||
|
|
||||||
# pkg install bison flex readline gawk libffi\
|
|
||||||
git graphviz pkgconf python3 python36 tcl-wrapper boost-libs
|
|
||||||
|
|
||||||
On FreeBSD system use gmake instead of make. To run tests use:
|
|
||||||
% MAKE=gmake CC=cc gmake test
|
|
||||||
|
|
||||||
For Cygwin use the following command to install all prerequisites, or select these additional packages:
|
|
||||||
|
|
||||||
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
|
|
||||||
|
|
||||||
The environment variable `CXX` can be used to control the C++ compiler used, or
|
The environment variable `CXX` can be used to control the C++ compiler used, or
|
||||||
run one of the following:
|
run one of the following to override it:
|
||||||
|
|
||||||
$ make config-clang
|
$ make config-clang
|
||||||
$ make config-gcc
|
$ make config-gcc
|
||||||
|
|
||||||
Note that these will result in `make` ignoring the `CXX` environment variable,
|
The Makefile has many variables influencing the build process. These can be
|
||||||
unless `CXX` is assigned in the call to make, e.g.
|
adjusted by modifying the Makefile.conf file which is created at the `make
|
||||||
|
config-...` step (see above), or they can be set by passing an option to the
|
||||||
|
make command directly:
|
||||||
|
|
||||||
$ make CXX=$CXX
|
$ make CXX=$CXX
|
||||||
|
|
||||||
The Makefile has many variables influencing the build process. These can be
|
For other compilers and build configurations it might be necessary to make some
|
||||||
adjusted by modifying the Makefile.conf file which is created at the
|
changes to the config section of the Makefile. It's also an alternative way to
|
||||||
`make config-...` step (see above), or they can be set by passing an option
|
set the make variables mentioned above.
|
||||||
to the make command directly.
|
|
||||||
|
|
||||||
For example, if you have clang, and (a compatible version of) `ld.lld`
|
|
||||||
available in PATH, it's recommended to speed up incremental builds with
|
|
||||||
lld by enabling LTO:
|
|
||||||
|
|
||||||
$ make ENABLE_LTO=1
|
|
||||||
|
|
||||||
For other compilers and build configurations it might be
|
|
||||||
necessary to make some changes to the config section of the
|
|
||||||
Makefile.
|
|
||||||
|
|
||||||
$ vi Makefile # ..or..
|
$ vi Makefile # ..or..
|
||||||
$ vi Makefile.conf
|
$ vi Makefile.conf
|
||||||
|
@ -139,10 +107,9 @@ To build Yosys simply type 'make' in this directory.
|
||||||
$ make
|
$ make
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
|
|
||||||
Note that this also downloads, builds and installs ABC (using yosys-abc
|
Tests are located in the tests subdirectory and can be executed using the test
|
||||||
as executable name).
|
target. Note that you need gawk as well as a recent version of iverilog (i.e.
|
||||||
|
build from git). Then, execute tests via:
|
||||||
Tests are located in the tests subdirectory and can be executed using the test target. Note that you need gawk as well as a recent version of iverilog (i.e. build from git). Then, execute tests via:
|
|
||||||
|
|
||||||
$ make test
|
$ make test
|
||||||
|
|
||||||
|
@ -153,6 +120,7 @@ To use a separate (out-of-tree) build directory, provide a path to the Makefile.
|
||||||
|
|
||||||
Out-of-tree builds require a clean source tree.
|
Out-of-tree builds require a clean source tree.
|
||||||
|
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
@ -257,365 +225,14 @@ The command ``prep`` provides a good default word-level synthesis script, as
|
||||||
used in SMT-based formal verification.
|
used in SMT-based formal verification.
|
||||||
|
|
||||||
|
|
||||||
Unsupported Verilog-2005 Features
|
Additional information
|
||||||
=================================
|
======================
|
||||||
|
|
||||||
The following Verilog-2005 features are not supported by
|
The ``read_verilog`` command, used by default when calling ``read`` with Verilog
|
||||||
Yosys and there are currently no plans to add support
|
source input, does not perform syntax checking. You should instead lint your
|
||||||
for them:
|
source with another tool such as
|
||||||
|
[Verilator](https://www.veripool.org/verilator/) first, e.g. by calling
|
||||||
- Non-synthesizable language features as defined in
|
``verilator --lint-only``.
|
||||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
|
||||||
|
|
||||||
- The ``tri``, ``triand`` and ``trior`` net types
|
|
||||||
|
|
||||||
- The ``config`` and ``disable`` keywords and library map files
|
|
||||||
|
|
||||||
|
|
||||||
Verilog Attributes and non-standard features
|
|
||||||
============================================
|
|
||||||
|
|
||||||
- The ``full_case`` attribute on case statements is supported
|
|
||||||
(also the non-standard ``// synopsys full_case`` directive)
|
|
||||||
|
|
||||||
- The ``parallel_case`` attribute on case statements is supported
|
|
||||||
(also the non-standard ``// synopsys parallel_case`` directive)
|
|
||||||
|
|
||||||
- The ``// synopsys translate_off`` and ``// synopsys translate_on``
|
|
||||||
directives are also supported (but the use of ``` `ifdef .. `endif ```
|
|
||||||
is strongly recommended instead).
|
|
||||||
|
|
||||||
- The ``nomem2reg`` attribute on modules or arrays prohibits the
|
|
||||||
automatic early conversion of arrays to separate registers. This
|
|
||||||
is potentially dangerous. Usually the front-end has good reasons
|
|
||||||
for converting an array to a list of registers. Prohibiting this
|
|
||||||
step will likely result in incorrect synthesis results.
|
|
||||||
|
|
||||||
- The ``mem2reg`` attribute on modules or arrays forces the early
|
|
||||||
conversion of arrays to separate registers.
|
|
||||||
|
|
||||||
- The ``nomeminit`` attribute on modules or arrays prohibits the
|
|
||||||
creation of initialized memories. This effectively puts ``mem2reg``
|
|
||||||
on all memories that are written to in an ``initial`` block and
|
|
||||||
are not ROMs.
|
|
||||||
|
|
||||||
- The ``nolatches`` attribute on modules or always-blocks
|
|
||||||
prohibits the generation of logic-loops for latches. Instead
|
|
||||||
all not explicitly assigned values default to x-bits. This does
|
|
||||||
not affect clocked storage elements such as flip-flops.
|
|
||||||
|
|
||||||
- The ``nosync`` attribute on registers prohibits the generation of a
|
|
||||||
storage element. The register itself will always have all bits set
|
|
||||||
to 'x' (undefined). The variable may only be used as blocking assigned
|
|
||||||
temporary variable within an always block. This is mostly used internally
|
|
||||||
by Yosys to synthesize Verilog functions and access arrays.
|
|
||||||
|
|
||||||
- The ``nowrshmsk`` attribute on a register prohibits the generation of
|
|
||||||
shift-and-mask type circuits for writing to bit slices of that register.
|
|
||||||
|
|
||||||
- The ``onehot`` attribute on wires mark them as one-hot state register. This
|
|
||||||
is used for example for memory port sharing and set by the fsm_map pass.
|
|
||||||
|
|
||||||
- The ``blackbox`` attribute on modules is used to mark empty stub modules
|
|
||||||
that have the same ports as the real thing but do not contain information
|
|
||||||
on the internal configuration. This modules are only used by the synthesis
|
|
||||||
passes to identify input and output ports of cells. The Verilog backend
|
|
||||||
also does not output blackbox modules on default. ``read_verilog``, unless
|
|
||||||
called with ``-noblackbox`` will automatically set the blackbox attribute
|
|
||||||
on any empty module it reads.
|
|
||||||
|
|
||||||
- The ``noblackbox`` attribute set on an empty module prevents ``read_verilog``
|
|
||||||
from automatically setting the blackbox attribute on the module.
|
|
||||||
|
|
||||||
- The ``whitebox`` attribute on modules triggers the same behavior as
|
|
||||||
``blackbox``, but is for whitebox modules, i.e. library modules that
|
|
||||||
contain a behavioral model of the cell type.
|
|
||||||
|
|
||||||
- The ``lib_whitebox`` attribute overwrites ``whitebox`` when ``read_verilog``
|
|
||||||
is run in `-lib` mode. Otherwise it's automatically removed.
|
|
||||||
|
|
||||||
- The ``dynports`` attribute is used by the Verilog front-end to mark modules
|
|
||||||
that have ports with a width that depends on a parameter.
|
|
||||||
|
|
||||||
- The ``hdlname`` attribute is used by some passes to document the original
|
|
||||||
(HDL) name of a module when renaming a module. It should contain a single
|
|
||||||
name, or, when describing a hierarchical name in a flattened design, multiple
|
|
||||||
names separated by a single space character.
|
|
||||||
|
|
||||||
- The ``keep`` attribute on cells and wires is used to mark objects that should
|
|
||||||
never be removed by the optimizer. This is used for example for cells that
|
|
||||||
have hidden connections that are not part of the netlist, such as IO pads.
|
|
||||||
Setting the ``keep`` attribute on a module has the same effect as setting it
|
|
||||||
on all instances of the module.
|
|
||||||
|
|
||||||
- The ``keep_hierarchy`` attribute on cells and modules keeps the ``flatten``
|
|
||||||
command from flattening the indicated cells and modules.
|
|
||||||
|
|
||||||
- The ``init`` attribute on wires is set by the frontend when a register is
|
|
||||||
initialized "FPGA-style" with ``reg foo = val``. It can be used during
|
|
||||||
synthesis to add the necessary reset logic.
|
|
||||||
|
|
||||||
- The ``top`` attribute on a module marks this module as the top of the
|
|
||||||
design hierarchy. The ``hierarchy`` command sets this attribute when called
|
|
||||||
with ``-top``. Other commands, such as ``flatten`` and various backends
|
|
||||||
use this attribute to determine the top module.
|
|
||||||
|
|
||||||
- The ``src`` attribute is set on cells and wires created by to the string
|
|
||||||
``<hdl-file-name>:<line-number>`` by the HDL front-end and is then carried
|
|
||||||
through the synthesis. When entities are combined, a new |-separated
|
|
||||||
string is created that contains all the string from the original entities.
|
|
||||||
|
|
||||||
- The ``defaultvalue`` attribute is used to store default values for
|
|
||||||
module inputs. The attribute is attached to the input wire by the HDL
|
|
||||||
front-end when the input is declared with a default value.
|
|
||||||
|
|
||||||
- The ``parameter`` and ``localparam`` attributes are used to mark wires
|
|
||||||
that represent module parameters or localparams (when the HDL front-end
|
|
||||||
is run in ``-pwires`` mode).
|
|
||||||
|
|
||||||
- Wires marked with the ``hierconn`` attribute are connected to wires with the
|
|
||||||
same name (format ``cell_name.identifier``) when they are imported from
|
|
||||||
sub-modules by ``flatten``.
|
|
||||||
|
|
||||||
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
|
|
||||||
module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
|
|
||||||
from inserting another clock buffer on a net driven by such output.
|
|
||||||
|
|
||||||
- The ``clkbuf_sink`` attribute can be set on an input port of a module to
|
|
||||||
request clock buffer insertion by the ``clkbufmap`` pass.
|
|
||||||
|
|
||||||
- The ``clkbuf_inv`` attribute can be set on an output port of a module
|
|
||||||
with the value set to the name of an input port of that module. When
|
|
||||||
the ``clkbufmap`` would otherwise insert a clock buffer on this output,
|
|
||||||
it will instead try inserting the clock buffer on the input port (this
|
|
||||||
is used to implement clock inverter cells that clock buffer insertion
|
|
||||||
will "see through").
|
|
||||||
|
|
||||||
- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent
|
|
||||||
automatic clock buffer insertion by ``clkbufmap``. This behaviour can be
|
|
||||||
overridden by providing a custom selection to ``clkbufmap``.
|
|
||||||
|
|
||||||
- The ``invertible_pin`` attribute can be set on a port to mark it as
|
|
||||||
invertible via a cell parameter. The name of the inversion parameter
|
|
||||||
is specified as the value of this attribute. The value of the inversion
|
|
||||||
parameter must be of the same width as the port, with 1 indicating
|
|
||||||
an inverted bit and 0 indicating a non-inverted bit.
|
|
||||||
|
|
||||||
- The ``iopad_external_pin`` attribute on a blackbox module's port marks
|
|
||||||
it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
|
|
||||||
from inserting another pad cell on it.
|
|
||||||
|
|
||||||
- The module attribute ``abc9_lut`` is an integer attribute indicating to
|
|
||||||
`abc9` that this module describes a LUT with an area cost of this value, and
|
|
||||||
propagation delays described using `specify` statements.
|
|
||||||
|
|
||||||
- The module attribute ``abc9_box`` is a boolean specifying a black/white-box
|
|
||||||
definition, with propagation delays described using `specify` statements, for
|
|
||||||
use by `abc9`.
|
|
||||||
|
|
||||||
- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and
|
|
||||||
carry-out (if output port) ports of a box. This information is necessary for
|
|
||||||
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
|
|
||||||
onto a bus port will affect only its most significant bit.
|
|
||||||
|
|
||||||
- The module attribute ``abc9_flop`` is a boolean marking the module as a
|
|
||||||
flip-flop. This allows `abc9` to analyse its contents in order to perform
|
|
||||||
sequential synthesis.
|
|
||||||
|
|
||||||
- The frontend sets attributes ``always_comb``, ``always_latch`` and
|
|
||||||
``always_ff`` on processes derived from SystemVerilog style always blocks
|
|
||||||
according to the type of the always. These are checked for correctness in
|
|
||||||
``proc_dlatch``.
|
|
||||||
|
|
||||||
- The cell attribute ``wildcard_port_conns`` represents wildcard port
|
|
||||||
connections (SystemVerilog ``.*``). These are resolved to concrete
|
|
||||||
connections to matching wires in ``hierarchy``.
|
|
||||||
|
|
||||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
|
|
||||||
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
|
||||||
for everything that comes after the ``{* ... *}`` statement. (Reset
|
|
||||||
by adding an empty ``{* *}`` statement.)
|
|
||||||
|
|
||||||
- In module parameter and port declarations, and cell port and parameter
|
|
||||||
lists, a trailing comma is ignored. This simplifies writing Verilog code
|
|
||||||
generators a bit in some cases.
|
|
||||||
|
|
||||||
- Modules can be declared with ``module mod_name(...);`` (with three dots
|
|
||||||
instead of a list of module ports). With this syntax it is sufficient
|
|
||||||
to simply declare a module port as 'input' or 'output' in the module
|
|
||||||
body.
|
|
||||||
|
|
||||||
- When defining a macro with `define, all text between triple double quotes
|
|
||||||
is interpreted as macro body, even if it contains unescaped newlines. The
|
|
||||||
triple double quotes are removed from the macro body. For example:
|
|
||||||
|
|
||||||
`define MY_MACRO(a, b) """
|
|
||||||
assign a = 23;
|
|
||||||
assign b = 42;
|
|
||||||
"""
|
|
||||||
|
|
||||||
- The attribute ``via_celltype`` can be used to implement a Verilog task or
|
|
||||||
function by instantiating the specified cell type. The value is the name
|
|
||||||
of the cell type to use. For functions the name of the output port can
|
|
||||||
be specified by appending it to the cell type separated by a whitespace.
|
|
||||||
The body of the task or function is unused in this case and can be used
|
|
||||||
to specify a behavioral model of the cell type for simulation. For example:
|
|
||||||
|
|
||||||
module my_add3(A, B, C, Y);
|
|
||||||
parameter WIDTH = 8;
|
|
||||||
input [WIDTH-1:0] A, B, C;
|
|
||||||
output [WIDTH-1:0] Y;
|
|
||||||
...
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module top;
|
|
||||||
...
|
|
||||||
(* via_celltype = "my_add3 Y" *)
|
|
||||||
(* via_celltype_defparam_WIDTH = 32 *)
|
|
||||||
function [31:0] add3;
|
|
||||||
input [31:0] A, B, C;
|
|
||||||
begin
|
|
||||||
add3 = A + B + C;
|
|
||||||
end
|
|
||||||
endfunction
|
|
||||||
...
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
- The ``wiretype`` attribute is added by the verilog parser for wires of a
|
|
||||||
typedef'd type to indicate the type identifier.
|
|
||||||
|
|
||||||
- Various ``enum_value_{value}`` attributes are added to wires of an enumerated type
|
|
||||||
to give a map of possible enum items to their values.
|
|
||||||
|
|
||||||
- The ``enum_base_type`` attribute is added to enum items to indicate which
|
|
||||||
enum they belong to (enums -- anonymous and otherwise -- are
|
|
||||||
automatically named with an auto-incrementing counter). Note that enums
|
|
||||||
are currently not strongly typed.
|
|
||||||
|
|
||||||
- A limited subset of DPI-C functions is supported. The plugin mechanism
|
|
||||||
(see ``help plugin``) can be used to load .so files with implementations
|
|
||||||
of DPI-C routines. As a non-standard extension it is possible to specify
|
|
||||||
a plugin alias using the ``<alias>:`` syntax. For example:
|
|
||||||
|
|
||||||
module dpitest;
|
|
||||||
import "DPI-C" function foo:round = real my_round (real);
|
|
||||||
parameter real r = my_round(12.345);
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
$ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v'
|
|
||||||
|
|
||||||
- Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant
|
|
||||||
expressions as ``<size>``. If the expression is not a simple identifier, it
|
|
||||||
must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010``
|
|
||||||
|
|
||||||
- The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in
|
|
||||||
initial blocks in an unconditional context (only if/case statements on
|
|
||||||
expressions over parameters and constant values are allowed). The intended
|
|
||||||
use for this is synthesis-time DRC.
|
|
||||||
|
|
||||||
- There is limited support for converting ``specify`` .. ``endspecify``
|
|
||||||
statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells,
|
|
||||||
for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to
|
|
||||||
enable this functionality. (By default these blocks are ignored.)
|
|
||||||
|
|
||||||
- The ``reprocess_after`` internal attribute is used by the Verilog frontend to
|
|
||||||
mark cells with bindings which might depend on the specified instantiated
|
|
||||||
module. Modules with such cells will be reprocessed during the ``hierarchy``
|
|
||||||
pass once the referenced module definition(s) become available.
|
|
||||||
|
|
||||||
- The ``smtlib2_module`` attribute can be set on a blackbox module to specify a
|
|
||||||
formal model directly using SMT-LIB 2. For such a module, the
|
|
||||||
``smtlib2_comb_expr`` attribute can be used on output ports to define their
|
|
||||||
value using an SMT-LIB 2 expression. For example:
|
|
||||||
|
|
||||||
(* blackbox *)
|
|
||||||
(* smtlib2_module *)
|
|
||||||
module submod(a, b);
|
|
||||||
input [7:0] a;
|
|
||||||
(* smtlib2_comb_expr = "(bvnot a)" *)
|
|
||||||
output [7:0] b;
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
Non-standard or SystemVerilog features for formal verification
|
|
||||||
==============================================================
|
|
||||||
|
|
||||||
- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
|
|
||||||
when ``read_verilog`` is called with ``-formal``.
|
|
||||||
|
|
||||||
- The system task ``$initstate`` evaluates to 1 in the initial state and
|
|
||||||
to 0 otherwise.
|
|
||||||
|
|
||||||
- The system function ``$anyconst`` evaluates to any constant value. This is
|
|
||||||
equivalent to declaring a reg as ``rand const``, but also works outside
|
|
||||||
of checkers. (Yosys also supports ``rand const`` outside checkers.)
|
|
||||||
|
|
||||||
- The system function ``$anyseq`` evaluates to any value, possibly a different
|
|
||||||
value in each cycle. This is equivalent to declaring a reg as ``rand``,
|
|
||||||
but also works outside of checkers. (Yosys also supports ``rand``
|
|
||||||
variables outside checkers.)
|
|
||||||
|
|
||||||
- The system functions ``$allconst`` and ``$allseq`` can be used to construct
|
|
||||||
formal exist-forall problems. Assumptions only hold if the trace satisfies
|
|
||||||
the assumption for all ``$allconst/$allseq`` values. For assertions and cover
|
|
||||||
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
|
|
||||||
the property (similar to ``$anyconst/$anyseq``).
|
|
||||||
|
|
||||||
- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq`` attribute
|
|
||||||
(for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven
|
|
||||||
by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
|
|
||||||
|
|
||||||
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
|
|
||||||
supported in any clocked block.
|
|
||||||
|
|
||||||
- The syntax ``@($global_clock)`` can be used to create FFs that have no
|
|
||||||
explicit clock input (``$ff`` cells). The same can be achieved by using
|
|
||||||
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
|
|
||||||
is marked with the ``(* gclk *)`` Verilog attribute.
|
|
||||||
|
|
||||||
|
|
||||||
Supported features from SystemVerilog
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
When ``read_verilog`` is called with ``-sv``, it accepts some language features
|
|
||||||
from SystemVerilog:
|
|
||||||
|
|
||||||
- The ``assert`` statement from SystemVerilog is supported in its most basic
|
|
||||||
form. In module context: ``assert property (<expression>);`` and within an
|
|
||||||
always block: ``assert(<expression>);``. It is transformed to an ``$assert`` cell.
|
|
||||||
|
|
||||||
- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
|
|
||||||
also supported. The same limitations as with the ``assert`` statement apply.
|
|
||||||
|
|
||||||
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
|
|
||||||
and ``bit`` are supported.
|
|
||||||
|
|
||||||
- Declaring free variables with ``rand`` and ``rand const`` is supported.
|
|
||||||
|
|
||||||
- Checkers without a port list that do not need to be instantiated (but instead
|
|
||||||
behave like a named block) are supported.
|
|
||||||
|
|
||||||
- SystemVerilog packages are supported. Once a SystemVerilog file is read
|
|
||||||
into a design with ``read_verilog``, all its packages are available to
|
|
||||||
SystemVerilog files being read into the same design afterwards.
|
|
||||||
|
|
||||||
- typedefs are supported (including inside packages)
|
|
||||||
- type casts are currently not supported
|
|
||||||
|
|
||||||
- enums are supported (including inside packages)
|
|
||||||
- but are currently not strongly typed
|
|
||||||
|
|
||||||
- packed structs and unions are supported
|
|
||||||
- arrays of packed structs/unions are currently not supported
|
|
||||||
- structure literals are currently not supported
|
|
||||||
|
|
||||||
- multidimensional arrays are supported
|
|
||||||
- array assignment of unpacked arrays is currently not supported
|
|
||||||
- array literals are currently not supported
|
|
||||||
|
|
||||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
|
||||||
ports are inputs or outputs are supported.
|
|
||||||
|
|
||||||
- Assignments within expressions are supported.
|
|
||||||
|
|
||||||
|
|
||||||
Building the documentation
|
Building the documentation
|
||||||
|
|
2
abc
2
abc
|
@ -1 +1 @@
|
||||||
Subproject commit 2188bc71228b0788569d83ad2b7e7b91ca5dcc09
|
Subproject commit fcd8ac34d6105b48f32dfaf31983b071c46fb7b9
|
|
@ -132,7 +132,7 @@ struct AigerWriter
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool lmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
|
AigerWriter(Module *module, bool no_sort, bool zinit_mode, bool imode, bool omode, bool bmode, bool lmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
|
||||||
{
|
{
|
||||||
pool<SigBit> undriven_bits;
|
pool<SigBit> undriven_bits;
|
||||||
pool<SigBit> unused_bits;
|
pool<SigBit> unused_bits;
|
||||||
|
@ -152,6 +152,37 @@ struct AigerWriter
|
||||||
if (wire->port_input)
|
if (wire->port_input)
|
||||||
sigmap.add(wire);
|
sigmap.add(wire);
|
||||||
|
|
||||||
|
// handle ports
|
||||||
|
// provided the input_bits and output_bits don't get sorted they
|
||||||
|
// will be returned in reverse order, so add them in reverse to
|
||||||
|
// match
|
||||||
|
for (auto riter = module->ports.rbegin(); riter != module->ports.rend(); ++riter) {
|
||||||
|
auto *wire = module->wire(*riter);
|
||||||
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
|
{
|
||||||
|
SigBit wirebit(wire, i);
|
||||||
|
SigBit bit = sigmap(wirebit);
|
||||||
|
|
||||||
|
if (bit.wire == nullptr) {
|
||||||
|
if (wire->port_output) {
|
||||||
|
aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
|
||||||
|
output_bits.insert(wirebit);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wire->port_input)
|
||||||
|
input_bits.insert(bit);
|
||||||
|
|
||||||
|
if (wire->port_output) {
|
||||||
|
if (bit != wirebit)
|
||||||
|
alias_map[wirebit] = bit;
|
||||||
|
output_bits.insert(wirebit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle wires
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
{
|
{
|
||||||
if (wire->attributes.count(ID::init)) {
|
if (wire->attributes.count(ID::init)) {
|
||||||
|
@ -167,25 +198,13 @@ struct AigerWriter
|
||||||
SigBit wirebit(wire, i);
|
SigBit wirebit(wire, i);
|
||||||
SigBit bit = sigmap(wirebit);
|
SigBit bit = sigmap(wirebit);
|
||||||
|
|
||||||
if (bit.wire == nullptr) {
|
if (bit.wire == nullptr)
|
||||||
if (wire->port_output) {
|
continue;
|
||||||
aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
|
if (wire->port_input || wire->port_output)
|
||||||
output_bits.insert(wirebit);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
undriven_bits.insert(bit);
|
undriven_bits.insert(bit);
|
||||||
unused_bits.insert(bit);
|
unused_bits.insert(bit);
|
||||||
|
|
||||||
if (wire->port_input)
|
|
||||||
input_bits.insert(bit);
|
|
||||||
|
|
||||||
if (wire->port_output) {
|
|
||||||
if (bit != wirebit)
|
|
||||||
alias_map[wirebit] = bit;
|
|
||||||
output_bits.insert(wirebit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wire->width == 1) {
|
if (wire->width == 1) {
|
||||||
|
@ -200,12 +219,6 @@ struct AigerWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto bit : input_bits)
|
|
||||||
undriven_bits.erase(bit);
|
|
||||||
|
|
||||||
for (auto bit : output_bits)
|
|
||||||
unused_bits.erase(bit);
|
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
for (auto cell : module->cells())
|
||||||
{
|
{
|
||||||
if (cell->type == ID($_NOT_))
|
if (cell->type == ID($_NOT_))
|
||||||
|
@ -343,8 +356,11 @@ struct AigerWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
init_map.sort();
|
init_map.sort();
|
||||||
input_bits.sort();
|
// we are relying here on unsorted pools iterating last-in-first-out
|
||||||
output_bits.sort();
|
if (!no_sort) {
|
||||||
|
input_bits.sort();
|
||||||
|
output_bits.sort();
|
||||||
|
}
|
||||||
not_map.sort();
|
not_map.sort();
|
||||||
ff_map.sort();
|
ff_map.sort();
|
||||||
and_map.sort();
|
and_map.sort();
|
||||||
|
@ -662,8 +678,7 @@ struct AigerWriter
|
||||||
f << std::endl;
|
f << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
f << stringf("c\nGenerated by %s\n", yosys_maybe_version());
|
||||||
f << stringf("c\nGenerated by %s\n", yosys_version_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_map(std::ostream &f, bool verbose_map, bool no_startoffset)
|
void write_map(std::ostream &f, bool verbose_map, bool no_startoffset)
|
||||||
|
@ -698,7 +713,7 @@ struct AigerWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wire->port_output) {
|
if (wire->port_output) {
|
||||||
int o = ordered_outputs.at(sig[i]);
|
int o = ordered_outputs.at(SigSpec(wire, i));
|
||||||
output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire));
|
output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,7 +761,7 @@ struct AigerWriter
|
||||||
{
|
{
|
||||||
json.begin_object();
|
json.begin_object();
|
||||||
json.entry("version", "Yosys Witness Aiger map");
|
json.entry("version", "Yosys Witness Aiger map");
|
||||||
json.entry("gennerator", yosys_version_str);
|
json.entry("gennerator", yosys_maybe_version());
|
||||||
|
|
||||||
json.entry("latch_count", aig_l);
|
json.entry("latch_count", aig_l);
|
||||||
json.entry("input_count", aig_i);
|
json.entry("input_count", aig_i);
|
||||||
|
@ -902,6 +917,9 @@ struct AigerBackend : public Backend {
|
||||||
log(" -symbols\n");
|
log(" -symbols\n");
|
||||||
log(" include a symbol table in the generated AIGER file\n");
|
log(" include a symbol table in the generated AIGER file\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -no-sort\n");
|
||||||
|
log(" don't sort input/output ports\n");
|
||||||
|
log("\n");
|
||||||
log(" -map <filename>\n");
|
log(" -map <filename>\n");
|
||||||
log(" write an extra file with port and latch symbols\n");
|
log(" write an extra file with port and latch symbols\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -926,6 +944,7 @@ struct AigerBackend : public Backend {
|
||||||
bool zinit_mode = false;
|
bool zinit_mode = false;
|
||||||
bool miter_mode = false;
|
bool miter_mode = false;
|
||||||
bool symbols_mode = false;
|
bool symbols_mode = false;
|
||||||
|
bool no_sort = false;
|
||||||
bool verbose_map = false;
|
bool verbose_map = false;
|
||||||
bool imode = false;
|
bool imode = false;
|
||||||
bool omode = false;
|
bool omode = false;
|
||||||
|
@ -956,6 +975,10 @@ struct AigerBackend : public Backend {
|
||||||
symbols_mode = true;
|
symbols_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-no-sort") {
|
||||||
|
no_sort = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) {
|
if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) {
|
||||||
map_filename = args[++argidx];
|
map_filename = args[++argidx];
|
||||||
continue;
|
continue;
|
||||||
|
@ -1009,7 +1032,7 @@ struct AigerBackend : public Backend {
|
||||||
if (!top_module->memories.empty())
|
if (!top_module->memories.empty())
|
||||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module));
|
log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module));
|
||||||
|
|
||||||
AigerWriter writer(top_module, zinit_mode, imode, omode, bmode, lmode);
|
AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode);
|
||||||
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
||||||
|
|
||||||
if (!map_filename.empty()) {
|
if (!map_filename.empty()) {
|
||||||
|
|
|
@ -53,6 +53,8 @@ struct XAigerWriter
|
||||||
dict<SigBit, float> arrival_times;
|
dict<SigBit, float> arrival_times;
|
||||||
|
|
||||||
vector<pair<int, int>> aig_gates;
|
vector<pair<int, int>> aig_gates;
|
||||||
|
vector<SigBit> bit2aig_stack;
|
||||||
|
int next_loop_check = 1024;
|
||||||
vector<int> aig_outputs;
|
vector<int> aig_outputs;
|
||||||
int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0;
|
int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0;
|
||||||
|
|
||||||
|
@ -76,6 +78,24 @@ struct XAigerWriter
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GetSize(bit2aig_stack)== next_loop_check) {
|
||||||
|
for (int i = 0; i < next_loop_check; ++i)
|
||||||
|
{
|
||||||
|
SigBit report_bit = bit2aig_stack[i];
|
||||||
|
if (report_bit != bit)
|
||||||
|
continue;
|
||||||
|
for (int j = i; j < next_loop_check; ++j) {
|
||||||
|
report_bit = bit2aig_stack[j];
|
||||||
|
if (report_bit.is_wire() && report_bit.wire->name.isPublic())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log_error("Found combinatorial logic loop while processing signal %s.\n", log_signal(report_bit));
|
||||||
|
}
|
||||||
|
next_loop_check *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit2aig_stack.push_back(bit);
|
||||||
|
|
||||||
// NB: Cannot use iterator returned from aig_map.insert()
|
// NB: Cannot use iterator returned from aig_map.insert()
|
||||||
// since this function is called recursively
|
// since this function is called recursively
|
||||||
|
|
||||||
|
@ -93,6 +113,8 @@ struct XAigerWriter
|
||||||
a = bit2aig(alias_map.at(bit));
|
a = bit2aig(alias_map.at(bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bit2aig_stack.pop_back();
|
||||||
|
|
||||||
if (bit == State::Sx || bit == State::Sz) {
|
if (bit == State::Sx || bit == State::Sz) {
|
||||||
log_debug("Design contains 'x' or 'z' bits. Treating as 1'b0.\n");
|
log_debug("Design contains 'x' or 'z' bits. Treating as 1'b0.\n");
|
||||||
a = aig_map.at(State::S0);
|
a = aig_map.at(State::S0);
|
||||||
|
@ -649,7 +671,7 @@ struct XAigerWriter
|
||||||
//f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
|
//f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
|
||||||
//f.write(buffer_str.data(), buffer_str.size());
|
//f.write(buffer_str.data(), buffer_str.size());
|
||||||
|
|
||||||
f << stringf("Generated by %s\n", yosys_version_str);
|
f << stringf("Generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
design->scratchpad_set_int("write_xaiger.num_ands", and_map.size());
|
design->scratchpad_set_int("write_xaiger.num_ands", and_map.size());
|
||||||
design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size());
|
design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size());
|
||||||
|
|
1
backends/aiger2/Makefile.inc
Normal file
1
backends/aiger2/Makefile.inc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
OBJS += backends/aiger2/aiger.o
|
1464
backends/aiger2/aiger.cc
Normal file
1464
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 &inputs = cell->getPort(ID::A);
|
||||||
auto width = cell->parameters.at(ID::WIDTH).as_int();
|
auto width = cell->parameters.at(ID::WIDTH).as_int();
|
||||||
auto depth = cell->parameters.at(ID::DEPTH).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)
|
while (GetSize(table) < 2*width*depth)
|
||||||
table.push_back(State::S0);
|
table.push_back(State::S0);
|
||||||
log_assert(inputs.size() == width);
|
log_assert(inputs.size() == width);
|
||||||
|
@ -649,7 +649,7 @@ struct BlifBackend : public Backend {
|
||||||
if (module->get_bool_attribute(ID::top))
|
if (module->get_bool_attribute(ID::top))
|
||||||
top_module_name = module->name.str();
|
top_module_name = module->name.str();
|
||||||
|
|
||||||
*f << stringf("# Generated by %s\n", yosys_version_str);
|
*f << stringf("# Generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
std::vector<RTLIL::Module*> mod_list;
|
std::vector<RTLIL::Module*> mod_list;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
#include "kernel/json.h"
|
#include "kernel/json.h"
|
||||||
#include "kernel/yw.h"
|
#include "kernel/yw.h"
|
||||||
|
#include "kernel/utils.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
@ -711,9 +712,9 @@ struct BtorWorker
|
||||||
Const initval;
|
Const initval;
|
||||||
for (int i = 0; i < GetSize(sig_q); i++)
|
for (int i = 0; i < GetSize(sig_q); i++)
|
||||||
if (initbits.count(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
|
else
|
||||||
initval.bits.push_back(State::Sx);
|
initval.bits().push_back(State::Sx);
|
||||||
|
|
||||||
int nid_init_val = -1;
|
int nid_init_val = -1;
|
||||||
|
|
||||||
|
@ -832,7 +833,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)
|
if (verbose)
|
||||||
btorf("; initval = %s\n", log_signal(firstword));
|
btorf("; initval = %s\n", log_signal(firstword));
|
||||||
|
@ -1042,7 +1046,7 @@ struct BtorWorker
|
||||||
Const c(bit.data);
|
Const c(bit.data);
|
||||||
|
|
||||||
while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr)
|
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) {
|
if (consts.count(c) == 0) {
|
||||||
int sid = get_bv_sid(GetSize(c));
|
int sid = get_bv_sid(GetSize(c));
|
||||||
|
@ -1077,6 +1081,7 @@ struct BtorWorker
|
||||||
btorf("%d input %d\n", nid, sid);
|
btorf("%d input %d\n", nid, sid);
|
||||||
ywmap_input(s);
|
ywmap_input(s);
|
||||||
nid_width[nid] = GetSize(s);
|
nid_width[nid] = GetSize(s);
|
||||||
|
add_nid_sig(nid, s);
|
||||||
|
|
||||||
for (int j = 0; j < GetSize(s); j++)
|
for (int j = 0; j < GetSize(s); j++)
|
||||||
nidbits.push_back(make_pair(nid, j));
|
nidbits.push_back(make_pair(nid, j));
|
||||||
|
@ -1494,7 +1499,7 @@ struct BtorWorker
|
||||||
{
|
{
|
||||||
ywmap_json.begin_object();
|
ywmap_json.begin_object();
|
||||||
ywmap_json.entry("version", "Yosys Witness BTOR map");
|
ywmap_json.entry("version", "Yosys Witness BTOR map");
|
||||||
ywmap_json.entry("generator", yosys_version_str);
|
ywmap_json.entry("generator", yosys_maybe_version());
|
||||||
|
|
||||||
ywmap_json.name("clocks");
|
ywmap_json.name("clocks");
|
||||||
ywmap_json.begin_array();
|
ywmap_json.begin_array();
|
||||||
|
@ -1608,7 +1613,7 @@ struct BtorBackend : public Backend {
|
||||||
log_cmd_error("No top module found.\n");
|
log_cmd_error("No top module found.\n");
|
||||||
|
|
||||||
*f << stringf("; BTOR description generated by %s for module %s.\n",
|
*f << stringf("; BTOR description generated by %s for module %s.\n",
|
||||||
yosys_version_str, log_id(topmod));
|
yosys_maybe_version(), log_id(topmod));
|
||||||
|
|
||||||
BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename);
|
BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename);
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@ cd test_cells.tmp
|
||||||
|
|
||||||
for fn in test_*.il; do
|
for fn in test_*.il; do
|
||||||
../../../yosys -p "
|
../../../yosys -p "
|
||||||
read_ilang $fn
|
read_rtlil $fn
|
||||||
rename gold gate
|
rename gold gate
|
||||||
synth
|
synth
|
||||||
|
|
||||||
read_ilang $fn
|
read_rtlil $fn
|
||||||
miter -equiv -make_assert -flatten gold gate main
|
miter -equiv -make_assert -flatten gold gate main
|
||||||
hierarchy -top main
|
hierarchy -top main
|
||||||
write_btor ${fn%.il}.btor
|
write_btor ${fn%.il}.btor
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct Scheduler {
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
T *data;
|
T *data;
|
||||||
Vertex *prev, *next;
|
Vertex *prev, *next;
|
||||||
pool<Vertex*, hash_ptr_ops> preds, succs;
|
pool<Vertex*> preds, succs;
|
||||||
|
|
||||||
Vertex() : data(NULL), prev(this), next(this) {}
|
Vertex() : data(NULL), prev(this), next(this) {}
|
||||||
Vertex(T *data) : data(data), prev(NULL), next(NULL) {}
|
Vertex(T *data) : data(data), prev(NULL), next(NULL) {}
|
||||||
|
@ -200,7 +200,7 @@ bool is_extending_cell(RTLIL::IdString type)
|
||||||
bool is_inlinable_cell(RTLIL::IdString type)
|
bool is_inlinable_cell(RTLIL::IdString type)
|
||||||
{
|
{
|
||||||
return is_unary_cell(type) || is_binary_cell(type) || type.in(
|
return is_unary_cell(type) || is_binary_cell(type) || type.in(
|
||||||
ID($mux), ID($concat), ID($slice), ID($pmux), ID($bmux), ID($demux));
|
ID($mux), ID($concat), ID($slice), ID($pmux), ID($bmux), ID($demux), ID($bwmux));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_ff_cell(RTLIL::IdString type)
|
bool is_ff_cell(RTLIL::IdString type)
|
||||||
|
@ -300,10 +300,10 @@ struct FlowGraph {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Node*> nodes;
|
std::vector<Node*> nodes;
|
||||||
dict<const RTLIL::Wire*, pool<Node*, hash_ptr_ops>> wire_comb_defs, wire_sync_defs, wire_uses;
|
dict<const RTLIL::Wire*, pool<Node*>> wire_comb_defs, wire_sync_defs, wire_uses;
|
||||||
dict<Node*, pool<const RTLIL::Wire*>, hash_ptr_ops> node_comb_defs, node_sync_defs, node_uses;
|
dict<Node*, pool<const RTLIL::Wire*>> node_comb_defs, node_sync_defs, node_uses;
|
||||||
dict<const RTLIL::Wire*, bool> wire_def_inlinable;
|
dict<const RTLIL::Wire*, bool> wire_def_inlinable;
|
||||||
dict<const RTLIL::Wire*, dict<Node*, bool, hash_ptr_ops>> wire_use_inlinable;
|
dict<const RTLIL::Wire*, dict<Node*, bool>> wire_use_inlinable;
|
||||||
dict<RTLIL::SigBit, bool> bit_has_state;
|
dict<RTLIL::SigBit, bool> bit_has_state;
|
||||||
|
|
||||||
~FlowGraph()
|
~FlowGraph()
|
||||||
|
@ -328,7 +328,7 @@ struct FlowGraph {
|
||||||
node_comb_defs[node].insert(chunk.wire);
|
node_comb_defs[node].insert(chunk.wire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto bit : sig.bits())
|
for (auto bit : sig)
|
||||||
bit_has_state[bit] |= is_ff;
|
bit_has_state[bit] |= is_ff;
|
||||||
// Only comb defs of an entire wire in the right order can be inlined.
|
// Only comb defs of an entire wire in the right order can be inlined.
|
||||||
if (!is_ff && sig.is_wire()) {
|
if (!is_ff && sig.is_wire()) {
|
||||||
|
@ -365,7 +365,7 @@ struct FlowGraph {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_inlinable(const RTLIL::Wire *wire, const pool<Node*, hash_ptr_ops> &nodes) const
|
bool is_inlinable(const RTLIL::Wire *wire, const pool<Node*> &nodes) const
|
||||||
{
|
{
|
||||||
// Can the wire be inlined, knowing that the given nodes are reachable?
|
// Can the wire be inlined, knowing that the given nodes are reachable?
|
||||||
if (nodes.size() != 1)
|
if (nodes.size() != 1)
|
||||||
|
@ -612,11 +612,11 @@ std::string escape_c_string(const std::string &input)
|
||||||
output.push_back('"');
|
output.push_back('"');
|
||||||
for (auto c : input) {
|
for (auto c : input) {
|
||||||
if (::isprint(c)) {
|
if (::isprint(c)) {
|
||||||
if (c == '\\')
|
if (c == '\\' || c == '"')
|
||||||
output.push_back('\\');
|
output.push_back('\\');
|
||||||
output.push_back(c);
|
output.push_back(c);
|
||||||
} else {
|
} else {
|
||||||
char l = c & 0x3, m = (c >> 3) & 0x3, h = (c >> 6) & 0x3;
|
char l = c & 0x7, m = (c >> 3) & 0x7, h = (c >> 6) & 0x3;
|
||||||
output.append("\\");
|
output.append("\\");
|
||||||
output.push_back('0' + h);
|
output.push_back('0' + h);
|
||||||
output.push_back('0' + m);
|
output.push_back('0' + m);
|
||||||
|
@ -864,7 +864,7 @@ struct CxxrtlWorker {
|
||||||
if (!module->has_attribute(ID(cxxrtl_template)))
|
if (!module->has_attribute(ID(cxxrtl_template)))
|
||||||
return {};
|
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));
|
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");
|
std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
|
||||||
|
@ -1198,6 +1198,14 @@ struct CxxrtlWorker {
|
||||||
f << ">(";
|
f << ">(";
|
||||||
dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
|
dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
|
||||||
f << ").val()";
|
f << ").val()";
|
||||||
|
// Bitwise muxes
|
||||||
|
} else if (cell->type == ID($bwmux)) {
|
||||||
|
dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
|
||||||
|
f << ".bwmux(";
|
||||||
|
dump_sigspec_rhs(cell->getPort(ID::B), for_debug);
|
||||||
|
f << ",";
|
||||||
|
dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
|
||||||
|
f << ").val()";
|
||||||
// Demuxes
|
// Demuxes
|
||||||
} else if (cell->type == ID($demux)) {
|
} else if (cell->type == ID($demux)) {
|
||||||
dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
|
dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
|
||||||
|
@ -1665,15 +1673,15 @@ struct CxxrtlWorker {
|
||||||
switch (bit) {
|
switch (bit) {
|
||||||
case RTLIL::S0:
|
case RTLIL::S0:
|
||||||
case RTLIL::S1:
|
case RTLIL::S1:
|
||||||
compare_mask.bits.push_back(RTLIL::S1);
|
compare_mask.bits().push_back(RTLIL::S1);
|
||||||
compare_value.bits.push_back(bit);
|
compare_value.bits().push_back(bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTLIL::Sx:
|
case RTLIL::Sx:
|
||||||
case RTLIL::Sz:
|
case RTLIL::Sz:
|
||||||
case RTLIL::Sa:
|
case RTLIL::Sa:
|
||||||
compare_mask.bits.push_back(RTLIL::S0);
|
compare_mask.bits().push_back(RTLIL::S0);
|
||||||
compare_value.bits.push_back(RTLIL::S0);
|
compare_value.bits().push_back(RTLIL::S0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -2402,7 +2410,12 @@ struct CxxrtlWorker {
|
||||||
auto cell_attrs = scopeinfo_attributes(cell, ScopeinfoAttrs::Cell);
|
auto cell_attrs = scopeinfo_attributes(cell, ScopeinfoAttrs::Cell);
|
||||||
cell_attrs.erase(ID::module_not_derived);
|
cell_attrs.erase(ID::module_not_derived);
|
||||||
f << indent << "scopes->add(path, " << escape_cxx_string(get_hdl_name(cell)) << ", ";
|
f << indent << "scopes->add(path, " << escape_cxx_string(get_hdl_name(cell)) << ", ";
|
||||||
f << escape_cxx_string(cell->get_string_attribute(ID(module))) << ", ";
|
if (module_attrs.count(ID(hdlname))) {
|
||||||
|
f << escape_cxx_string(module_attrs.at(ID(hdlname)).decode_string());
|
||||||
|
} else {
|
||||||
|
f << escape_cxx_string(cell->get_string_attribute(ID(module)));
|
||||||
|
}
|
||||||
|
f << ", ";
|
||||||
dump_serialized_metadata(module_attrs);
|
dump_serialized_metadata(module_attrs);
|
||||||
f << ", ";
|
f << ", ";
|
||||||
dump_serialized_metadata(cell_attrs);
|
dump_serialized_metadata(cell_attrs);
|
||||||
|
@ -2416,8 +2429,6 @@ struct CxxrtlWorker {
|
||||||
inc_indent();
|
inc_indent();
|
||||||
for (auto wire : module->wires()) {
|
for (auto wire : module->wires()) {
|
||||||
const auto &debug_wire_type = debug_wire_types[wire];
|
const auto &debug_wire_type = debug_wire_types[wire];
|
||||||
if (!wire->name.isPublic())
|
|
||||||
continue;
|
|
||||||
count_public_wires++;
|
count_public_wires++;
|
||||||
switch (debug_wire_type.type) {
|
switch (debug_wire_type.type) {
|
||||||
case WireType::BUFFERED:
|
case WireType::BUFFERED:
|
||||||
|
@ -2425,6 +2436,9 @@ struct CxxrtlWorker {
|
||||||
// Member wire
|
// Member wire
|
||||||
std::vector<std::string> flags;
|
std::vector<std::string> flags;
|
||||||
|
|
||||||
|
if (!wire->name.isPublic())
|
||||||
|
flags.push_back("GENERATED");
|
||||||
|
|
||||||
if (wire->port_input && wire->port_output)
|
if (wire->port_input && wire->port_output)
|
||||||
flags.push_back("INOUT");
|
flags.push_back("INOUT");
|
||||||
else if (wire->port_output)
|
else if (wire->port_output)
|
||||||
|
@ -2497,7 +2511,7 @@ struct CxxrtlWorker {
|
||||||
// Alias of a member wire
|
// Alias of a member wire
|
||||||
const RTLIL::Wire *aliasee = debug_wire_type.sig_subst.as_wire();
|
const RTLIL::Wire *aliasee = debug_wire_type.sig_subst.as_wire();
|
||||||
f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
|
f << indent << "items->add(path, " << escape_cxx_string(get_hdl_name(wire)) << ", ";
|
||||||
dump_debug_attrs(aliasee);
|
dump_debug_attrs(wire);
|
||||||
f << ", ";
|
f << ", ";
|
||||||
// If the aliasee is an outline, then the alias must be an outline, too; otherwise downstream
|
// If the aliasee is an outline, then the alias must be an outline, too; otherwise downstream
|
||||||
// tooling has no way to find out about the outline.
|
// tooling has no way to find out about the outline.
|
||||||
|
@ -3028,7 +3042,7 @@ struct CxxrtlWorker {
|
||||||
if (init == RTLIL::Const()) {
|
if (init == RTLIL::Const()) {
|
||||||
init = RTLIL::Const(State::Sx, GetSize(bit.wire));
|
init = RTLIL::Const(State::Sx, GetSize(bit.wire));
|
||||||
}
|
}
|
||||||
init[bit.offset] = port.init_value[i];
|
init.bits()[bit.offset] = port.init_value[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3080,7 +3094,7 @@ struct CxxrtlWorker {
|
||||||
// without feedback arcs can generally be evaluated in a single pass, i.e. it always requires only
|
// without feedback arcs can generally be evaluated in a single pass, i.e. it always requires only
|
||||||
// a single delta cycle.
|
// a single delta cycle.
|
||||||
Scheduler<FlowGraph::Node> scheduler;
|
Scheduler<FlowGraph::Node> scheduler;
|
||||||
dict<FlowGraph::Node*, Scheduler<FlowGraph::Node>::Vertex*, hash_ptr_ops> node_vertex_map;
|
dict<FlowGraph::Node*, Scheduler<FlowGraph::Node>::Vertex*> node_vertex_map;
|
||||||
for (auto node : flow.nodes)
|
for (auto node : flow.nodes)
|
||||||
node_vertex_map[node] = scheduler.add(node);
|
node_vertex_map[node] = scheduler.add(node);
|
||||||
for (auto node_comb_def : flow.node_comb_defs) {
|
for (auto node_comb_def : flow.node_comb_defs) {
|
||||||
|
@ -3095,7 +3109,7 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
// Find out whether the order includes any feedback arcs.
|
// Find out whether the order includes any feedback arcs.
|
||||||
std::vector<FlowGraph::Node*> node_order;
|
std::vector<FlowGraph::Node*> node_order;
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> evaluated_nodes;
|
pool<FlowGraph::Node*> evaluated_nodes;
|
||||||
pool<const RTLIL::Wire*> feedback_wires;
|
pool<const RTLIL::Wire*> feedback_wires;
|
||||||
for (auto vertex : scheduler.schedule()) {
|
for (auto vertex : scheduler.schedule()) {
|
||||||
auto node = vertex->data;
|
auto node = vertex->data;
|
||||||
|
@ -3139,7 +3153,7 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discover nodes reachable from primary outputs (i.e. members) and collect reachable wire users.
|
// Discover nodes reachable from primary outputs (i.e. members) and collect reachable wire users.
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> worklist;
|
pool<FlowGraph::Node*> worklist;
|
||||||
for (auto node : flow.nodes) {
|
for (auto node : flow.nodes) {
|
||||||
if (node->type == FlowGraph::Node::Type::CELL_EVAL && !is_internal_cell(node->cell->type))
|
if (node->type == FlowGraph::Node::Type::CELL_EVAL && !is_internal_cell(node->cell->type))
|
||||||
worklist.insert(node); // node evaluates a submodule
|
worklist.insert(node); // node evaluates a submodule
|
||||||
|
@ -3159,8 +3173,8 @@ struct CxxrtlWorker {
|
||||||
worklist.insert(node); // node drives public wires
|
worklist.insert(node); // node drives public wires
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> live_wires;
|
dict<const RTLIL::Wire*, pool<FlowGraph::Node*>> live_wires;
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> live_nodes;
|
pool<FlowGraph::Node*> live_nodes;
|
||||||
while (!worklist.empty()) {
|
while (!worklist.empty()) {
|
||||||
auto node = worklist.pop();
|
auto node = worklist.pop();
|
||||||
live_nodes.insert(node);
|
live_nodes.insert(node);
|
||||||
|
@ -3290,15 +3304,15 @@ struct CxxrtlWorker {
|
||||||
|
|
||||||
// Discover nodes reachable from primary outputs (i.e. outlines) up until primary inputs (i.e. members)
|
// Discover nodes reachable from primary outputs (i.e. outlines) up until primary inputs (i.e. members)
|
||||||
// and collect reachable wire users.
|
// and collect reachable wire users.
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> worklist;
|
pool<FlowGraph::Node*> worklist;
|
||||||
for (auto node : flow.nodes) {
|
for (auto node : flow.nodes) {
|
||||||
if (flow.node_comb_defs.count(node))
|
if (flow.node_comb_defs.count(node))
|
||||||
for (auto wire : flow.node_comb_defs[node])
|
for (auto wire : flow.node_comb_defs[node])
|
||||||
if (debug_wire_types[wire].is_outline())
|
if (debug_wire_types[wire].is_outline())
|
||||||
worklist.insert(node); // node drives outline
|
worklist.insert(node); // node drives outline
|
||||||
}
|
}
|
||||||
dict<const RTLIL::Wire*, pool<FlowGraph::Node*, hash_ptr_ops>> debug_live_wires;
|
dict<const RTLIL::Wire*, pool<FlowGraph::Node*>> debug_live_wires;
|
||||||
pool<FlowGraph::Node*, hash_ptr_ops> debug_live_nodes;
|
pool<FlowGraph::Node*> debug_live_nodes;
|
||||||
while (!worklist.empty()) {
|
while (!worklist.empty()) {
|
||||||
auto node = worklist.pop();
|
auto node = worklist.pop();
|
||||||
debug_live_nodes.insert(node);
|
debug_live_nodes.insert(node);
|
||||||
|
|
|
@ -200,6 +200,10 @@ enum cxxrtl_flag {
|
||||||
// node, such as inputs and dangling wires.
|
// node, such as inputs and dangling wires.
|
||||||
CXXRTL_UNDRIVEN = 1 << 4,
|
CXXRTL_UNDRIVEN = 1 << 4,
|
||||||
|
|
||||||
|
// Generated correspond to netlist nodes that correspond to state with an internal name, that
|
||||||
|
// need to be saved, but wouldn't otherwise have a debug item generated.
|
||||||
|
CXXRTL_GENERATED = 1 << 5,
|
||||||
|
|
||||||
// More object flags may be added in the future, but the existing ones will never change.
|
// More object flags may be added in the future, but the existing ones will never change.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -498,6 +498,11 @@ struct value : public expr_base<value<Bits>> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CXXRTL_ALWAYS_INLINE
|
||||||
|
value<Bits> bwmux(const value<Bits> &b, const value<Bits> &s) const {
|
||||||
|
return (bit_and(s.bit_not())).bit_or(b.bit_and(s));
|
||||||
|
}
|
||||||
|
|
||||||
template<size_t ResultBits, size_t SelBits>
|
template<size_t ResultBits, size_t SelBits>
|
||||||
value<ResultBits> demux(const value<SelBits> &sel) const {
|
value<ResultBits> demux(const value<SelBits> &sel) const {
|
||||||
static_assert(Bits << SelBits == ResultBits, "invalid sizes used in demux()");
|
static_assert(Bits << SelBits == ResultBits, "invalid sizes used in demux()");
|
||||||
|
@ -1127,7 +1132,7 @@ struct fmt_part {
|
||||||
}
|
}
|
||||||
|
|
||||||
case UNICHAR: {
|
case UNICHAR: {
|
||||||
uint32_t codepoint = val.template get<uint32_t>();
|
uint32_t codepoint = val.template zcast<32>().template get<uint32_t>();
|
||||||
if (codepoint >= 0x10000)
|
if (codepoint >= 0x10000)
|
||||||
buf += (char)(0xf0 | (codepoint >> 18));
|
buf += (char)(0xf0 | (codepoint >> 18));
|
||||||
else if (codepoint >= 0x800)
|
else if (codepoint >= 0x800)
|
||||||
|
@ -1289,6 +1294,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
DRIVEN_SYNC = CXXRTL_DRIVEN_SYNC,
|
DRIVEN_SYNC = CXXRTL_DRIVEN_SYNC,
|
||||||
DRIVEN_COMB = CXXRTL_DRIVEN_COMB,
|
DRIVEN_COMB = CXXRTL_DRIVEN_COMB,
|
||||||
UNDRIVEN = CXXRTL_UNDRIVEN,
|
UNDRIVEN = CXXRTL_UNDRIVEN,
|
||||||
|
GENERATED = CXXRTL_GENERATED,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {}
|
debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {}
|
||||||
|
@ -1764,7 +1770,7 @@ value<BitsY> shr_uu(const value<BitsA> &a, const value<BitsB> &b) {
|
||||||
template<size_t BitsY, size_t BitsA, size_t BitsB>
|
template<size_t BitsY, size_t BitsA, size_t BitsB>
|
||||||
CXXRTL_ALWAYS_INLINE
|
CXXRTL_ALWAYS_INLINE
|
||||||
value<BitsY> shr_su(const value<BitsA> &a, const value<BitsB> &b) {
|
value<BitsY> shr_su(const value<BitsA> &a, const value<BitsB> &b) {
|
||||||
return a.shr(b).template scast<BitsY>();
|
return a.template scast<BitsY>().shr(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t BitsY, size_t BitsA, size_t BitsB>
|
template<size_t BitsY, size_t BitsA, size_t BitsB>
|
||||||
|
@ -2005,7 +2011,7 @@ std::pair<value<BitsY>, value<BitsY>> divmod_uu(const value<BitsA> &a, const val
|
||||||
value<Bits> quotient;
|
value<Bits> quotient;
|
||||||
value<Bits> remainder;
|
value<Bits> remainder;
|
||||||
value<Bits> dividend = a.template zext<Bits>();
|
value<Bits> dividend = a.template zext<Bits>();
|
||||||
value<Bits> divisor = b.template zext<Bits>();
|
value<Bits> divisor = b.template trunc<BitsB>().template zext<Bits>();
|
||||||
std::tie(quotient, remainder) = dividend.udivmod(divisor);
|
std::tie(quotient, remainder) = dividend.udivmod(divisor);
|
||||||
return {quotient.template trunc<BitsY>(), remainder.template trunc<BitsY>()};
|
return {quotient.template trunc<BitsY>(), remainder.template trunc<BitsY>()};
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,13 @@ class vcd_writer {
|
||||||
|
|
||||||
void emit_scope(const std::vector<std::string> &scope) {
|
void emit_scope(const std::vector<std::string> &scope) {
|
||||||
assert(!streaming);
|
assert(!streaming);
|
||||||
while (current_scope.size() > scope.size() ||
|
size_t same_scope_count = 0;
|
||||||
(current_scope.size() > 0 &&
|
while ((same_scope_count < current_scope.size()) &&
|
||||||
current_scope[current_scope.size() - 1] != scope[current_scope.size() - 1])) {
|
(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";
|
buffer += "$upscope $end\n";
|
||||||
current_scope.pop_back();
|
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))));
|
bool bit_curr = var.curr[bit / (8 * sizeof(chunk_t))] & (1 << (bit % (8 * sizeof(chunk_t))));
|
||||||
buffer += (bit_curr ? '1' : '0');
|
buffer += (bit_curr ? '1' : '0');
|
||||||
}
|
}
|
||||||
|
if (var.width == 0)
|
||||||
|
buffer += '0';
|
||||||
buffer += ' ';
|
buffer += ' ';
|
||||||
emit_ident(var.ident);
|
emit_ident(var.ident);
|
||||||
buffer += '\n';
|
buffer += '\n';
|
||||||
|
|
|
@ -231,7 +231,8 @@ struct EdifBackend : public Backend {
|
||||||
*f << stringf(" (edifVersion 2 0 0)\n");
|
*f << stringf(" (edifVersion 2 0 0)\n");
|
||||||
*f << stringf(" (edifLevel 0)\n");
|
*f << stringf(" (edifLevel 0)\n");
|
||||||
*f << stringf(" (keywordMap (keywordLevel 0))\n");
|
*f << stringf(" (keywordMap (keywordLevel 0))\n");
|
||||||
*f << stringf(" (comment \"Generated by %s\")\n", yosys_version_str);
|
|
||||||
|
*f << stringf(" (comment \"Generated by %s\")\n", yosys_maybe_version());
|
||||||
|
|
||||||
*f << stringf(" (external LIB\n");
|
*f << stringf(" (external LIB\n");
|
||||||
*f << stringf(" (edifLevel 0)\n");
|
*f << stringf(" (edifLevel 0)\n");
|
||||||
|
@ -334,20 +335,20 @@ struct EdifBackend : public Backend {
|
||||||
auto add_prop = [&](IdString name, Const val) {
|
auto add_prop = [&](IdString name, Const val) {
|
||||||
if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
|
if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
|
||||||
*f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str());
|
*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());
|
*f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
|
||||||
else {
|
else {
|
||||||
std::string hex_string = "";
|
std::string hex_string = "";
|
||||||
for (size_t i = 0; i < val.bits.size(); i += 4) {
|
for (auto i = 0; i < val.size(); i += 4) {
|
||||||
int digit_value = 0;
|
int digit_value = 0;
|
||||||
if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1;
|
if (i+0 < val.size() && val.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+1 < val.size() && val.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+2 < val.size() && val.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+3 < val.size() && val.at(i+3) == RTLIL::State::S1) digit_value |= 8;
|
||||||
char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
|
char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
|
||||||
hex_string = std::string(digit_str) + hex_string;
|
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)
|
for (auto module : sorted_modules)
|
||||||
|
|
|
@ -149,7 +149,7 @@ std::string dump_const(const RTLIL::Const &data)
|
||||||
// Numeric (non-real) parameter.
|
// Numeric (non-real) parameter.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int width = data.bits.size();
|
int width = data.size();
|
||||||
|
|
||||||
// If a standard 32-bit int, then emit standard int value like "56" or
|
// If a standard 32-bit int, then emit standard int value like "56" or
|
||||||
// "-56". Firrtl supports negative-valued int literals.
|
// "-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++)
|
for (int i = 0; i < width; i++)
|
||||||
{
|
{
|
||||||
switch (data.bits[i])
|
switch (data[i])
|
||||||
{
|
{
|
||||||
case State::S0: break;
|
case State::S0: break;
|
||||||
case State::S1: int_val |= (1 << i); 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--)
|
for (int i = width - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
log_assert(i < width);
|
log_assert(i < width);
|
||||||
switch (data.bits[i])
|
switch (data[i])
|
||||||
{
|
{
|
||||||
case State::S0: res_str += "0"; break;
|
case State::S0: res_str += "0"; break;
|
||||||
case State::S1: res_str += "1"; break;
|
case State::S1: res_str += "1"; break;
|
||||||
|
@ -1215,9 +1215,6 @@ struct FirrtlBackend : public Backend {
|
||||||
}
|
}
|
||||||
extra_args(f, filename, args, argidx);
|
extra_args(f, filename, args, argidx);
|
||||||
|
|
||||||
if (!design->full_selection())
|
|
||||||
log_cmd_error("This command only operates on fully selected designs!\n");
|
|
||||||
|
|
||||||
log_header(design, "Executing FIRRTL backend.\n");
|
log_header(design, "Executing FIRRTL backend.\n");
|
||||||
log_push();
|
log_push();
|
||||||
|
|
||||||
|
@ -1226,11 +1223,12 @@ struct FirrtlBackend : public Backend {
|
||||||
Pass::call(design, "demuxmap");
|
Pass::call(design, "demuxmap");
|
||||||
Pass::call(design, "bwmuxmap");
|
Pass::call(design, "bwmuxmap");
|
||||||
|
|
||||||
|
used_names.clear();
|
||||||
namecache.clear();
|
namecache.clear();
|
||||||
autoid_counter = 0;
|
autoid_counter = 0;
|
||||||
|
|
||||||
// Get the top module, or a reasonable facsimile - we need something for the circuit name.
|
// Get the top module, or a reasonable facsimile - we need something for the circuit name.
|
||||||
Module *top = design->top_module();
|
Module *top = nullptr;
|
||||||
Module *last = nullptr;
|
Module *last = nullptr;
|
||||||
// Generate module and wire names.
|
// Generate module and wire names.
|
||||||
for (auto module : design->modules()) {
|
for (auto module : design->modules()) {
|
||||||
|
@ -1265,6 +1263,7 @@ struct FirrtlBackend : public Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
used_names.clear();
|
||||||
namecache.clear();
|
namecache.clear();
|
||||||
autoid_counter = 0;
|
autoid_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,6 +246,8 @@ struct FunctionalCxxBackend : public Backend
|
||||||
{
|
{
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log("TODO: add help message\n");
|
||||||
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void printCxx(std::ostream &stream, std::string, Module *module)
|
void printCxx(std::ostream &stream, std::string, Module *module)
|
||||||
|
|
|
@ -210,14 +210,8 @@ struct SmtrModule {
|
||||||
state_struct.insert(state->name, state->sort);
|
state_struct.insert(state->name, state->sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(std::ostream &out)
|
void write_eval(SExprWriter &w)
|
||||||
{
|
{
|
||||||
SExprWriter w(out);
|
|
||||||
|
|
||||||
input_struct.write_definition(w);
|
|
||||||
output_struct.write_definition(w);
|
|
||||||
state_struct.write_definition(w);
|
|
||||||
|
|
||||||
w.push();
|
w.push();
|
||||||
w.open(list("define", list(name, "inputs", "state")));
|
w.open(list("define", list(name, "inputs", "state")));
|
||||||
auto inlined = [&](Functional::Node n) {
|
auto inlined = [&](Functional::Node n) {
|
||||||
|
@ -240,7 +234,10 @@ struct SmtrModule {
|
||||||
output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.output(name).value()); });
|
output_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.output(name).value()); });
|
||||||
state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.state(name).next_value()); });
|
state_struct.write_value(w, [&](IdString name) { return node_to_sexpr(ir.state(name).next_value()); });
|
||||||
w.pop();
|
w.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_initial(SExprWriter &w)
|
||||||
|
{
|
||||||
w.push();
|
w.push();
|
||||||
auto initial = name + "_initial";
|
auto initial = name + "_initial";
|
||||||
w.open(list("define", initial));
|
w.open(list("define", initial));
|
||||||
|
@ -259,6 +256,18 @@ struct SmtrModule {
|
||||||
}
|
}
|
||||||
w.pop();
|
w.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write(std::ostream &out)
|
||||||
|
{
|
||||||
|
SExprWriter w(out);
|
||||||
|
|
||||||
|
input_struct.write_definition(w);
|
||||||
|
output_struct.write_definition(w);
|
||||||
|
state_struct.write_definition(w);
|
||||||
|
|
||||||
|
write_eval(w);
|
||||||
|
write_initial(w);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionalSmtrBackend : public Backend {
|
struct FunctionalSmtrBackend : public Backend {
|
||||||
|
@ -267,7 +276,7 @@ struct FunctionalSmtrBackend : public Backend {
|
||||||
void help() override {
|
void help() override {
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" write_functional_rosette [options] [selection] [filename]\n");
|
log(" write_functional_rosette [options] [filename]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Functional Rosette Backend.\n");
|
log("Functional Rosette Backend.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
|
|
@ -105,7 +105,7 @@ struct MemContentsTest {
|
||||||
RTLIL::Const values;
|
RTLIL::Const values;
|
||||||
for(addr_t addr = low; addr <= high; addr++) {
|
for(addr_t addr = low; addr <= high; addr++) {
|
||||||
RTLIL::Const word(data_dist(rnd), data_width);
|
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);
|
insert_concatenated(low, values);
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,8 @@ struct FunctionalTestGeneric : public Pass
|
||||||
{
|
{
|
||||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log("TODO: add help message\n");
|
||||||
|
log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
|
|
@ -176,11 +176,11 @@ struct IntersynthBackend : public Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto ¶m : cell->parameters) {
|
for (auto ¶m : cell->parameters) {
|
||||||
celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), log_id(param.first));
|
celltype_code += stringf(" cfg:%d %s", int(param.second.size()), log_id(param.first));
|
||||||
if (param.second.bits.size() != 32) {
|
if (param.second.size() != 32) {
|
||||||
node_code += stringf(" %s '", log_id(param.first));
|
node_code += stringf(" %s '", log_id(param.first));
|
||||||
for (int i = param.second.bits.size()-1; i >= 0; i--)
|
for (int i = param.second.size()-1; i >= 0; i--)
|
||||||
node_code += param.second.bits[i] == State::S1 ? "1" : "0";
|
node_code += param.second[i] == State::S1 ? "1" : "0";
|
||||||
} else
|
} else
|
||||||
node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int());
|
node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int());
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ struct JnyWriter
|
||||||
|
|
||||||
f << "{\n";
|
f << "{\n";
|
||||||
f << " \"$schema\": \"https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json\",\n";
|
f << " \"$schema\": \"https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json\",\n";
|
||||||
f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_version_str).c_str());
|
f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_maybe_version()).c_str());
|
||||||
f << " \"version\": \"0.0.1\",\n";
|
f << " \"version\": \"0.0.1\",\n";
|
||||||
f << " \"invocation\": \"" << escape_string(invk) << "\",\n";
|
f << " \"invocation\": \"" << escape_string(invk) << "\",\n";
|
||||||
f << " \"features\": [";
|
f << " \"features\": [";
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct JsonWriter
|
||||||
bool use_selection;
|
bool use_selection;
|
||||||
bool aig_mode;
|
bool aig_mode;
|
||||||
bool compat_int_mode;
|
bool compat_int_mode;
|
||||||
|
bool scopeinfo_mode;
|
||||||
|
|
||||||
Design *design;
|
Design *design;
|
||||||
Module *module;
|
Module *module;
|
||||||
|
@ -43,9 +44,9 @@ struct JsonWriter
|
||||||
dict<SigBit, string> sigids;
|
dict<SigBit, string> sigids;
|
||||||
pool<Aig> aig_models;
|
pool<Aig> aig_models;
|
||||||
|
|
||||||
JsonWriter(std::ostream &f, bool use_selection, bool aig_mode, bool compat_int_mode) :
|
JsonWriter(std::ostream &f, bool use_selection, bool aig_mode, bool compat_int_mode, bool scopeinfo_mode) :
|
||||||
f(f), use_selection(use_selection), aig_mode(aig_mode),
|
f(f), use_selection(use_selection), aig_mode(aig_mode),
|
||||||
compat_int_mode(compat_int_mode) { }
|
compat_int_mode(compat_int_mode), scopeinfo_mode(scopeinfo_mode) { }
|
||||||
|
|
||||||
string get_string(string str)
|
string get_string(string str)
|
||||||
{
|
{
|
||||||
|
@ -192,9 +193,7 @@ struct JsonWriter
|
||||||
for (auto c : module->cells()) {
|
for (auto c : module->cells()) {
|
||||||
if (use_selection && !module->selected(c))
|
if (use_selection && !module->selected(c))
|
||||||
continue;
|
continue;
|
||||||
// Eventually we will want to emit $scopeinfo, but currently this
|
if (!scopeinfo_mode && c->type == ID($scopeinfo))
|
||||||
// will break JSON netlist consumers like nextpnr
|
|
||||||
if (c->type == ID($scopeinfo))
|
|
||||||
continue;
|
continue;
|
||||||
f << stringf("%s\n", first ? "" : ",");
|
f << stringf("%s\n", first ? "" : ",");
|
||||||
f << stringf(" %s: {\n", get_name(c->name).c_str());
|
f << stringf(" %s: {\n", get_name(c->name).c_str());
|
||||||
|
@ -292,7 +291,7 @@ struct JsonWriter
|
||||||
design->sort();
|
design->sort();
|
||||||
|
|
||||||
f << stringf("{\n");
|
f << stringf("{\n");
|
||||||
f << stringf(" \"creator\": %s,\n", get_string(yosys_version_str).c_str());
|
f << stringf(" \"creator\": %s,\n", get_string(yosys_maybe_version()).c_str());
|
||||||
f << stringf(" \"modules\": {\n");
|
f << stringf(" \"modules\": {\n");
|
||||||
vector<Module*> modules = use_selection ? design->selected_modules() : design->modules();
|
vector<Module*> modules = use_selection ? design->selected_modules() : design->modules();
|
||||||
bool first_module = true;
|
bool first_module = true;
|
||||||
|
@ -353,6 +352,12 @@ struct JsonBackend : public Backend {
|
||||||
log(" emit 32-bit or smaller fully-defined parameter values directly\n");
|
log(" emit 32-bit or smaller fully-defined parameter values directly\n");
|
||||||
log(" as JSON numbers (for compatibility with old parsers)\n");
|
log(" as JSON numbers (for compatibility with old parsers)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -selected\n");
|
||||||
|
log(" output only select module\n");
|
||||||
|
log("\n");
|
||||||
|
log(" -noscopeinfo\n");
|
||||||
|
log(" don't include $scopeinfo cells in the output\n");
|
||||||
|
log("\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The general syntax of the JSON output created by this command is as follows:\n");
|
log("The general syntax of the JSON output created by this command is as follows:\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -403,7 +408,7 @@ struct JsonBackend : public Backend {
|
||||||
log("\n");
|
log("\n");
|
||||||
log("The \"offset\" and \"upto\" fields are skipped if their value would be 0.\n");
|
log("The \"offset\" and \"upto\" fields are skipped if their value would be 0.\n");
|
||||||
log("They don't affect connection semantics, and are only used to preserve original\n");
|
log("They don't affect connection semantics, and are only used to preserve original\n");
|
||||||
log("HDL bit indexing.");
|
log("HDL bit indexing.\n");
|
||||||
log("And <cell_details> is:\n");
|
log("And <cell_details> is:\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" {\n");
|
log(" {\n");
|
||||||
|
@ -597,6 +602,8 @@ struct JsonBackend : public Backend {
|
||||||
{
|
{
|
||||||
bool aig_mode = false;
|
bool aig_mode = false;
|
||||||
bool compat_int_mode = false;
|
bool compat_int_mode = false;
|
||||||
|
bool use_selection = false;
|
||||||
|
bool scopeinfo_mode = true;
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
@ -609,13 +616,21 @@ struct JsonBackend : public Backend {
|
||||||
compat_int_mode = true;
|
compat_int_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-selected") {
|
||||||
|
use_selection = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args[argidx] == "-noscopeinfo") {
|
||||||
|
scopeinfo_mode = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(f, filename, args, argidx);
|
extra_args(f, filename, args, argidx);
|
||||||
|
|
||||||
log_header(design, "Executing JSON backend.\n");
|
log_header(design, "Executing JSON backend.\n");
|
||||||
|
|
||||||
JsonWriter json_writer(*f, false, aig_mode, compat_int_mode);
|
JsonWriter json_writer(*f, use_selection, aig_mode, compat_int_mode, scopeinfo_mode);
|
||||||
json_writer.write_design(design);
|
json_writer.write_design(design);
|
||||||
}
|
}
|
||||||
} JsonBackend;
|
} JsonBackend;
|
||||||
|
@ -640,6 +655,9 @@ struct JsonPass : public Pass {
|
||||||
log(" emit 32-bit or smaller fully-defined parameter values directly\n");
|
log(" emit 32-bit or smaller fully-defined parameter values directly\n");
|
||||||
log(" as JSON numbers (for compatibility with old parsers)\n");
|
log(" as JSON numbers (for compatibility with old parsers)\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -noscopeinfo\n");
|
||||||
|
log(" don't include $scopeinfo cells in the output\n");
|
||||||
|
log("\n");
|
||||||
log("See 'help write_json' for a description of the JSON format used.\n");
|
log("See 'help write_json' for a description of the JSON format used.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
@ -648,6 +666,7 @@ struct JsonPass : public Pass {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
bool aig_mode = false;
|
bool aig_mode = false;
|
||||||
bool compat_int_mode = false;
|
bool compat_int_mode = false;
|
||||||
|
bool scopeinfo_mode = true;
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++)
|
for (argidx = 1; argidx < args.size(); argidx++)
|
||||||
|
@ -664,6 +683,10 @@ struct JsonPass : public Pass {
|
||||||
compat_int_mode = true;
|
compat_int_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (args[argidx] == "-noscopeinfo") {
|
||||||
|
scopeinfo_mode = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
@ -685,7 +708,7 @@ struct JsonPass : public Pass {
|
||||||
f = &buf;
|
f = &buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonWriter json_writer(*f, true, aig_mode, compat_int_mode);
|
JsonWriter json_writer(*f, true, aig_mode, compat_int_mode, scopeinfo_mode);
|
||||||
json_writer.write_design(design);
|
json_writer.write_design(design);
|
||||||
|
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
|
|
|
@ -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)
|
void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
|
||||||
{
|
{
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
width = data.bits.size() - offset;
|
width = data.size() - offset;
|
||||||
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 && autoint) {
|
if (width == 32 && autoint) {
|
||||||
int32_t val = 0;
|
int32_t val = 0;
|
||||||
for (int i = 0; i < width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
log_assert(offset+i < (int)data.bits.size());
|
log_assert(offset+i < (int)data.size());
|
||||||
switch (data.bits[offset+i]) {
|
switch (data[offset+i]) {
|
||||||
case State::S0: break;
|
case State::S0: break;
|
||||||
case State::S1: val |= 1 << i; break;
|
case State::S1: val |= 1 << i; break;
|
||||||
default: val = -1; 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";
|
f << "x";
|
||||||
} else {
|
} else {
|
||||||
for (int i = offset+width-1; i >= offset; i--) {
|
for (int i = offset+width-1; i >= offset; i--) {
|
||||||
log_assert(i < (int)data.bits.size());
|
log_assert(i < (int)data.size());
|
||||||
switch (data.bits[i]) {
|
switch (data[i]) {
|
||||||
case State::S0: f << stringf("0"); break;
|
case State::S0: f << stringf("0"); break;
|
||||||
case State::S1: f << stringf("1"); break;
|
case State::S1: f << stringf("1"); break;
|
||||||
case RTLIL::Sx: f << stringf("x"); break;
|
case RTLIL::Sx: f << stringf("x"); break;
|
||||||
|
@ -125,6 +125,10 @@ void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::
|
||||||
dump_const(f, it.second);
|
dump_const(f, it.second);
|
||||||
f << stringf("\n");
|
f << stringf("\n");
|
||||||
}
|
}
|
||||||
|
if (wire->driverCell_) {
|
||||||
|
f << stringf("%s" "# driver %s %s\n", indent.c_str(),
|
||||||
|
wire->driverCell()->name.c_str(), wire->driverPort().c_str());
|
||||||
|
}
|
||||||
f << stringf("%s" "wire ", indent.c_str());
|
f << stringf("%s" "wire ", indent.c_str());
|
||||||
if (wire->width != 1)
|
if (wire->width != 1)
|
||||||
f << stringf("width %d ", wire->width);
|
f << stringf("width %d ", wire->width);
|
||||||
|
@ -300,8 +304,8 @@ void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::
|
||||||
|
|
||||||
void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
|
void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
|
||||||
{
|
{
|
||||||
bool print_header = flag_m || design->selected_whole_module(module->name);
|
bool print_header = flag_m || module->is_selected_whole();
|
||||||
bool print_body = !flag_n || !design->selected_whole_module(module->name);
|
bool print_body = !flag_n || !module->is_selected_whole();
|
||||||
|
|
||||||
if (print_header)
|
if (print_header)
|
||||||
{
|
{
|
||||||
|
@ -455,26 +459,12 @@ struct RTLILBackend : public Backend {
|
||||||
design->sort();
|
design->sort();
|
||||||
|
|
||||||
log("Output filename: %s\n", filename.c_str());
|
log("Output filename: %s\n", filename.c_str());
|
||||||
*f << stringf("# Generated by %s\n", yosys_version_str);
|
|
||||||
|
*f << stringf("# Generated by %s\n", yosys_maybe_version());
|
||||||
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
|
RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
|
||||||
}
|
}
|
||||||
} RTLILBackend;
|
} 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 {
|
struct DumpPass : public Pass {
|
||||||
DumpPass() : Pass("dump", "print parts of the design in RTLIL format") { }
|
DumpPass() : Pass("dump", "print parts of the design in RTLIL format") { }
|
||||||
void help() override
|
void help() override
|
||||||
|
|
|
@ -657,7 +657,7 @@ struct SimplecWorker
|
||||||
{
|
{
|
||||||
SigSpec sig = sigmaps.at(module)(w);
|
SigSpec sig = sigmaps.at(module)(w);
|
||||||
Const val = w->attributes.at(ID::init);
|
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++)
|
for (int i = 0; i < GetSize(sig); i++)
|
||||||
if (val[i] == State::S0 || val[i] == State::S1) {
|
if (val[i] == State::S0 || val[i] == State::S1) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
#include "libs/json11/json11.hpp"
|
#include "libs/json11/json11.hpp"
|
||||||
|
#include "kernel/utils.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
@ -329,13 +330,14 @@ struct Smt2Worker
|
||||||
{
|
{
|
||||||
sigmap.apply(bit);
|
sigmap.apply(bit);
|
||||||
|
|
||||||
|
if (bit_driver.count(bit)) {
|
||||||
|
export_cell(bit_driver.at(bit));
|
||||||
|
sigmap.apply(bit);
|
||||||
|
}
|
||||||
|
|
||||||
if (bit.wire == nullptr)
|
if (bit.wire == nullptr)
|
||||||
return bit == RTLIL::State::S1 ? "true" : "false";
|
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 (fcache.count(bit) == 0) {
|
||||||
if (verbose) log("%*s-> external bool: %s\n", 2+2*GetSize(recursive_cells), "",
|
if (verbose) log("%*s-> external bool: %s\n", 2+2*GetSize(recursive_cells), "",
|
||||||
log_signal(bit));
|
log_signal(bit));
|
||||||
|
@ -1077,14 +1079,14 @@ struct Smt2Worker
|
||||||
|
|
||||||
RTLIL::SigSpec sig = sigmap(wire);
|
RTLIL::SigSpec sig = sigmap(wire);
|
||||||
Const val = wire->attributes.at(ID::init);
|
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) {
|
if (bvmode && GetSize(sig) > 1) {
|
||||||
Const mask(State::S1, GetSize(sig));
|
Const mask(State::S1, GetSize(sig));
|
||||||
bool use_mask = false;
|
bool use_mask = false;
|
||||||
for (int i = 0; i < GetSize(sig); i++)
|
for (int i = 0; i < GetSize(sig); i++)
|
||||||
if (val[i] != State::S0 && val[i] != State::S1) {
|
if (val[i] != State::S0 && val[i] != State::S1) {
|
||||||
val[i] = State::S0;
|
val.bits()[i] = State::S0;
|
||||||
mask[i] = State::S0;
|
mask.bits()[i] = State::S0;
|
||||||
use_mask = true;
|
use_mask = true;
|
||||||
}
|
}
|
||||||
if (use_mask)
|
if (use_mask)
|
||||||
|
@ -1359,10 +1361,10 @@ struct Smt2Worker
|
||||||
for (int k = 0; k < GetSize(initword); k++) {
|
for (int k = 0; k < GetSize(initword); k++) {
|
||||||
if (initword[k] == State::S0 || initword[k] == State::S1) {
|
if (initword[k] == State::S0 || initword[k] == State::S1) {
|
||||||
gen_init_constr = true;
|
gen_init_constr = true;
|
||||||
initmask[k] = State::S1;
|
initmask.bits()[k] = State::S1;
|
||||||
} else {
|
} else {
|
||||||
initmask[k] = State::S0;
|
initmask.bits()[k] = State::S0;
|
||||||
initword[k] = State::S0;
|
initword.bits()[k] = State::S0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1829,7 +1831,7 @@ struct Smt2Backend : public Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*f << stringf("; SMT-LIBv2 description generated by %s\n", yosys_version_str);
|
*f << stringf("; SMT-LIBv2 description generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
if (!bvmode)
|
if (!bvmode)
|
||||||
*f << stringf("; yosys-smt2-nobv\n");
|
*f << stringf("; yosys-smt2-nobv\n");
|
||||||
|
|
|
@ -1454,6 +1454,10 @@ def write_trace(steps_start, steps_stop, index, allregs=False):
|
||||||
if outywfile is not None:
|
if outywfile is not None:
|
||||||
write_yw_trace(steps, index, allregs)
|
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=()):
|
def print_failed_asserts_worker(mod, state, path, extrainfo, infomap, infokey=()):
|
||||||
assert mod in smt.modinfo
|
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():
|
for cellname, celltype in smt.modinfo[mod].cells.items():
|
||||||
cell_infokey = (mod, cellname, infokey)
|
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
|
found_failed_assert = True
|
||||||
|
|
||||||
for assertfun, assertinfo in smt.modinfo[mod].asserts.items():
|
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
|
assert mod in smt.modinfo
|
||||||
|
|
||||||
for cellname, celltype in smt.modinfo[mod].cells.items():
|
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():
|
for fun, info in smt.modinfo[mod].anyconsts.items():
|
||||||
if info[1] is None:
|
if info[1] is None:
|
||||||
|
@ -1517,18 +1522,21 @@ def print_anyconsts(state):
|
||||||
print_anyconsts_worker(topmod, "s%d" % state, topmod)
|
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
|
assert mod in smt.modinfo
|
||||||
|
|
||||||
cover_expr = list()
|
cover_expr = list()
|
||||||
|
# A tuple of path and cell name
|
||||||
cover_desc = list()
|
cover_desc = list()
|
||||||
|
|
||||||
for expr, desc in smt.modinfo[mod].covers.items():
|
for expr, desc in smt.modinfo[mod].covers.items():
|
||||||
cover_expr.append("(ite (|%s| %s) #b1 #b0)" % (expr, base))
|
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():
|
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_expr += e
|
||||||
cover_desc += d
|
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)
|
assert_map[(expr, key_base)] = ("(|%s| %s)" % (expr, base), path, desc)
|
||||||
|
|
||||||
for cell, submod in smt.modinfo[mod].cells.items():
|
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
|
return assert_map
|
||||||
|
|
||||||
|
@ -1903,7 +1912,9 @@ elif covermode:
|
||||||
new_cover_mask.append(cover_mask[i])
|
new_cover_mask.append(cover_mask[i])
|
||||||
continue
|
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")
|
new_cover_mask.append("0")
|
||||||
|
|
||||||
cover_mask = "".join(new_cover_mask)
|
cover_mask = "".join(new_cover_mask)
|
||||||
|
@ -1933,7 +1944,7 @@ elif covermode:
|
||||||
if "1" in cover_mask:
|
if "1" in cover_mask:
|
||||||
for i in range(len(cover_mask)):
|
for i in range(len(cover_mask)):
|
||||||
if cover_mask[i] == "1":
|
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
|
else: # not tempind, covermode
|
||||||
active_assert_keys = get_assert_keys()
|
active_assert_keys = get_assert_keys()
|
||||||
|
|
|
@ -1217,7 +1217,7 @@ class SmtOpts:
|
||||||
def helpmsg(self):
|
def helpmsg(self):
|
||||||
return """
|
return """
|
||||||
-s <solver>
|
-s <solver>
|
||||||
set SMT solver: z3, yices, boolector, bitwuzla, cvc4, mathsat, dummy
|
set SMT solver: z3, yices, boolector, bitwuzla, cvc4, cvc5, mathsat, dummy
|
||||||
default: yices
|
default: yices
|
||||||
|
|
||||||
-S <opt>
|
-S <opt>
|
||||||
|
|
|
@ -21,7 +21,7 @@ EOT
|
||||||
for x in $(set +x; ls test_*.il | sort -R); do
|
for x in $(set +x; ls test_*.il | sort -R); do
|
||||||
x=${x%.il}
|
x=${x%.il}
|
||||||
cat > $x.ys <<- EOT
|
cat > $x.ys <<- EOT
|
||||||
read_ilang $x.il
|
read_rtlil $x.il
|
||||||
copy gold gate
|
copy gold gate
|
||||||
|
|
||||||
cd gate
|
cd gate
|
||||||
|
|
|
@ -797,7 +797,7 @@ struct SmvBackend : public Backend {
|
||||||
if (module == nullptr)
|
if (module == nullptr)
|
||||||
log_error("Module '%s' not found.\n", stmt[1].c_str());
|
log_error("Module '%s' not found.\n", stmt[1].c_str());
|
||||||
|
|
||||||
*f << stringf("-- SMV description generated by %s\n", yosys_version_str);
|
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
log("Creating SMV representation of module %s.\n", log_id(module));
|
log("Creating SMV representation of module %s.\n", log_id(module));
|
||||||
SmvWorker worker(module, verbose, *f);
|
SmvWorker worker(module, verbose, *f);
|
||||||
|
@ -816,7 +816,7 @@ struct SmvBackend : public Backend {
|
||||||
|
|
||||||
if (!modules.empty())
|
if (!modules.empty())
|
||||||
{
|
{
|
||||||
*f << stringf("-- SMV description generated by %s\n", yosys_version_str);
|
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
||||||
|
|
||||||
for (auto module : modules) {
|
for (auto module : modules) {
|
||||||
log("Creating SMV representation of module %s.\n", log_id(module));
|
log("Creating SMV representation of module %s.\n", log_id(module));
|
||||||
|
|
|
@ -17,11 +17,11 @@ EOT
|
||||||
|
|
||||||
for fn in test_*.il; do
|
for fn in test_*.il; do
|
||||||
../../../yosys -p "
|
../../../yosys -p "
|
||||||
read_ilang $fn
|
read_rtlil $fn
|
||||||
rename gold gate
|
rename gold gate
|
||||||
synth
|
synth
|
||||||
|
|
||||||
read_ilang $fn
|
read_rtlil $fn
|
||||||
miter -equiv -flatten gold gate main
|
miter -equiv -flatten gold gate main
|
||||||
hierarchy -top main
|
hierarchy -top main
|
||||||
write_smv -tpl template.txt ${fn#.il}.smv
|
write_smv -tpl template.txt ${fn#.il}.smv
|
||||||
|
|
|
@ -215,7 +215,7 @@ struct SpiceBackend : public Backend {
|
||||||
if (module->get_bool_attribute(ID::top))
|
if (module->get_bool_attribute(ID::top))
|
||||||
top_module_name = module->name.str();
|
top_module_name = module->name.str();
|
||||||
|
|
||||||
*f << stringf("* SPICE netlist generated by %s\n", yosys_version_str);
|
*f << stringf("* SPICE netlist generated by %s\n", yosys_maybe_version());
|
||||||
*f << stringf("\n");
|
*f << stringf("\n");
|
||||||
|
|
||||||
for (auto module : design->modules())
|
for (auto module : design->modules())
|
||||||
|
|
|
@ -28,12 +28,71 @@
|
||||||
#include "kernel/ff.h"
|
#include "kernel/ff.h"
|
||||||
#include "kernel/mem.h"
|
#include "kernel/mem.h"
|
||||||
#include "kernel/fmt.h"
|
#include "kernel/fmt.h"
|
||||||
|
#include "backends/verilog/verilog_backend.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
|
||||||
|
using namespace VERILOG_BACKEND;
|
||||||
|
|
||||||
|
const pool<string> VERILOG_BACKEND::verilog_keywords() {
|
||||||
|
static const pool<string> res = {
|
||||||
|
// IEEE 1800-2017 Annex B
|
||||||
|
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
||||||
|
"begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle",
|
||||||
|
"checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint",
|
||||||
|
"cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker",
|
||||||
|
"endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
|
||||||
|
"endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually",
|
||||||
|
"expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function",
|
||||||
|
"generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
|
||||||
|
"import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface",
|
||||||
|
"intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint",
|
||||||
|
"macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor",
|
||||||
|
"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive",
|
||||||
|
"priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
|
||||||
|
"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat",
|
||||||
|
"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
|
||||||
|
"s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify",
|
||||||
|
"specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on",
|
||||||
|
"sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
|
||||||
|
"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with",
|
||||||
|
"untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
|
||||||
|
"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
|
||||||
|
};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VERILOG_BACKEND::char_is_verilog_escaped(char c) {
|
||||||
|
if ('0' <= c && c <= '9')
|
||||||
|
return false;
|
||||||
|
if ('a' <= c && c <= 'z')
|
||||||
|
return false;
|
||||||
|
if ('A' <= c && c <= 'Z')
|
||||||
|
return false;
|
||||||
|
if (c == '_')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VERILOG_BACKEND::id_is_verilog_escaped(const std::string &str) {
|
||||||
|
if ('0' <= str[0] && str[0] <= '9')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = 0; str[i]; i++)
|
||||||
|
if (char_is_verilog_escaped(str[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (verilog_keywords().count(str))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
|
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog, simple_lhs, noparallelcase;
|
||||||
|
@ -105,7 +164,6 @@ std::string next_auto_id()
|
||||||
std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
||||||
{
|
{
|
||||||
const char *str = internal_id.c_str();
|
const char *str = internal_id.c_str();
|
||||||
bool do_escape = false;
|
|
||||||
|
|
||||||
if (may_rename && auto_name_map.count(internal_id) != 0)
|
if (may_rename && auto_name_map.count(internal_id) != 0)
|
||||||
return stringf("%s_%0*d_", auto_prefix.c_str(), auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
|
return stringf("%s_%0*d_", auto_prefix.c_str(), auto_name_digits, auto_name_offset + auto_name_map[internal_id]);
|
||||||
|
@ -113,51 +171,7 @@ std::string id(RTLIL::IdString internal_id, bool may_rename = true)
|
||||||
if (*str == '\\')
|
if (*str == '\\')
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
if ('0' <= *str && *str <= '9')
|
if (id_is_verilog_escaped(str))
|
||||||
do_escape = true;
|
|
||||||
|
|
||||||
for (int i = 0; str[i]; i++)
|
|
||||||
{
|
|
||||||
if ('0' <= str[i] && str[i] <= '9')
|
|
||||||
continue;
|
|
||||||
if ('a' <= str[i] && str[i] <= 'z')
|
|
||||||
continue;
|
|
||||||
if ('A' <= str[i] && str[i] <= 'Z')
|
|
||||||
continue;
|
|
||||||
if (str[i] == '_')
|
|
||||||
continue;
|
|
||||||
do_escape = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const pool<string> keywords = {
|
|
||||||
// IEEE 1800-2017 Annex B
|
|
||||||
"accept_on", "alias", "always", "always_comb", "always_ff", "always_latch", "and", "assert", "assign", "assume", "automatic", "before",
|
|
||||||
"begin", "bind", "bins", "binsof", "bit", "break", "buf", "bufif0", "bufif1", "byte", "case", "casex", "casez", "cell", "chandle",
|
|
||||||
"checker", "class", "clocking", "cmos", "config", "const", "constraint", "context", "continue", "cover", "covergroup", "coverpoint",
|
|
||||||
"cross", "deassign", "default", "defparam", "design", "disable", "dist", "do", "edge", "else", "end", "endcase", "endchecker",
|
|
||||||
"endclass", "endclocking", "endconfig", "endfunction", "endgenerate", "endgroup", "endinterface", "endmodule", "endpackage",
|
|
||||||
"endprimitive", "endprogram", "endproperty", "endsequence", "endspecify", "endtable", "endtask", "enum", "event", "eventually",
|
|
||||||
"expect", "export", "extends", "extern", "final", "first_match", "for", "force", "foreach", "forever", "fork", "forkjoin", "function",
|
|
||||||
"generate", "genvar", "global", "highz0", "highz1", "if", "iff", "ifnone", "ignore_bins", "illegal_bins", "implements", "implies",
|
|
||||||
"import", "incdir", "include", "initial", "inout", "input", "inside", "instance", "int", "integer", "interconnect", "interface",
|
|
||||||
"intersect", "join", "join_any", "join_none", "large", "let", "liblist", "library", "local", "localparam", "logic", "longint",
|
|
||||||
"macromodule", "matches", "medium", "modport", "module", "nand", "negedge", "nettype", "new", "nexttime", "nmos", "nor",
|
|
||||||
"noshowcancelled", "not", "notif0", "notif1", "null", "or", "output", "package", "packed", "parameter", "pmos", "posedge", "primitive",
|
|
||||||
"priority", "program", "property", "protected", "pull0", "pull1", "pulldown", "pullup", "pulsestyle_ondetect", "pulsestyle_onevent",
|
|
||||||
"pure", "rand", "randc", "randcase", "randsequence", "rcmos", "real", "realtime", "ref", "reg", "reject_on", "release", "repeat",
|
|
||||||
"restrict", "return", "rnmos", "rpmos", "rtran", "rtranif0", "rtranif1", "s_always", "s_eventually", "s_nexttime", "s_until",
|
|
||||||
"s_until_with", "scalared", "sequence", "shortint", "shortreal", "showcancelled", "signed", "small", "soft", "solve", "specify",
|
|
||||||
"specparam", "static", "string", "strong", "strong0", "strong1", "struct", "super", "supply0", "supply1", "sync_accept_on",
|
|
||||||
"sync_reject_on", "table", "tagged", "task", "this", "throughout", "time", "timeprecision", "timeunit", "tran", "tranif0", "tranif1",
|
|
||||||
"tri", "tri0", "tri1", "triand", "trior", "trireg", "type", "typedef", "union", "unique", "unique0", "unsigned", "until", "until_with",
|
|
||||||
"untyped", "use", "uwire", "var", "vectored", "virtual", "void", "wait", "wait_order", "wand", "weak", "weak0", "weak1", "while",
|
|
||||||
"wildcard", "wire", "with", "within", "wor", "xnor", "xor",
|
|
||||||
};
|
|
||||||
if (keywords.count(str))
|
|
||||||
do_escape = true;
|
|
||||||
|
|
||||||
if (do_escape)
|
|
||||||
return "\\" + std::string(str) + " ";
|
return "\\" + std::string(str) + " ";
|
||||||
return std::string(str);
|
return std::string(str);
|
||||||
}
|
}
|
||||||
|
@ -191,7 +205,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;
|
bool set_signed = (data.flags & RTLIL::CONST_FLAG_SIGNED) != 0;
|
||||||
if (width < 0)
|
if (width < 0)
|
||||||
width = data.bits.size() - offset;
|
width = data.size() - offset;
|
||||||
if (width == 0) {
|
if (width == 0) {
|
||||||
// See IEEE 1364-2005 Clause 5.1.14.
|
// See IEEE 1364-2005 Clause 5.1.14.
|
||||||
f << "{0{1'b0}}";
|
f << "{0{1'b0}}";
|
||||||
|
@ -199,14 +213,14 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
||||||
}
|
}
|
||||||
if (nostr)
|
if (nostr)
|
||||||
goto dump_hex;
|
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) {
|
if (width == 32 && !no_decimal && !nodec) {
|
||||||
int32_t val = 0;
|
int32_t val = 0;
|
||||||
for (int i = offset+width-1; i >= offset; i--) {
|
for (int i = offset+width-1; i >= offset; i--) {
|
||||||
log_assert(i < (int)data.bits.size());
|
log_assert(i < (int)data.size());
|
||||||
if (data.bits[i] != State::S0 && data.bits[i] != State::S1)
|
if (data[i] != State::S0 && data[i] != State::S1)
|
||||||
goto dump_hex;
|
goto dump_hex;
|
||||||
if (data.bits[i] == State::S1)
|
if (data[i] == State::S1)
|
||||||
val |= 1 << (i - offset);
|
val |= 1 << (i - offset);
|
||||||
}
|
}
|
||||||
if (decimal)
|
if (decimal)
|
||||||
|
@ -221,8 +235,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
||||||
goto dump_bin;
|
goto dump_bin;
|
||||||
vector<char> bin_digits, hex_digits;
|
vector<char> bin_digits, hex_digits;
|
||||||
for (int i = offset; i < offset+width; i++) {
|
for (int i = offset; i < offset+width; i++) {
|
||||||
log_assert(i < (int)data.bits.size());
|
log_assert(i < (int)data.size());
|
||||||
switch (data.bits[i]) {
|
switch (data[i]) {
|
||||||
case State::S0: bin_digits.push_back('0'); break;
|
case State::S0: bin_digits.push_back('0'); break;
|
||||||
case State::S1: bin_digits.push_back('1'); break;
|
case State::S1: bin_digits.push_back('1'); break;
|
||||||
case RTLIL::Sx: bin_digits.push_back('x'); break;
|
case RTLIL::Sx: bin_digits.push_back('x'); break;
|
||||||
|
@ -275,8 +289,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
|
||||||
if (width == 0)
|
if (width == 0)
|
||||||
f << stringf("0");
|
f << stringf("0");
|
||||||
for (int i = offset+width-1; i >= offset; i--) {
|
for (int i = offset+width-1; i >= offset; i--) {
|
||||||
log_assert(i < (int)data.bits.size());
|
log_assert(i < (int)data.size());
|
||||||
switch (data.bits[i]) {
|
switch (data[i]) {
|
||||||
case State::S0: f << stringf("0"); break;
|
case State::S0: f << stringf("0"); break;
|
||||||
case State::S1: f << stringf("1"); break;
|
case State::S1: f << stringf("1"); break;
|
||||||
case RTLIL::Sx: f << stringf("x"); break;
|
case RTLIL::Sx: f << stringf("x"); break;
|
||||||
|
@ -318,10 +332,10 @@ void dump_reg_init(std::ostream &f, SigSpec sig)
|
||||||
|
|
||||||
for (auto bit : active_sigmap(sig)) {
|
for (auto bit : active_sigmap(sig)) {
|
||||||
if (active_initdata.count(bit)) {
|
if (active_initdata.count(bit)) {
|
||||||
initval.bits.push_back(active_initdata.at(bit));
|
initval.bits().push_back(active_initdata.at(bit));
|
||||||
gotinit = true;
|
gotinit = true;
|
||||||
} else {
|
} else {
|
||||||
initval.bits.push_back(State::Sx);
|
initval.bits().push_back(State::Sx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +397,7 @@ void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString,
|
||||||
if (attr2comment)
|
if (attr2comment)
|
||||||
as_comment = true;
|
as_comment = true;
|
||||||
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
||||||
|
if (it->first == ID::single_bit_vector) continue;
|
||||||
if (it->first == ID::init && regattr) continue;
|
if (it->first == ID::init && regattr) continue;
|
||||||
f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str());
|
f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str());
|
||||||
f << stringf(" = ");
|
f << stringf(" = ");
|
||||||
|
@ -419,6 +434,9 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
|
||||||
range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset);
|
range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset);
|
||||||
else
|
else
|
||||||
range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
|
range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset);
|
||||||
|
} else {
|
||||||
|
if (wire->attributes.count(ID::single_bit_vector))
|
||||||
|
range = stringf(" [%d:%d]", wire->start_offset, wire->start_offset);
|
||||||
}
|
}
|
||||||
if (wire->port_input && !wire->port_output)
|
if (wire->port_input && !wire->port_output)
|
||||||
f << stringf("%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
|
f << stringf("%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
|
||||||
|
@ -751,7 +769,7 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
|
||||||
if (port.wide_log2) {
|
if (port.wide_log2) {
|
||||||
Const addr_lo;
|
Const addr_lo;
|
||||||
for (int i = 0; i < port.wide_log2; i++)
|
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 << "{";
|
||||||
os << temp_id;
|
os << temp_id;
|
||||||
os << ", ";
|
os << ", ";
|
||||||
|
@ -1044,16 +1062,23 @@ void dump_cell_expr_print(std::ostream &f, std::string indent, const RTLIL::Cell
|
||||||
void dump_cell_expr_check(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
|
void dump_cell_expr_check(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
|
||||||
{
|
{
|
||||||
std::string flavor = cell->getParam(ID(FLAVOR)).decode_string();
|
std::string flavor = cell->getParam(ID(FLAVOR)).decode_string();
|
||||||
|
std::string label = "";
|
||||||
|
if (cell->name.isPublic()) {
|
||||||
|
label = stringf("%s: ", id(cell->name).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (flavor == "assert")
|
if (flavor == "assert")
|
||||||
f << stringf("%s" "assert (", indent.c_str());
|
f << stringf("%s" "%s" "assert (", indent.c_str(), label.c_str());
|
||||||
else if (flavor == "assume")
|
else if (flavor == "assume")
|
||||||
f << stringf("%s" "assume (", indent.c_str());
|
f << stringf("%s" "%s" "assume (", indent.c_str(), label.c_str());
|
||||||
else if (flavor == "live")
|
else if (flavor == "live")
|
||||||
f << stringf("%s" "assert (eventually ", indent.c_str());
|
f << stringf("%s" "%s" "assert (eventually ", indent.c_str(), label.c_str());
|
||||||
else if (flavor == "fair")
|
else if (flavor == "fair")
|
||||||
f << stringf("%s" "assume (eventually ", indent.c_str());
|
f << stringf("%s" "%s" "assume (eventually ", indent.c_str(), label.c_str());
|
||||||
else if (flavor == "cover")
|
else if (flavor == "cover")
|
||||||
f << stringf("%s" "cover (", indent.c_str());
|
f << stringf("%s" "%s" "cover (", indent.c_str(), label.c_str());
|
||||||
|
else
|
||||||
|
log_abort();
|
||||||
dump_sigspec(f, cell->getPort(ID::A));
|
dump_sigspec(f, cell->getPort(ID::A));
|
||||||
f << stringf(");\n");
|
f << stringf(");\n");
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1096,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == ID($_BUF_)) {
|
if (cell->type.in(ID($_BUF_), ID($buf))) {
|
||||||
f << stringf("%s" "assign ", indent.c_str());
|
f << stringf("%s" "assign ", indent.c_str());
|
||||||
dump_sigspec(f, cell->getPort(ID::Y));
|
dump_sigspec(f, cell->getPort(ID::Y));
|
||||||
f << stringf(" = ");
|
f << stringf(" = ");
|
||||||
|
@ -1138,9 +1163,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||||
dump_sigspec(f, cell->getPort(ID::Y));
|
dump_sigspec(f, cell->getPort(ID::Y));
|
||||||
f << stringf(" = ~((");
|
f << stringf(" = ~((");
|
||||||
dump_cell_expr_port(f, cell, "A", false);
|
dump_cell_expr_port(f, cell, "A", false);
|
||||||
f << stringf(cell->type == ID($_AOI3_) ? " & " : " | ");
|
f << (cell->type == ID($_AOI3_) ? " & " : " | ");
|
||||||
dump_cell_expr_port(f, cell, "B", false);
|
dump_cell_expr_port(f, cell, "B", false);
|
||||||
f << stringf(cell->type == ID($_AOI3_) ? ") |" : ") &");
|
f << (cell->type == ID($_AOI3_) ? ") |" : ") &");
|
||||||
dump_attributes(f, "", cell->attributes, " ");
|
dump_attributes(f, "", cell->attributes, " ");
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
dump_cell_expr_port(f, cell, "C", false);
|
dump_cell_expr_port(f, cell, "C", false);
|
||||||
|
@ -1153,13 +1178,13 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||||
dump_sigspec(f, cell->getPort(ID::Y));
|
dump_sigspec(f, cell->getPort(ID::Y));
|
||||||
f << stringf(" = ~((");
|
f << stringf(" = ~((");
|
||||||
dump_cell_expr_port(f, cell, "A", false);
|
dump_cell_expr_port(f, cell, "A", false);
|
||||||
f << stringf(cell->type == ID($_AOI4_) ? " & " : " | ");
|
f << (cell->type == ID($_AOI4_) ? " & " : " | ");
|
||||||
dump_cell_expr_port(f, cell, "B", false);
|
dump_cell_expr_port(f, cell, "B", false);
|
||||||
f << stringf(cell->type == ID($_AOI4_) ? ") |" : ") &");
|
f << (cell->type == ID($_AOI4_) ? ") |" : ") &");
|
||||||
dump_attributes(f, "", cell->attributes, " ");
|
dump_attributes(f, "", cell->attributes, " ");
|
||||||
f << stringf(" (");
|
f << stringf(" (");
|
||||||
dump_cell_expr_port(f, cell, "C", false);
|
dump_cell_expr_port(f, cell, "C", false);
|
||||||
f << stringf(cell->type == ID($_AOI4_) ? " & " : " | ");
|
f << (cell->type == ID($_AOI4_) ? " & " : " | ");
|
||||||
dump_cell_expr_port(f, cell, "D", false);
|
dump_cell_expr_port(f, cell, "D", false);
|
||||||
f << stringf("));\n");
|
f << stringf("));\n");
|
||||||
return true;
|
return true;
|
||||||
|
@ -1370,10 +1395,10 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||||
int s_width = cell->getPort(ID::S).size();
|
int s_width = cell->getPort(ID::S).size();
|
||||||
std::string func_name = cellname(cell);
|
std::string func_name = cellname(cell);
|
||||||
|
|
||||||
f << stringf("%s" "function [%d:0] %s;\n", indent.c_str(), width-1, func_name.c_str());
|
f << stringf("%s" "function [%d:0] %s;\n", indent, width-1, func_name);
|
||||||
f << stringf("%s" " input [%d:0] a;\n", indent.c_str(), width-1);
|
f << stringf("%s" " input [%d:0] a;\n", indent, width-1);
|
||||||
f << stringf("%s" " input [%d:0] b;\n", indent.c_str(), s_width*width-1);
|
f << stringf("%s" " input [%d:0] b;\n", indent, s_width*width-1);
|
||||||
f << stringf("%s" " input [%d:0] s;\n", indent.c_str(), s_width-1);
|
f << stringf("%s" " input [%d:0] s;\n", indent, s_width-1);
|
||||||
|
|
||||||
dump_attributes(f, indent + " ", cell->attributes);
|
dump_attributes(f, indent + " ", cell->attributes);
|
||||||
if (noparallelcase)
|
if (noparallelcase)
|
||||||
|
@ -1382,7 +1407,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
|
||||||
if (!noattr)
|
if (!noattr)
|
||||||
f << stringf("%s" " (* parallel_case *)\n", indent.c_str());
|
f << stringf("%s" " (* parallel_case *)\n", indent.c_str());
|
||||||
f << stringf("%s" " casez (s)", indent.c_str());
|
f << stringf("%s" " casez (s)", indent.c_str());
|
||||||
f << stringf(noattr ? " // synopsys parallel_case\n" : "\n");
|
f << (noattr ? " // synopsys parallel_case\n" : "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < s_width; i++)
|
for (int i = 0; i < s_width; i++)
|
||||||
|
@ -2332,19 +2357,15 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
||||||
|
|
||||||
dump_attributes(f, indent, module->attributes, "\n", /*modattr=*/true);
|
dump_attributes(f, indent, module->attributes, "\n", /*modattr=*/true);
|
||||||
f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
|
f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
|
||||||
bool keep_running = true;
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
for (int port_id = 1; keep_running; port_id++) {
|
for (auto port : module->ports) {
|
||||||
keep_running = false;
|
Wire *wire = module->wire(port);
|
||||||
for (auto wire : module->wires()) {
|
if (wire) {
|
||||||
if (wire->port_id == port_id) {
|
if (port != module->ports[0])
|
||||||
if (port_id != 1)
|
f << stringf(", ");
|
||||||
f << stringf(", ");
|
f << stringf("%s", id(wire->name).c_str());
|
||||||
f << stringf("%s", id(wire->name).c_str());
|
if (cnt==20) { f << stringf("\n"); cnt = 0; } else cnt++;
|
||||||
keep_running = true;
|
continue;
|
||||||
if (cnt==20) { f << stringf("\n"); cnt = 0; } else cnt++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f << stringf(");\n");
|
f << stringf(");\n");
|
||||||
|
@ -2591,9 +2612,10 @@ struct VerilogBackend : public Backend {
|
||||||
Pass::call(design, "clean_zerowidth");
|
Pass::call(design, "clean_zerowidth");
|
||||||
log_pop();
|
log_pop();
|
||||||
|
|
||||||
design->sort();
|
design->sort_modules();
|
||||||
|
|
||||||
|
*f << stringf("/* Generated by %s */\n", yosys_maybe_version());
|
||||||
|
|
||||||
*f << stringf("/* Generated by %s */\n", yosys_version_str);
|
|
||||||
for (auto module : design->modules()) {
|
for (auto module : design->modules()) {
|
||||||
if (module->get_blackbox_attribute() != blackboxes)
|
if (module->get_blackbox_attribute() != blackboxes)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2603,6 +2625,7 @@ struct VerilogBackend : public Backend {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log("Dumping module `%s'.\n", module->name.c_str());
|
log("Dumping module `%s'.\n", module->name.c_str());
|
||||||
|
module->sort();
|
||||||
dump_module(*f, "", module);
|
dump_module(*f, "", module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
backends/verilog/verilog_backend.h
Normal file
39
backends/verilog/verilog_backend.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* yosys -- Yosys Open SYnthesis Suite
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* A simple and straightforward Verilog backend.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VERILOG_BACKEND_H
|
||||||
|
#define VERILOG_BACKEND_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
YOSYS_NAMESPACE_BEGIN
|
||||||
|
namespace VERILOG_BACKEND {
|
||||||
|
|
||||||
|
const pool<string> verilog_keywords();
|
||||||
|
bool char_is_verilog_escaped(char c);
|
||||||
|
bool id_is_verilog_escaped(const std::string &str);
|
||||||
|
|
||||||
|
}; /* namespace VERILOG_BACKEND */
|
||||||
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif /* VERILOG_BACKEND_H */
|
|
@ -238,7 +238,7 @@ Makefile-%: FORCE
|
||||||
$(MAKE) -C $(@D) $(*F)
|
$(MAKE) -C $(@D) $(*F)
|
||||||
|
|
||||||
CODE_EXAMPLES := $(wildcard source/code_examples/*/Makefile)
|
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))
|
CLEAN_EXAMPLES := $(addsuffix -clean,$(CODE_EXAMPLES))
|
||||||
test-examples: $(TEST_EXAMPLES)
|
test-examples: $(TEST_EXAMPLES)
|
||||||
clean-examples: $(CLEAN_EXAMPLES)
|
clean-examples: $(CLEAN_EXAMPLES)
|
||||||
|
@ -252,6 +252,11 @@ images:
|
||||||
$(MAKE) -C source/_images
|
$(MAKE) -C source/_images
|
||||||
$(MAKE) -C source/_images convert
|
$(MAKE) -C source/_images convert
|
||||||
|
|
||||||
|
.PHONY: gen
|
||||||
|
gen:
|
||||||
|
$(MAKE) examples
|
||||||
|
$(MAKE) images
|
||||||
|
|
||||||
.PHONY: reqs
|
.PHONY: reqs
|
||||||
reqs:
|
reqs:
|
||||||
$(PYTHON) -m pip install -r source/requirements.txt
|
$(PYTHON) -m pip install -r source/requirements.txt
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
all: examples all_tex tidy
|
all: examples all_tex
|
||||||
|
|
||||||
# set a fake time in pdf generation to prevent unnecessary differences in output
|
# 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'
|
FAKETIME := TZ='Z' faketime -f '2022-01-01 00:00:00 x0,001'
|
||||||
|
|
||||||
|
ifneq ($(shell :; command -v rsync),)
|
||||||
|
RSYNC_CP ?= rsync -t
|
||||||
|
else
|
||||||
|
RSYNC_CP ?= cp -a
|
||||||
|
endif
|
||||||
|
|
||||||
# find all code example makefiles
|
# find all code example makefiles
|
||||||
.PHONY: examples
|
.PHONY: examples
|
||||||
CODE_EXAMPLES := ../code_examples/*/Makefile
|
CODE_EXAMPLES := ../code_examples/*/Makefile
|
||||||
|
@ -19,7 +25,7 @@ FORCE:
|
||||||
../%/Makefile: FORCE
|
../%/Makefile: FORCE
|
||||||
@make -C $(@D) dots
|
@make -C $(@D) dots
|
||||||
@mkdir -p $*
|
@mkdir -p $*
|
||||||
@find $(@D) -name *.dot -exec rsync -t {} $* \;
|
@find $(@D) -name *.dot -exec $(RSYNC_CP) {} $* \;
|
||||||
|
|
||||||
# find and build all tex files
|
# find and build all tex files
|
||||||
.PHONY: all_tex
|
.PHONY: all_tex
|
||||||
|
|
|
@ -15,23 +15,23 @@
|
||||||
\tikzstyle{data} = [draw, fill=blue!10, ellipse, minimum height=3em, minimum width=7em, node distance=15em]
|
\tikzstyle{data} = [draw, fill=blue!10, ellipse, minimum height=3em, minimum width=7em, node distance=15em]
|
||||||
\node[process] (vlog) {Verilog Frontend};
|
\node[process] (vlog) {Verilog Frontend};
|
||||||
\node[process, dashed, fill=green!5] (vhdl) [right of=vlog] {VHDL 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[data] (ast) [below of=vlog, node distance=5em, xshift=7.5em] {AST};
|
||||||
\node[process] (astfe) [below of=ast, node distance=5em] {AST Frontend};
|
\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[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] (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] (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};
|
\node[process, dashed, fill=green!5] (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] {Other Backends};
|
||||||
|
|
||||||
\draw[-latex] (vlog) -- (ast);
|
\draw[-latex] (vlog) -- (ast);
|
||||||
\draw[-latex] (vhdl) -- (ast);
|
\draw[-latex] (vhdl) -- (ast);
|
||||||
\draw[-latex] (ast) -- (astfe);
|
\draw[-latex] (ast) -- (astfe);
|
||||||
\draw[-latex] (astfe) -- (rtlil);
|
\draw[-latex] (astfe) -- (rtlil);
|
||||||
\draw[-latex] (ilang) -- (rtlil);
|
\draw[-latex] (rtlilfe) -- (rtlil);
|
||||||
\draw[latex-latex] (rtlil) -- (pass);
|
\draw[latex-latex] (rtlil) -- (pass);
|
||||||
\draw[-latex] (rtlil) -- (vlbe);
|
\draw[-latex] (rtlil) -- (vlbe);
|
||||||
\draw[-latex] (rtlil) -- (ilangbe);
|
\draw[-latex] (rtlil) -- (rtlilbe);
|
||||||
\draw[-latex] (rtlil) -- (otherbe);
|
\draw[-latex] (rtlil) -- (otherbe);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{document}
|
\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
|
The files in ``libs/ezsat`` provide a library for simplifying generating CNF
|
||||||
formulas for SAT solvers. It also contains bindings of MiniSAT. The ezSAT
|
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`).
|
:doc:`/cmd/sat`).
|
||||||
|
|
||||||
fst
|
fst
|
||||||
|
@ -37,22 +37,22 @@ fst
|
||||||
|
|
||||||
``libfst`` files from `gtkwave`_ are included in ``libs/fst`` to support
|
``libfst`` files from `gtkwave`_ are included in ``libs/fst`` to support
|
||||||
reading/writing signal traces from/to the GTKWave developed FST format. This is
|
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
|
.. _gtkwave: https://github.com/gtkwave/gtkwave
|
||||||
|
|
||||||
json11
|
json11
|
||||||
------
|
------
|
||||||
|
|
||||||
For reading/writing designs from/to JSON, :cmd:ref:`read_json` and
|
For reading/writing designs from/to JSON, `read_json` and
|
||||||
:cmd:ref:`write_json` should be used. For everything else there is the `json11
|
`write_json` should be used. For everything else there is the `json11
|
||||||
library`_:
|
library`_:
|
||||||
|
|
||||||
json11 is a tiny JSON library for C++11, providing JSON parsing and
|
json11 is a tiny JSON library for C++11, providing JSON parsing and
|
||||||
serialization.
|
serialization.
|
||||||
|
|
||||||
This library is used for outputting machine-readable statistics (:cmd:ref:`stat`
|
This library is used for outputting machine-readable statistics (`stat`
|
||||||
with ``-json`` flag), using the RPC frontend (:cmd:ref:`connect_rpc`), and the
|
with ``-json`` flag), using the RPC frontend (`connect_rpc`), and the
|
||||||
yosys-witness ``yw`` format.
|
yosys-witness ``yw`` format.
|
||||||
|
|
||||||
.. _json11 library: https://github.com/dropbox/json11
|
.. _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
|
The files in ``libs/minisat`` provide a high-performance SAT solver, used by the
|
||||||
:cmd:ref:`sat` command.
|
`sat` command.
|
||||||
|
|
||||||
SHA1
|
SHA1
|
||||||
----
|
----
|
||||||
|
|
|
@ -3,7 +3,7 @@ Yosys environment variables
|
||||||
|
|
||||||
``HOME``
|
``HOME``
|
||||||
Yosys command history is stored in :file:`$HOME/.yosys_history`. Graphics
|
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
|
directory by default. This environment variable is also used in some cases
|
||||||
for resolving filenames with :file:`~`.
|
for resolving filenames with :file:`~`.
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ circuits.
|
||||||
Tools exist to synthesize high level code (usually in the form of C/C++/SystemC
|
Tools exist to synthesize high level code (usually in the form of C/C++/SystemC
|
||||||
code with additional metadata) to behavioural HDL code (usually in the form of
|
code with additional metadata) to behavioural HDL code (usually in the form of
|
||||||
Verilog or VHDL code). Aside from the many commercial tools for high level
|
Verilog or VHDL code). Aside from the many commercial tools for high level
|
||||||
synthesis there are also a number of FOSS tools for high level synthesis .
|
synthesis there are also a number of FOSS tools for high level synthesis.
|
||||||
|
|
||||||
Behavioural level
|
Behavioural level
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
@ -185,7 +185,7 @@ advantage that it has a unique normalized form. The latter has much better worst
|
||||||
case performance and is therefore better suited for the synthesis of large logic
|
case performance and is therefore better suited for the synthesis of large logic
|
||||||
functions.
|
functions.
|
||||||
|
|
||||||
Good FOSS tools exists for multi-level logic synthesis .
|
Good FOSS tools exists for multi-level logic synthesis.
|
||||||
|
|
||||||
Yosys contains basic logic synthesis functionality but can also use ABC for the
|
Yosys contains basic logic synthesis functionality but can also use ABC for the
|
||||||
logic synthesis step. Using ABC is recommended.
|
logic synthesis step. Using ABC is recommended.
|
||||||
|
@ -221,7 +221,7 @@ design description as input and generates an RTL, logical gate or physical gate
|
||||||
level description of the design as output. Yosys' main strengths are behavioural
|
level description of the design as output. Yosys' main strengths are behavioural
|
||||||
and RTL synthesis. A wide range of commands (synthesis passes) exist within
|
and RTL synthesis. A wide range of commands (synthesis passes) exist within
|
||||||
Yosys that can be used to perform a wide range of synthesis tasks within the
|
Yosys that can be used to perform a wide range of synthesis tasks within the
|
||||||
domain of behavioural, rtl and logic synthesis. Yosys is designed to be
|
domain of behavioural, RTL and logic synthesis. Yosys is designed to be
|
||||||
extensible and therefore is a good basis for implementing custom synthesis tools
|
extensible and therefore is a good basis for implementing custom synthesis tools
|
||||||
for specialised tasks.
|
for specialised tasks.
|
||||||
|
|
||||||
|
@ -572,7 +572,7 @@ of lexical tokens given in :numref:`Tab. %s <tab:Basics_tokens>`.
|
||||||
TOK_SEMICOLON \-
|
TOK_SEMICOLON \-
|
||||||
============== ===============
|
============== ===============
|
||||||
|
|
||||||
The lexer is usually generated by a lexer generator (e.g. flex ) from a
|
The lexer is usually generated by a lexer generator (e.g. flex) from a
|
||||||
description file that is using regular expressions to specify the text pattern
|
description file that is using regular expressions to specify the text pattern
|
||||||
that should match the individual tokens.
|
that should match the individual tokens.
|
||||||
|
|
||||||
|
|
|
@ -223,8 +223,8 @@ Cells
|
||||||
Declares a cell, with zero or more attributes, with the given identifier and
|
Declares a cell, with zero or more attributes, with the given identifier and
|
||||||
type in the enclosing module.
|
type in the enclosing module.
|
||||||
|
|
||||||
Cells perform functions on input signals. See
|
Cells perform functions on input signals. See :doc:`/cell_index` for a detailed
|
||||||
:doc:`/yosys_internals/formats/cell_library` for a detailed list of cell types.
|
list of cell types.
|
||||||
|
|
||||||
.. code:: BNF
|
.. code:: BNF
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ Processes
|
||||||
|
|
||||||
Declares a process, with zero or more attributes, with the given identifier in
|
Declares a process, with zero or more attributes, with the given identifier in
|
||||||
the enclosing module. The body of a process consists of zero or more
|
the enclosing module. The body of a process consists of zero or more
|
||||||
assignments, exactly one switch, and zero or more syncs.
|
assignments followed by zero or more switches and zero or more syncs.
|
||||||
|
|
||||||
See :ref:`sec:rtlil_process` for an overview of processes.
|
See :ref:`sec:rtlil_process` for an overview of processes.
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ See :ref:`sec:rtlil_process` for an overview of processes.
|
||||||
|
|
||||||
<process> ::= <attr-stmt>* <proc-stmt> <process-body> <proc-end-stmt>
|
<process> ::= <attr-stmt>* <proc-stmt> <process-body> <proc-end-stmt>
|
||||||
<proc-stmt> ::= process <id> <eol>
|
<proc-stmt> ::= process <id> <eol>
|
||||||
<process-body> ::= <assign-stmt>* <switch>? <assign-stmt>* <sync>*
|
<process-body> ::= <assign-stmt>* <switch>* <sync>*
|
||||||
<assign-stmt> ::= assign <dest-sigspec> <src-sigspec> <eol>
|
<assign-stmt> ::= assign <dest-sigspec> <src-sigspec> <eol>
|
||||||
<dest-sigspec> ::= <sigspec>
|
<dest-sigspec> ::= <sigspec>
|
||||||
<src-sigspec> ::= <sigspec>
|
<src-sigspec> ::= <sigspec>
|
||||||
|
@ -262,8 +262,8 @@ Switches
|
||||||
Switches test a signal for equality against a list of cases. Each case specifies
|
Switches test a signal for equality against a list of cases. Each case specifies
|
||||||
a comma-separated list of signals to check against. If there are no signals in
|
a comma-separated list of signals to check against. If there are no signals in
|
||||||
the list, then the case is the default case. The body of a case consists of zero
|
the list, then the case is the default case. The body of a case consists of zero
|
||||||
or more switches and assignments. Both switches and cases may have zero or more
|
or more assignments followed by zero or more switches. Both switches and cases
|
||||||
attributes.
|
may have zero or more attributes.
|
||||||
|
|
||||||
.. code:: BNF
|
.. code:: BNF
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ attributes.
|
||||||
<case> ::= <attr-stmt>* <case-stmt> <case-body>
|
<case> ::= <attr-stmt>* <case-stmt> <case-body>
|
||||||
<case-stmt> ::= case <compare>? <eol>
|
<case-stmt> ::= case <compare>? <eol>
|
||||||
<compare> ::= <sigspec> (, <sigspec>)*
|
<compare> ::= <sigspec> (, <sigspec>)*
|
||||||
<case-body> ::= (<switch> | <assign-stmt>)*
|
<case-body> ::= <assign-stmt>* <switch>*
|
||||||
<switch-end-stmt> ::= end <eol>
|
<switch-end-stmt> ::= end <eol>
|
||||||
|
|
||||||
Syncs
|
Syncs
|
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`, `$macc_v2`, 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, the ``unique`` or ``unique0``
|
||||||
|
SystemVerilog keywords, 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
|
*.dot
|
||||||
*.pdf
|
*.pdf
|
||||||
|
*.out
|
||||||
|
*.log
|
||||||
|
*.stat
|
||||||
|
|
|
@ -2,9 +2,10 @@ PROGRAM_PREFIX :=
|
||||||
|
|
||||||
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
||||||
|
|
||||||
.PHONY: all dots
|
.PHONY: all dots examples
|
||||||
all: dots test0.log test1.log test2.log
|
all: dots examples
|
||||||
dots: test1.dot
|
dots: test1.dot my_cmd.so
|
||||||
|
examples: test0.log test1.log test2.log my_cmd.so
|
||||||
|
|
||||||
CXXFLAGS=$(shell $(YOSYS)-config --cxxflags)
|
CXXFLAGS=$(shell $(YOSYS)-config --cxxflags)
|
||||||
DATDIR=$(shell $(YOSYS)-config --datdir)
|
DATDIR=$(shell $(YOSYS)-config --datdir)
|
||||||
|
|
|
@ -51,10 +51,10 @@ struct Test2Pass : public Pass {
|
||||||
Test2Pass() : Pass("test2", "demonstrating sigmap on test module") { }
|
Test2Pass() : Pass("test2", "demonstrating sigmap on test module") { }
|
||||||
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
void execute(std::vector<std::string>, RTLIL::Design *design) override
|
||||||
{
|
{
|
||||||
if (design->selection_stack.back().empty())
|
if (design->selection().empty())
|
||||||
log_cmd_error("This command can't operator on an empty selection!\n");
|
log_cmd_error("This command can't operator on an empty selection!\n");
|
||||||
|
|
||||||
RTLIL::Module *module = design->modules_.at("\\test");
|
RTLIL::Module *module = design->module("\\test");
|
||||||
|
|
||||||
RTLIL::SigSpec a(module->wire("\\a")), x(module->wire("\\x")), y(module->wire("\\y"));
|
RTLIL::SigSpec a(module->wire("\\a")), x(module->wire("\\x")), y(module->wire("\\y"));
|
||||||
log("%d %d %d\n", a == x, x == y, y == a); // will print "0 0 0"
|
log("%d %d %d\n", a == x, x == y, y == a); // will print "0 0 0"
|
||||||
|
|
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))
|
DOTS := $(addsuffix .dot,$(DOT_NAMES))
|
||||||
MAPDOTS := $(addsuffix .dot,$(MAPDOT_NAMES))
|
MAPDOTS := $(addsuffix .dot,$(MAPDOT_NAMES))
|
||||||
|
|
||||||
all: dots fifo.out fifo.stat
|
.PHONY: all dots examples
|
||||||
|
all: dots examples
|
||||||
dots: $(DOTS) $(MAPDOTS)
|
dots: $(DOTS) $(MAPDOTS)
|
||||||
|
examples: fifo.out fifo.stat
|
||||||
|
|
||||||
$(DOTS) fifo.out: fifo.v fifo.ys
|
$(DOTS) fifo.out: fifo.v fifo.ys
|
||||||
$(YOSYS) fifo.ys -l fifo.out -Q -T
|
$(YOSYS) fifo.ys -l fifo.out -Q -T
|
||||||
|
@ -22,3 +24,4 @@ $(MAPDOTS) fifo.stat: fifo.v fifo_map.ys
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f *.dot
|
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
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ module addr_gen
|
||||||
) ( input en, clk, rst,
|
) ( input en, clk, rst,
|
||||||
output reg [AWIDTH-1:0] addr
|
output reg [AWIDTH-1:0] addr
|
||||||
);
|
);
|
||||||
initial addr <= 0;
|
initial addr = 0;
|
||||||
|
|
||||||
// async reset
|
// async reset
|
||||||
// increment address when enabled
|
// increment address when enabled
|
||||||
|
@ -13,7 +13,7 @@ module addr_gen
|
||||||
if (rst)
|
if (rst)
|
||||||
addr <= 0;
|
addr <= 0;
|
||||||
else if (en) begin
|
else if (en) begin
|
||||||
if (addr == MAX_DATA-1)
|
if ({'0, addr} == MAX_DATA-1)
|
||||||
addr <= 0;
|
addr <= 0;
|
||||||
else
|
else
|
||||||
addr <= addr + 1;
|
addr <= addr + 1;
|
||||||
|
@ -57,7 +57,7 @@ module fifo
|
||||||
);
|
);
|
||||||
|
|
||||||
// status signals
|
// status signals
|
||||||
initial count <= 0;
|
initial count = 0;
|
||||||
|
|
||||||
always @(posedge clk or posedge rst) begin
|
always @(posedge clk or posedge rst) begin
|
||||||
if (rst)
|
if (rst)
|
||||||
|
|
|
@ -67,7 +67,7 @@ show -color maroon3 @new_cells -notitle -format dot -prefix rdata_memrdv2 o:rdat
|
||||||
# ========================================================
|
# ========================================================
|
||||||
|
|
||||||
alumacc
|
alumacc
|
||||||
select -set new_cells t:$alu t:$macc
|
select -set new_cells t:$alu t:$macc_v2
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_alumacc o:rdata %ci*
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_alumacc o:rdata %ci*
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
|
|
44
docs/source/code_examples/functional/dummy.cc
Normal file
44
docs/source/code_examples/functional/dummy.cc
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "kernel/functional.h"
|
||||||
|
#include "kernel/yosys.h"
|
||||||
|
|
||||||
|
USING_YOSYS_NAMESPACE
|
||||||
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct FunctionalDummyBackend : public Backend {
|
||||||
|
FunctionalDummyBackend() : Backend("functional_dummy", "dump generated Functional IR") {}
|
||||||
|
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
|
||||||
|
{
|
||||||
|
// backend pass boiler plate
|
||||||
|
log_header(design, "Executing dummy functional backend.\n");
|
||||||
|
|
||||||
|
size_t argidx = 1;
|
||||||
|
extra_args(f, filename, args, argidx, design);
|
||||||
|
|
||||||
|
for (auto module : design->selected_modules())
|
||||||
|
{
|
||||||
|
log("Processing module `%s`.\n", module->name.c_str());
|
||||||
|
|
||||||
|
// convert module to FunctionalIR
|
||||||
|
auto ir = Functional::IR::from_module(module);
|
||||||
|
*f << "module " << module->name.c_str() << "\n";
|
||||||
|
|
||||||
|
// write node functions
|
||||||
|
for (auto node : ir)
|
||||||
|
*f << " assign " << id2cstr(node.name())
|
||||||
|
<< " = " << node.to_string() << "\n";
|
||||||
|
*f << "\n";
|
||||||
|
|
||||||
|
// write outputs and next state
|
||||||
|
for (auto output : ir.outputs())
|
||||||
|
*f << " " << id2cstr(output->kind)
|
||||||
|
<< " " << id2cstr(output->name)
|
||||||
|
<< " = " << id2cstr(output->value().name()) << "\n";
|
||||||
|
for (auto state : ir.states())
|
||||||
|
*f << " " << id2cstr(state->kind)
|
||||||
|
<< " " << id2cstr(state->name)
|
||||||
|
<< " = " << id2cstr(state->next_value().name()) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} FunctionalDummyBackend;
|
||||||
|
|
||||||
|
PRIVATE_NAMESPACE_END
|
|
@ -4,8 +4,10 @@ YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
||||||
|
|
||||||
DOTS = counter_00.dot counter_01.dot counter_02.dot counter_03.dot
|
DOTS = counter_00.dot counter_01.dot counter_02.dot counter_03.dot
|
||||||
|
|
||||||
all: dots
|
.PHONY: all dots examples
|
||||||
|
all: dots examples
|
||||||
dots: $(DOTS)
|
dots: $(DOTS)
|
||||||
|
examples:
|
||||||
|
|
||||||
$(DOTS): counter.v counter.ys mycells.lib
|
$(DOTS): counter.v counter.ys mycells.lib
|
||||||
$(YOSYS) counter.ys
|
$(YOSYS) counter.ys
|
||||||
|
|
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