mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-15 03:35:40 +00:00
Merge remote-tracking branch 'upstream/main' into silimate
This commit is contained in:
commit
e58125b605
834 changed files with 25281 additions and 8780 deletions
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -6,7 +6,7 @@ body:
|
|||
attributes:
|
||||
value: >
|
||||
|
||||
Learn more [here](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) about how to report bugs. We fix well-reported bugs the fastest.
|
||||
Learn more in our [Reporting bugs](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) docs section. We fix well-reported bugs the fastest.
|
||||
|
||||
If you have a general question, please ask it on the [Discourse forum](https://yosyshq.discourse.group/).
|
||||
|
||||
|
|
|
|||
2
.github/actions/setup-build-env/action.yml
vendored
2
.github/actions/setup-build-env/action.yml
vendored
|
|
@ -42,7 +42,7 @@ runs:
|
|||
if: runner.os == 'Linux' && inputs.get-build-deps == 'true'
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||
with:
|
||||
packages: gawk git make python3 bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache libgtest-dev
|
||||
packages: gawk git make python3 bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev libnsl-dev libdwarf-dev libelf-dev elfutils libdw-dev ccache libgtest-dev libgmock-dev
|
||||
version: ${{ inputs.runs-on }}-buildys
|
||||
|
||||
- name: Linux docs dependencies
|
||||
|
|
|
|||
14
.github/workflows/codeql.yml
vendored
14
.github/workflows/codeql.yml
vendored
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
permissions: write-all
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
get-build-deps: true
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: cpp
|
||||
queries: security-extended,security-and-quality
|
||||
|
|
@ -37,7 +37,13 @@ jobs:
|
|||
run: cd verific/tclmain && make -j6
|
||||
|
||||
- name: Build
|
||||
run: make yosys -j6
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j6
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
|
|
|
|||
132
.github/workflows/extra-builds.yml
vendored
132
.github/workflows/extra-builds.yml
vendored
|
|
@ -1,23 +1,20 @@
|
|||
name: Test extra build flows
|
||||
|
||||
on:
|
||||
# always test main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
merge_group:
|
||||
# test PRs
|
||||
pull_request:
|
||||
# allow triggering tests, ignores skip check
|
||||
merge_group:
|
||||
#push:
|
||||
# branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
if: ${{ github.event_name != 'merge_group' }}
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# don't run on documentation changes
|
||||
|
|
@ -26,58 +23,67 @@ jobs:
|
|||
# but never cancel main
|
||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
vs-prep:
|
||||
name: Prepare Visual Studio build
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre_job]
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
- run: sudo apt-get install libfl-dev
|
||||
- name: Build
|
||||
run: make vcxsrc YOSYS_COMPILER="Visual Studio" VCX_DIR_NAME=yosys-win32-vcxsrc-latest
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: vcxsrc
|
||||
path: yosys-win32-vcxsrc-latest.zip
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
vs-build:
|
||||
name: Visual Studio build
|
||||
runs-on: windows-latest
|
||||
needs: [vs-prep, pre_job]
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
needs: [pre_job]
|
||||
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
name: vcxsrc
|
||||
path: .
|
||||
- name: unzip
|
||||
run: unzip yosys-win32-vcxsrc-latest.zip
|
||||
- name: setup-msbuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
- name: MSBuild
|
||||
working-directory: yosys-win32-vcxsrc-latest
|
||||
run: msbuild YosysVS.sln /p:PlatformToolset=v142 /p:Configuration=Release /p:WindowsTargetPlatformVersion=10.0.26100.0
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: Install flex/bison
|
||||
shell: pwsh
|
||||
run: |
|
||||
choco install winflexbison3 --no-progress
|
||||
|
||||
# Make tools visible to CMake
|
||||
echo "C:\Program Files (x86)\GnuWin32\bin" | Out-File -Append -FilePath $env:GITHUB_PATH
|
||||
echo "C:\ProgramData\chocolatey\lib\winflexbison3\tools" | Out-File -Append -FilePath $env:GITHUB_PATH
|
||||
|
||||
- name: Configure CMake
|
||||
run: >
|
||||
cmake -S . -B build
|
||||
-A x64
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DYOSYS_WITHOUT_ABC=ON
|
||||
|
||||
- name: Build
|
||||
run: >
|
||||
cmake --build build
|
||||
--config Release
|
||||
--parallel
|
||||
|
||||
wasi-build:
|
||||
name: WASI build
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
- name: Build
|
||||
run: |
|
||||
WASI_SDK=wasi-sdk-27.0-x86_64-linux
|
||||
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz
|
||||
WASI_VER=33
|
||||
WASI_SDK=wasi-sdk-${WASI_VER}.0-x86_64-linux
|
||||
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VER}/${WASI_SDK}.tar.gz
|
||||
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
|
||||
|
||||
WASI_SDK_PATH=$(pwd)/${WASI_SDK}
|
||||
FLEX_VER=2.6.4
|
||||
FLEX=flex-${FLEX_VER}
|
||||
FLEX_URL=https://github.com/westes/flex/releases/download/v${FLEX_VER}/${FLEX}.tar.gz
|
||||
|
|
@ -89,35 +95,21 @@ jobs:
|
|||
make &&
|
||||
make install)
|
||||
|
||||
mkdir -p build
|
||||
cat > build/Makefile.conf <<END
|
||||
export PATH := $(pwd)/${WASI_SDK}/bin:$(pwd)/flex-prefix/bin:${PATH}
|
||||
WASI_SYSROOT := $(pwd)/${WASI_SDK}/share/wasi-sysroot
|
||||
|
||||
CONFIG := wasi
|
||||
PREFIX := /
|
||||
|
||||
ENABLE_TCL := 0
|
||||
ENABLE_READLINE := 0
|
||||
ENABLE_PLUGINS := 0
|
||||
ENABLE_ZLIB := 0
|
||||
|
||||
CXXFLAGS += -I$(pwd)/flex-prefix/include
|
||||
END
|
||||
|
||||
make -C build -f ../Makefile CXX=clang -j$(nproc)
|
||||
export PATH=${WASI_SDK_PATH}/bin:$(pwd)/flex-prefix/bin:${PATH}
|
||||
cmake -B build -DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PATH}/share/cmake/wasi-sdk-p1.cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
cmake --build build -j$(nproc)
|
||||
|
||||
nix-build:
|
||||
name: "Build nix flake"
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
|
@ -125,3 +117,21 @@ jobs:
|
|||
with:
|
||||
install_url: https://releases.nixos.org/nix/nix-2.30.0/install
|
||||
- run: nix build .?submodules=1 -L
|
||||
|
||||
extra-builds-result:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- vs-build
|
||||
- wasi-build
|
||||
- nix-build
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||
echo "Some jobs failed or were cancelled"
|
||||
exit 1
|
||||
fi
|
||||
- run: echo "All good"
|
||||
|
|
|
|||
50
.github/workflows/prepare-docs.yml
vendored
50
.github/workflows/prepare-docs.yml
vendored
|
|
@ -1,12 +1,18 @@
|
|||
name: Build docs artifact with Verific
|
||||
|
||||
on: [push, pull_request, merge_group]
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [ main, "docs-preview/**", "docs-preview*" ]
|
||||
tags: [ "*" ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check_docs_rebuild:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
skip_check: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.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/') }}
|
||||
|
|
@ -17,16 +23,26 @@ jobs:
|
|||
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'}}
|
||||
# push filtering means we only want to skip duplicates for PRs
|
||||
do_not_skip: '["workflow_dispatch", "merge_group", "push"]'
|
||||
concurrent_skipping: 'same_content_newer'
|
||||
|
||||
- id: docs_var
|
||||
run: echo "docs_export=${docs_export}" >> $GITHUB_OUTPUT
|
||||
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
prepare-docs:
|
||||
# docs builds are needed for anything on main, any tagged versions, and any tag
|
||||
# or branch starting with docs-preview
|
||||
needs: check_docs_rebuild
|
||||
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
||||
if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
|
|
@ -41,19 +57,19 @@ jobs:
|
|||
|
||||
- name: Build Yosys
|
||||
run: |
|
||||
make config-clang
|
||||
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||
echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf
|
||||
make -j$procs
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: Prepare docs
|
||||
shell: bash
|
||||
run:
|
||||
make docs/prep -j$procs TARGETS= EXTRA_TARGETS=
|
||||
cmake --build build --target docs-prepare -j$procs
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
@ -67,15 +83,15 @@ jobs:
|
|||
- name: Install doc prereqs
|
||||
shell: bash
|
||||
run: |
|
||||
make docs/reqs
|
||||
make -C docs reqs
|
||||
|
||||
- name: Test build docs
|
||||
shell: bash
|
||||
run: |
|
||||
make -C docs html -j$procs TARGETS= EXTRA_TARGETS=
|
||||
cmake --build build --target docs-html -j$procs
|
||||
|
||||
- name: Trigger RTDs build
|
||||
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' }}
|
||||
if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' && github.repository == 'YosysHQ/yosys' }}
|
||||
uses: dfm/rtds-action@v1.1.0
|
||||
with:
|
||||
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
|
||||
|
|
|
|||
11
.github/workflows/source-vendor.yml
vendored
11
.github/workflows/source-vendor.yml
vendored
|
|
@ -1,13 +1,18 @@
|
|||
name: Create source archive with vendored dependencies
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
vendor-sources:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository with submodules
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
persist-credentials: false
|
||||
|
|
@ -28,7 +33,7 @@ jobs:
|
|||
gzip yosys-src-vendored.tar
|
||||
|
||||
- name: Store tarball artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: vendored-sources
|
||||
path: yosys-src-vendored.tar.gz
|
||||
|
|
|
|||
117
.github/workflows/test-build.yml
vendored
117
.github/workflows/test-build.yml
vendored
|
|
@ -1,23 +1,20 @@
|
|||
name: Build and run tests
|
||||
|
||||
on:
|
||||
# always test main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
merge_group:
|
||||
# test PRs
|
||||
pull_request:
|
||||
# allow triggering tests, ignores skip check
|
||||
merge_group:
|
||||
#push:
|
||||
# branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
if: ${{ github.event_name != 'merge_group' }}
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# don't run on documentation changes
|
||||
|
|
@ -26,12 +23,21 @@ jobs:
|
|||
# but never cancel main
|
||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
pre_docs_job:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
if: ${{ github.event_name != 'merge_group' }}
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# don't run on readme changes
|
||||
|
|
@ -40,6 +46,14 @@ jobs:
|
|||
# but never cancel main
|
||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
build-yosys:
|
||||
name: Reusable build
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
@ -54,7 +68,7 @@ jobs:
|
|||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
|
@ -71,24 +85,23 @@ jobs:
|
|||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
make -f ../Makefile config-$CC ENABLE_LTO=1 SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0 VERIFIC_DIR=../verific
|
||||
make -f ../Makefile -j$procs ENABLE_LTO=1 SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0 VERIFIC_DIR=../verific
|
||||
make -f ../Makefile unit-test -j$procs ENABLE_LTO=1 SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0 VERIFIC_DIR=../verific
|
||||
rm -rf build
|
||||
cmake -B build . -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j$procs
|
||||
ctest --test-dir build/tests/unit
|
||||
|
||||
- name: Log yosys-config output
|
||||
run: |
|
||||
./yosys-config || true
|
||||
./build/yosys-config || true
|
||||
|
||||
- name: Compress build
|
||||
shell: bash
|
||||
run: |
|
||||
cd build
|
||||
tar -cvf ../build.tar share/ yosys yosys-* libyosys.so
|
||||
tar -cvf ../build.tar share/ yosys yosys-*
|
||||
|
||||
- name: Store build artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: build-${{ matrix.os }}
|
||||
path: build.tar
|
||||
|
|
@ -107,7 +120,7 @@ jobs:
|
|||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
|
@ -120,18 +133,19 @@ jobs:
|
|||
get-iverilog: true
|
||||
|
||||
- name: Download build artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: build-${{ matrix.os }}
|
||||
|
||||
- name: Uncompress build
|
||||
shell: bash
|
||||
run:
|
||||
tar -xvf build.tar
|
||||
run: |
|
||||
mkdir -p build
|
||||
tar -xvf build.tar -C build
|
||||
|
||||
- name: Log yosys-config output
|
||||
run: |
|
||||
./yosys-config || true
|
||||
./build/yosys-config || true
|
||||
|
||||
- name: Build Verific
|
||||
run: cd verific/tclmain && make -j$procs
|
||||
|
|
@ -139,7 +153,7 @@ jobs:
|
|||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
make -j$procs vanilla-test TARGETS= EXTRA_TARGETS= CONFIG=$CC SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0
|
||||
make -C tests -j$procs vanilla-test
|
||||
|
||||
- name: Report errors
|
||||
if: ${{ failure() }}
|
||||
|
|
@ -159,7 +173,9 @@ jobs:
|
|||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-build-env
|
||||
|
|
@ -167,7 +183,7 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
|
||||
- name: Download build artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: build-${{ matrix.os }}
|
||||
|
||||
|
|
@ -189,15 +205,13 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
needs: [build-yosys, pre_docs_job]
|
||||
if: needs.pre_docs_job.outputs.should_skip != 'true'
|
||||
env:
|
||||
CC: clang
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
|
|
@ -210,18 +224,19 @@ jobs:
|
|||
get-docs-deps: true
|
||||
|
||||
- name: Download build artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: build-${{ matrix.os }}
|
||||
|
||||
- name: Uncompress build
|
||||
shell: bash
|
||||
run:
|
||||
tar -xvf build.tar
|
||||
run: |
|
||||
mkdir -p build
|
||||
tar -xvf build.tar -C build
|
||||
|
||||
- name: Log yosys-config output
|
||||
run: |
|
||||
./yosys-config || true
|
||||
./build/yosys-config || true
|
||||
|
||||
- name: Build Verific
|
||||
run: cd verific/tclmain && make -j$procs
|
||||
|
|
@ -235,7 +250,7 @@ jobs:
|
|||
name: Try build docs
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
needs: [pre_docs_job]
|
||||
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
||||
if: ${{ needs.pre_docs_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||
strategy:
|
||||
matrix:
|
||||
docs-target: [html, latexpdf]
|
||||
|
|
@ -253,20 +268,23 @@ jobs:
|
|||
|
||||
- name: Build Yosys
|
||||
run: |
|
||||
make config-clang
|
||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||
echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf
|
||||
make -j$procs
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: Install doc prereqs
|
||||
shell: bash
|
||||
run: |
|
||||
make docs/reqs
|
||||
make -C docs reqs
|
||||
|
||||
- name: Build docs
|
||||
shell: bash
|
||||
run: |
|
||||
make docs DOC_TARGET=${{ matrix.docs-target }} -j$procs
|
||||
cmake --build build --target docs-${{ matrix.docs-target }} -j$procs
|
||||
|
||||
- name: Store docs build artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
@ -274,3 +292,22 @@ jobs:
|
|||
name: docs-build-${{ matrix.docs-target }}
|
||||
path: docs/build/
|
||||
retention-days: 7
|
||||
|
||||
test-build-result:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- test-yosys
|
||||
- test-cells
|
||||
- test-docs
|
||||
- test-docs-build
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||
echo "Some jobs failed or were cancelled"
|
||||
exit 1
|
||||
fi
|
||||
- run: echo "All good"
|
||||
|
|
|
|||
76
.github/workflows/test-compile.yml
vendored
76
.github/workflows/test-compile.yml
vendored
|
|
@ -1,23 +1,20 @@
|
|||
name: Compiler testing
|
||||
|
||||
on:
|
||||
# always test main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
merge_group:
|
||||
# test PRs
|
||||
pull_request:
|
||||
# allow triggering tests, ignores skip check
|
||||
merge_group:
|
||||
#push:
|
||||
# branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
if: ${{ github.event_name != 'merge_group' }}
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# don't run on documentation changes
|
||||
|
|
@ -26,35 +23,42 @@ jobs:
|
|||
# but never cancel main
|
||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
test-compile:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||
env:
|
||||
CXXFLAGS: ${{ startsWith(matrix.compiler, 'gcc') && '-Wp,-D_GLIBCXX_ASSERTIONS' || ''}}
|
||||
CC_SHORT: ${{ startsWith(matrix.compiler, 'gcc') && 'gcc' || 'clang' }}
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
compiler:
|
||||
# oldest supported
|
||||
- 'clang-10'
|
||||
- 'gcc-10'
|
||||
- 'clang-14'
|
||||
- 'gcc-11'
|
||||
# newest, make sure to update maximum standard step to match
|
||||
- 'clang-19'
|
||||
- 'gcc-14'
|
||||
- 'clang-22'
|
||||
- 'gcc-16'
|
||||
include:
|
||||
# macOS x86
|
||||
- os: macos-15-intel
|
||||
compiler: 'clang-19'
|
||||
compiler: 'clang-22'
|
||||
# macOS arm
|
||||
- os: macos-latest
|
||||
compiler: 'clang-19'
|
||||
compiler: 'clang-22'
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
|
@ -69,6 +73,7 @@ jobs:
|
|||
uses: aminya/setup-cpp@v1
|
||||
with:
|
||||
compiler: ${{ matrix.compiler }}
|
||||
gcc: ${{ (matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14') && '12' || '' }}
|
||||
|
||||
- name: Tool versions
|
||||
shell: bash
|
||||
|
|
@ -76,17 +81,40 @@ jobs:
|
|||
$CC --version
|
||||
$CXX --version
|
||||
|
||||
- name: Fix clang-14 toolchain
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.compiler == 'clang-14'
|
||||
run: |
|
||||
echo 'CXXFLAGS=--gcc-toolchain=/usr -isystem /usr/include/c++/12 -isystem /usr/include/x86_64-linux-gnu/c++/12' >> $GITHUB_ENV
|
||||
|
||||
# minimum standard
|
||||
- name: Build C++17
|
||||
- name: Build C++20
|
||||
shell: bash
|
||||
run: |
|
||||
make config-$CC_SHORT
|
||||
make -j$procs CXXSTD=c++17 compile-only
|
||||
rm -rf build
|
||||
cmake -B build -DCMAKE_CXX_STANDARD=20 . --fresh
|
||||
cmake --build build --target yosys -j$procs
|
||||
|
||||
# maximum standard, only on newest compilers
|
||||
- name: Build C++20
|
||||
if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }}
|
||||
- name: Build C++26
|
||||
if: ${{ matrix.compiler == 'clang-22' || matrix.compiler == 'gcc-16' }}
|
||||
shell: bash
|
||||
run: |
|
||||
make config-$CC_SHORT
|
||||
make -j$procs CXXSTD=c++20 compile-only
|
||||
rm -rf build
|
||||
cmake -B build -DCMAKE_CXX_STANDARD=26 . --fresh
|
||||
cmake --build build --target yosys -j$procs
|
||||
|
||||
test-compile-result:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- test-compile
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||
echo "Some jobs failed or were cancelled"
|
||||
exit 1
|
||||
fi
|
||||
- run: echo "All good"
|
||||
|
|
|
|||
56
.github/workflows/test-sanitizers.yml
vendored
56
.github/workflows/test-sanitizers.yml
vendored
|
|
@ -1,35 +1,44 @@
|
|||
name: Check clang sanitizers
|
||||
|
||||
on:
|
||||
# always test main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
merge_group:
|
||||
# ignore PRs due to time needed
|
||||
# allow triggering tests, ignores skip check
|
||||
#push:
|
||||
# branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
if: ${{ github.event_name != 'merge_group' }}
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# don't run on documentation changes
|
||||
paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]'
|
||||
# cancel previous builds if a new commit is pushed
|
||||
# but never cancel main
|
||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
run_san:
|
||||
name: Build and run tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
if: (github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch') && needs.pre_job.outputs.should_skip != 'true'
|
||||
env:
|
||||
CC: clang
|
||||
ASAN_OPTIONS: halt_on_error=1
|
||||
ASAN_OPTIONS: halt_on_error=1 detect_container_overflow=0
|
||||
UBSAN_OPTIONS: halt_on_error=1
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
@ -38,7 +47,7 @@ jobs:
|
|||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
|
@ -55,18 +64,20 @@ jobs:
|
|||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
make config-$CC SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0 ENABLE_VERIFIC=0
|
||||
echo 'SANITIZER = ${{ matrix.sanitizer }}' >> Makefile.conf
|
||||
make -j$procs SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0 ENABLE_VERIFIC=0
|
||||
rm -rf build
|
||||
cmake -B build . \
|
||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ \
|
||||
-DCMAKE_BUILD_TYPE=Sanitize -DSANITIZE=${{ matrix.sanitizer }}
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: Log yosys-config output
|
||||
run: |
|
||||
./yosys-config || true
|
||||
./build/yosys-config || true
|
||||
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
make -j$procs vanilla-test TARGETS= EXTRA_TARGETS= SMALL=0 ENABLE_PLUGINS=1 ENABLE_PYOSYS=0 ENABLE_CCACHE=0 ENABLE_EDITLINE=0 ENABLE_VERIFIC=0
|
||||
make -C tests -j$procs vanilla-test
|
||||
|
||||
- name: Report errors
|
||||
if: ${{ failure() }}
|
||||
|
|
@ -74,3 +85,18 @@ jobs:
|
|||
run: |
|
||||
find tests/**/*.err -print -exec cat {} \;
|
||||
|
||||
test-sanitizers-result:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- run_san
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||
echo "Some jobs failed or were cancelled"
|
||||
exit 1
|
||||
fi
|
||||
- run: echo "All good"
|
||||
|
|
|
|||
95
.github/workflows/test-verific-cfg.yml
vendored
Normal file
95
.github/workflows/test-verific-cfg.yml
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
name: Build various Verific configurations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test-verific-cfg:
|
||||
if: github.repository_owner == 'YosysHQ'
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
- name: Runtime environment
|
||||
run: |
|
||||
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||
|
||||
- name: verific [SV]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: verific [VHDL]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "vhdl" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: verific [SV + VHDL]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "vhdl;systemverilog" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: verific [SV + HIER]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog;hier_tree" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: verific [VHDL + HIER]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "vhdl;hier_tree" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: verific [SV + VHDL + HIER]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog;vhdl;hier_tree" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: verific [SV + VHDL + HIER + EDIF + LIBERTY]
|
||||
run: |
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_FEATURES "systemverilog;vhdl;hier_tree;edif;liberty" CACHE STRING "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build .
|
||||
cmake --build build -j$procs
|
||||
127
.github/workflows/test-verific.yml
vendored
127
.github/workflows/test-verific.yml
vendored
|
|
@ -1,23 +1,20 @@
|
|||
name: Build and run tests with Verific (Linux)
|
||||
|
||||
on:
|
||||
# always test main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
merge_group:
|
||||
# test PRs
|
||||
pull_request:
|
||||
# allow triggering tests, ignores skip check
|
||||
merge_group:
|
||||
#push:
|
||||
# branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
pre-job:
|
||||
pre_job:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
should_skip: ${{ steps.set_output.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
if: ${{ github.event_name != 'merge_group' }}
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# don't run on documentation changes
|
||||
|
|
@ -26,9 +23,17 @@ jobs:
|
|||
# but never cancel main
|
||||
cancel_others: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
- id: set_output
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "merge_group" ]; then
|
||||
echo "should_skip=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "should_skip=${{ steps.skip_check.outputs.should_skip }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
test-verific:
|
||||
needs: pre-job
|
||||
if: ${{ needs.pre-job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
||||
needs: pre_job
|
||||
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
|
|
@ -39,21 +44,30 @@ jobs:
|
|||
- name: Runtime environment
|
||||
run: |
|
||||
echo "procs=$(nproc)" >> $GITHUB_ENV
|
||||
mkdir -p "${GITHUB_WORKSPACE}/coverage"
|
||||
echo "LLVM_PROFILE_FILE=${GITHUB_WORKSPACE}/coverage/coverage_%p.profraw" >> $GITHUB_ENV
|
||||
echo "LLVM_PROFILE_FILE_BUFFER_SIZE=0" >> $GITHUB_ENV
|
||||
|
||||
- name: Skip generating files
|
||||
if: ${{ github.event_name != 'merge_group' && github.event_name != 'workflow_dispatch' }}
|
||||
run: |
|
||||
echo "LLVM_PROFILE_FILE=/dev/null" >> $GITHUB_ENV
|
||||
|
||||
- name: Build Yosys
|
||||
run: |
|
||||
make config-clang
|
||||
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||
echo "ENABLE_FUNCTIONAL_TESTS := 1" >> Makefile.conf
|
||||
make -j$procs ENABLE_LTO=1
|
||||
rm -rf build Configuration.cmake
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_ENABLE_COVERAGE ON CACHE BOOL "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
|
||||
cmake -C Configuration.cmake -B build . -DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.local -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: Install Yosys
|
||||
run: |
|
||||
make install DESTDIR=${GITHUB_WORKSPACE}/.local PREFIX=
|
||||
cmake --build build --target install
|
||||
|
||||
- name: Checkout SBY
|
||||
uses: actions/checkout@v4
|
||||
|
|
@ -68,21 +82,46 @@ jobs:
|
|||
|
||||
- name: Run Yosys tests
|
||||
run: |
|
||||
make -j$procs vanilla-test
|
||||
make -C tests -j$procs vanilla-test
|
||||
|
||||
- name: Run Verific specific Yosys tests
|
||||
run: |
|
||||
make -C tests/sva
|
||||
cd tests/svtypes && bash run-test.sh
|
||||
make -C tests/svtypes
|
||||
|
||||
- name: Run SBY tests
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
make -C sby run_ci
|
||||
|
||||
- name: Run coverage
|
||||
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
make -C tests coverage
|
||||
make -C tests clean_coverage
|
||||
|
||||
- name: Push coverage
|
||||
if: ${{ github.event_name == 'merge_group' || github.event_name == 'workflow_dispatch' }}
|
||||
run: |
|
||||
git clone https://x-access-token:${{ secrets.REPORTS_TOKEN }}@github.com/YosysHQ/reports.git out
|
||||
rm -rf out/coverage/main
|
||||
mkdir -p out/coverage/main
|
||||
cp -r coverage_html/* out/coverage/main/
|
||||
cd out
|
||||
# find . -name "*.html" -type f -print0 | xargs -0 sed -i -z 's#\(<td class="headerItem">Date:</td>[[:space:]]*<td class="headerValue">\)[^<]*\(</td>\)#\1\2#g'
|
||||
git config user.name "yosyshq-ci"
|
||||
git config user.email "105224853+yosyshq-ci@users.noreply.github.com"
|
||||
git add .
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "Update coverage"
|
||||
git push
|
||||
else
|
||||
echo "No changes to commit"
|
||||
fi
|
||||
|
||||
test-pyosys:
|
||||
needs: pre-job
|
||||
if: ${{ needs.pre-job.outputs.should_skip != 'true' && github.repository == 'YosysHQ/Yosys' }}
|
||||
needs: pre_job
|
||||
if: ${{ needs.pre_job.outputs.should_skip != 'true' && github.repository_owner == 'YosysHQ' }}
|
||||
runs-on: [self-hosted, linux, x64, fast]
|
||||
steps:
|
||||
- name: Checkout Yosys
|
||||
|
|
@ -100,21 +139,39 @@ jobs:
|
|||
|
||||
- name: Build pyosys
|
||||
run: |
|
||||
make config-clang
|
||||
echo "ENABLE_VERIFIC := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf
|
||||
echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf
|
||||
echo "ENABLE_CCACHE := 1" >> Makefile.conf
|
||||
echo "ENABLE_PYOSYS := 1" >> Makefile.conf
|
||||
echo "PYTHON_DESTDIR := /usr/lib/python3/site-packages" >> Makefile.conf
|
||||
make -j$procs
|
||||
echo 'set(CMAKE_C_COMPILER clang CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(CMAKE_CXX_COMPILER clang++ CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_COMPILER_LAUNCHER ccache CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_VERIFIC_DIR "/usr/local/src/verific_lib" CACHE STRING "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_WITH_PYTHON ON CACHE BOOL "")' >> Configuration.cmake
|
||||
echo 'set(YOSYS_INSTALL_PYTHON ON CACHE BOOL "")' >> Configuration.cmake
|
||||
cmake -C Configuration.cmake -B build . \
|
||||
-DCMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.local \
|
||||
-DYOSYS_INSTALL_PYTHON_SITEDIR=$GITHUB_WORKSPACE/.local/usr/lib/python3/site-packages
|
||||
cmake --build build -j$procs
|
||||
|
||||
- name: Install pyosys
|
||||
run: |
|
||||
make install DESTDIR=${GITHUB_WORKSPACE}/.local PREFIX=
|
||||
cmake --build build --target install
|
||||
|
||||
- name: Run pyosys tests
|
||||
run: |
|
||||
export PYTHONPATH=${GITHUB_WORKSPACE}/.local/usr/lib/python3/site-packages:$PYTHONPATH
|
||||
python3 tests/pyosys/run_tests.py
|
||||
|
||||
test-verific-result:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- test-verific
|
||||
- test-pyosys
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
echo "Needs results: ${{ join(needs.*.result, ',') }}"
|
||||
if [[ "${{ join(needs.*.result, ',') }}" == *failure* ]] || \
|
||||
[[ "${{ join(needs.*.result, ',') }}" == *cancelled* ]]; then
|
||||
echo "Some jobs failed or were cancelled"
|
||||
exit 1
|
||||
fi
|
||||
- run: echo "All good"
|
||||
|
|
|
|||
25
.github/workflows/update-flake-lock.yml
vendored
25
.github/workflows/update-flake-lock.yml
vendored
|
|
@ -1,25 +0,0 @@
|
|||
name: update-flake-lock
|
||||
on:
|
||||
workflow_dispatch: # allows manual triggering
|
||||
schedule:
|
||||
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
|
||||
|
||||
jobs:
|
||||
lockfile:
|
||||
if: github.repository == 'YosysHQ/Yosys'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
- name: Update flake.lock
|
||||
uses: DeterminateSystems/update-flake-lock@main
|
||||
with:
|
||||
token: ${{CI_CREATE_PR_TOKEN}}
|
||||
pr-title: "Update flake.lock" # Title of PR to be created
|
||||
pr-labels: | # Labels to be set on the PR
|
||||
dependencies
|
||||
automated
|
||||
34
.github/workflows/version.yml
vendored
34
.github/workflows/version.yml
vendored
|
|
@ -1,34 +0,0 @@
|
|||
name: Bump version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
bump-version:
|
||||
if: github.repository == 'YosysHQ/Yosys'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
- name: Take last commit
|
||||
id: log
|
||||
run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT
|
||||
- name: Bump version
|
||||
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
|
||||
run: |
|
||||
make bumpversion
|
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git add Makefile
|
||||
git commit -m "Bump version"
|
||||
- name: Push changes # push the output folder to your repo
|
||||
if: ${{ !contains(steps.log.outputs.message, 'Bump version') }}
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
26
.github/workflows/wheels.yml
vendored
26
.github/workflows/wheels.yml
vendored
|
|
@ -36,20 +36,18 @@ jobs:
|
|||
runner: "macos-15",
|
||||
archs: "arm64",
|
||||
},
|
||||
## Windows is disabled because of an issue with compiling FFI as
|
||||
## under MinGW in the GitHub Actions environment (SHELL variable has
|
||||
## whitespace.)
|
||||
## Windows still needs to be tested.
|
||||
# {
|
||||
# name: "Windows Server 2019",
|
||||
# name: "Windows Server 2025",
|
||||
# family: "windows",
|
||||
# runner: "windows-2019",
|
||||
# runner: "windows-2025",
|
||||
# archs: "AMD64",
|
||||
# },
|
||||
]
|
||||
name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }}
|
||||
runs-on: ${{ matrix.os.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
|
@ -77,17 +75,14 @@ jobs:
|
|||
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
|
||||
uses: pypa/cibuildwheel@v3.4.1
|
||||
env:
|
||||
# * APIs not supported by PyPy
|
||||
# * Musllinux disabled because it increases build time from 48m to ~3h
|
||||
CIBW_SKIP: >
|
||||
cp38*
|
||||
cp39*
|
||||
pp*
|
||||
*musllinux*
|
||||
CIBW_ARCHS: ${{ matrix.os.archs }}
|
||||
|
|
@ -104,17 +99,16 @@ jobs:
|
|||
OPTFLAGS=-O3
|
||||
PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig
|
||||
MACOSX_DEPLOYMENT_TARGET=11
|
||||
makeFlags='CONFIG=clang'
|
||||
PATH="$PWD/bison/src:$PATH"
|
||||
CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh
|
||||
CIBW_TEST_COMMAND: python3 {project}/tests/pyosys/run_tests.py
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: python-wheels-${{ matrix.os.runner }}
|
||||
path: ./wheelhouse/*.whl
|
||||
upload_wheels:
|
||||
name: Upload Wheels
|
||||
if: (github.repository == 'YosysHQ/Yosys') && (github.event_name == 'workflow_dispatch')
|
||||
if: (github.repository == 'YosysHQ/yosys') && (github.event_name == 'workflow_dispatch')
|
||||
runs-on: ubuntu-latest
|
||||
# Specifying a GitHub environment is optional, but strongly encouraged
|
||||
environment: pypi
|
||||
|
|
@ -123,7 +117,7 @@ jobs:
|
|||
id-token: write
|
||||
needs: build_wheels
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: "."
|
||||
pattern: python-wheels-*
|
||||
|
|
|
|||
52
.github/workflows/wheels/_run_cibw_linux.py
vendored
52
.github/workflows/wheels/_run_cibw_linux.py
vendored
|
|
@ -1,52 +0,0 @@
|
|||
#!/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
|
||||
from pathlib import Path
|
||||
|
||||
__yosys_root__ = Path(__file__).absolute().parents[3]
|
||||
|
||||
for source in ["ffi", "bison"]:
|
||||
if not (__yosys_root__ / source).is_dir():
|
||||
print(
|
||||
"You need to download ffi and bison in a similar manner to wheels.yml first."
|
||||
)
|
||||
exit(-1)
|
||||
|
||||
with open(__yosys_root__ / ".github" / "workflows" / "wheels.yml") as f:
|
||||
workflow = yaml.safe_load(f)
|
||||
|
||||
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", platform.machine())
|
||||
subprocess.check_call(["cibuildwheel"], env=env)
|
||||
2
.github/workflows/wheels/cibw_before_all.sh
vendored
2
.github/workflows/wheels/cibw_before_all.sh
vendored
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
set -e -x
|
||||
|
||||
# Build-time dependencies
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
set -e
|
||||
set -x
|
||||
|
||||
# Don't use Python objects from previous compiles
|
||||
make clean-py
|
||||
|
||||
# DEBUG: show python3 and python3-config outputs
|
||||
if [ "$(uname)" != "Linux" ]; then
|
||||
# https://github.com/pypa/cibuildwheel/issues/2021
|
||||
|
|
|
|||
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -1,5 +1,7 @@
|
|||
## user config
|
||||
/Makefile.conf
|
||||
/Configuration.cmake
|
||||
/CMakeUserPresets.json
|
||||
|
||||
## homebrew
|
||||
/Brewfile.lock.json
|
||||
|
|
@ -49,7 +51,9 @@
|
|||
/tests/unit/objtest/
|
||||
/tests/ystests
|
||||
/build
|
||||
/build-*
|
||||
/result
|
||||
/result-*
|
||||
/dist
|
||||
|
||||
# pyosys
|
||||
|
|
@ -65,10 +69,10 @@
|
|||
/viz.js
|
||||
|
||||
# other
|
||||
/coverage.info
|
||||
/yosys.profdata
|
||||
/coverage
|
||||
/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
|
||||
|
|
@ -86,3 +90,5 @@ __pycache__
|
|||
/qtcreator.creator
|
||||
/qtcreator.creator.user
|
||||
/compile_commands.json
|
||||
/.direnv
|
||||
/.envrc
|
||||
|
|
|
|||
3
Brewfile
3
Brewfile
|
|
@ -6,10 +6,11 @@ brew "git"
|
|||
brew "graphviz"
|
||||
brew "pkg-config"
|
||||
brew "python3"
|
||||
brew "tcl-tk"
|
||||
brew "uv"
|
||||
brew "xdot"
|
||||
brew "bash"
|
||||
brew "llvm@20"
|
||||
brew "llvm"
|
||||
brew "lld"
|
||||
brew "googletest"
|
||||
|
||||
|
|
|
|||
58
CHANGELOG
58
CHANGELOG
|
|
@ -2,9 +2,65 @@
|
|||
List of major changes and improvements between releases
|
||||
=======================================================
|
||||
|
||||
Yosys 0.62 .. Yosys 0.63-dev
|
||||
Yosys 0.66 .. Yosys 0.67-dev
|
||||
--------------------------
|
||||
|
||||
Yosys 0.65 .. Yosys 0.66
|
||||
--------------------------
|
||||
* Various
|
||||
- C++ compiler with C++20 support is required.
|
||||
- Please be aware that next release will also
|
||||
migrate to CMake build system.
|
||||
|
||||
* New commands and options
|
||||
- Added "lattice_dsp_nexus" pass for Lattice Nexus
|
||||
DSP inference.
|
||||
- Added "-scopename" option to "synth_gatemate" pass
|
||||
that is propagated to "flatten".
|
||||
|
||||
Yosys 0.64 .. Yosys 0.65
|
||||
--------------------------
|
||||
* New commands and options
|
||||
- Added "arith_tree" pass to convert add/sub/macc chains
|
||||
to carry-save adder trees.
|
||||
- Removed "-force" option from "share" pass.
|
||||
|
||||
* Various
|
||||
- read_verilog: support positional assignment patterns
|
||||
for unpacked arrays.
|
||||
|
||||
Yosys 0.63 .. Yosys 0.64
|
||||
--------------------------
|
||||
* New commands and options
|
||||
- Added "synth_analogdevices" pass to support synthesis
|
||||
for Analog Devices FPGAs.
|
||||
|
||||
* Various
|
||||
- Removed rarely-used options from ABC/ABC9.
|
||||
- Removed "-S" option from "abc" pass.
|
||||
- Removed "-fast" option from "abc9" and "abc9_exe".
|
||||
- Calls to "abc -g AND -fast" to map logic to
|
||||
AND-Inverter Graph form should be replaced with
|
||||
"aigmap".
|
||||
- The above change was made to SBY, so we recommend
|
||||
updating it.
|
||||
- Added hardware latch support for Gowin FPGAs.
|
||||
|
||||
Yosys 0.62 .. Yosys 0.63
|
||||
--------------------------
|
||||
* Various
|
||||
- Added DSP inference for Gowin GW1N and GW2A.
|
||||
- Added support for subtract in preadder for Xilinx arch.
|
||||
- Added infrastructure to run a sat solver as a command.
|
||||
|
||||
* New commands and options
|
||||
- Added "-ignore-unknown-cells" option to "equiv_induct"
|
||||
and "equiv_simple" pass.
|
||||
- Added "-force-params" option to "memory_libmap" pass.
|
||||
- Added "-select-solver" option to "sat" pass.
|
||||
- Added "-default_params" option to "write_verilog" pass.
|
||||
- Added "-nodsp" option to "synth_gowin" pass.
|
||||
|
||||
Yosys 0.61 .. Yosys 0.62
|
||||
--------------------------
|
||||
* Various
|
||||
|
|
|
|||
577
CMakeLists.txt
Normal file
577
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,577 @@
|
|||
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
set(rm "rm -rf")
|
||||
if (WIN32)
|
||||
set(rm "del /s /q")
|
||||
endif()
|
||||
message(FATAL_ERROR
|
||||
"In-tree builds are not supported. Instead, run:\n"
|
||||
"${rm} CMakeCache.txt CMakeFiles ; cmake -B build <options>"
|
||||
)
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
project(yosys LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(CMakeDependentOption)
|
||||
include(FeatureSummary)
|
||||
include(CheckPIESupported)
|
||||
|
||||
include(Condition)
|
||||
include(CheckLibcFeatures)
|
||||
include(PkgConfig)
|
||||
include(PmgenCommand)
|
||||
include(YosysVersion)
|
||||
include(YosysInstallDirs)
|
||||
include(YosysConfigScript)
|
||||
include(YosysComponent)
|
||||
include(YosysLinkTarget)
|
||||
include(YosysAbc)
|
||||
include(YosysAbcSubmodule)
|
||||
include(YosysVerific)
|
||||
|
||||
# Build options.
|
||||
set(YOSYS_COMPILER_LAUNCHER "" CACHE STRING "Compiler launcher (ccache, sccache)")
|
||||
option(YOSYS_ENABLE_COVERAGE "Enable code coverage" OFF)
|
||||
option(YOSYS_ENABLE_PROFILING "Enable instruction profiling" OFF)
|
||||
|
||||
set(YOSYS_PROGRAM_PREFIX "" CACHE STRING "Name prefix for programs, libraries, and data")
|
||||
set(YOSYS_COMPONENTS "everything" CACHE STRING "List of components to build (use pass names)")
|
||||
option(BUILD_SHARED_LIBS "Build libyosys as a shared library" ON)
|
||||
|
||||
option(YOSYS_DISABLE_THREADS "Disable threading" OFF)
|
||||
set(YOSYS_ABC_EXECUTABLE "" CACHE FILEPATH
|
||||
"Path to the ABC executable (empty for vendored, 'INTEGRATED-NOTFOUND' for in-process)")
|
||||
option(YOSYS_WITHOUT_ABC "Disable ABC support (not recommended)" OFF)
|
||||
option(YOSYS_WITHOUT_ZLIB "Disable zlib integration" OFF)
|
||||
option(YOSYS_WITHOUT_LIBFFI "Disable libffi integration" OFF)
|
||||
option(YOSYS_WITHOUT_READLINE "Disable readline integration" OFF)
|
||||
option(YOSYS_WITHOUT_EDITLINE "Disable editline integration" OFF)
|
||||
option(YOSYS_WITHOUT_TCL "Disable Tcl integration" OFF)
|
||||
option(YOSYS_WITH_PYTHON "Enable Python integration" OFF)
|
||||
|
||||
set(YOSYS_VERIFIC_DIR "" CACHE FILEPATH "Path to the Verific source code (empty to disable)")
|
||||
set(YOSYS_VERIFIC_COMPONENTS "" CACHE STRING
|
||||
"List of Verific components to link (empty for autodetect)")
|
||||
set(YOSYS_VERIFIC_FEATURES "" CACHE STRING
|
||||
"List of Yosys Verific frontend features to enable (empty for autodetect)")
|
||||
|
||||
option(YOSYS_INSTALL_DRIVER "Install Yosys executable" ON)
|
||||
option(YOSYS_INSTALL_LIBRARY "Install libyosys library" OFF)
|
||||
cmake_dependent_option(YOSYS_INSTALL_PYTHON "Install Python extension module" OFF
|
||||
YOSYS_WITH_PYTHON OFF)
|
||||
set(YOSYS_INSTALL_PYTHON_SITEDIR "" CACHE STRING "Path to Python package installation directory")
|
||||
|
||||
# This option is something of a hack to make Python wheels buildable in an environment that has
|
||||
# the `Development.Module` component, but not `Development.Embed` (e.g. cibuildwheel). It is only
|
||||
# present to be used in the wheel build and is not supported otherwise.
|
||||
cmake_dependent_option(YOSYS_BUILD_PYTHON_ONLY "Build only Pyosys components" ON
|
||||
"NOT (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY) AND YOSYS_INSTALL_PYTHON" OFF)
|
||||
mark_as_advanced(YOSYS_BUILD_PYTHON_ONLY)
|
||||
|
||||
# Configure compiler.
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
|
||||
|
||||
if (YOSYS_COMPILER_LAUNCHER)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER "${YOSYS_COMPILER_LAUNCHER}")
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER "${YOSYS_COMPILER_LAUNCHER}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
check_pie_supported() # opportunistically enable PIE
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -ggdb")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -ggdb")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
|
||||
set(CMAKE_CXX_FLAGS_SANITIZE "-O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
||||
if ("${SANITIZE}" MATCHES "memory")
|
||||
set(CMAKE_CXX_FLAGS_SANITIZE "${CMAKE_CXX_FLAGS_SANITIZE} -fsanitize-memory-track-origins")
|
||||
endif()
|
||||
set(no_abc_options
|
||||
"$<$<AND:$<NOT:$<BOOL:$<TARGET_PROPERTY:YOSYS_IS_ABC>>>,$<CONFIG:Sanitize>>:-fsanitize=${SANITIZE}>"
|
||||
"$<$<NOT:$<BOOL:$<TARGET_PROPERTY:YOSYS_IS_ABC>>>:-Wall;-Wextra;-Werror=unused>"
|
||||
)
|
||||
add_compile_options("${no_abc_options}")
|
||||
add_link_options("${no_abc_options}")
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/Od /DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/O2")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/O2 /DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os")
|
||||
add_compile_options(/Zc:__cplusplus)
|
||||
add_compile_definitions(
|
||||
_CRT_NONSTDC_NO_DEPRECATE
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
)
|
||||
else()
|
||||
# We have to do this because CMake adds `-DNDEBUG` in release builds by default, and there's
|
||||
# no particularly good way to prevent this without also erasing optimization flags.
|
||||
# If you see this message, reproduce the block above with the flags supported by your compiler.
|
||||
message(FATAL_ERROR "${CMAKE_CXX_COMPILER_ID} compiler is not supported")
|
||||
endif()
|
||||
|
||||
if (YOSYS_ENABLE_COVERAGE)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
|
||||
else()
|
||||
message(FATAL_ERROR "Code coverage is not supported on ${CMAKE_CXX_COMPILER_ID} compiler")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (YOSYS_ENABLE_PROFILING)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
|
||||
else()
|
||||
message(FATAL_ERROR "Instruction profiling is not supported on ${CMAKE_CXX_COMPILER_ID} compiler")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_C_COMPILER_ID STREQUAL CMAKE_CXX_COMPILER_ID)
|
||||
message(FATAL_ERROR "C and C++ compilers must be provided by the same vendor")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
|
||||
set(CMAKE_C_FLAGS_SANITIZE "${CMAKE_CXX_FLAGS_SANITIZE}")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "WASI")
|
||||
add_compile_options(
|
||||
-fwasm-exceptions -mllvm -wasm-use-legacy-eh=false
|
||||
-D_WASI_EMULATED_PROCESS_CLOCKS
|
||||
)
|
||||
add_link_options(
|
||||
-fwasm-exceptions -mllvm -wasm-use-legacy-eh=false -lunwind
|
||||
-lwasi-emulated-process-clocks
|
||||
-Wl,--stack-first,-z,stack-size=8388608
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "16.0.0")
|
||||
# GCC 15.2 sometimes refuses to construct an import directory for yosys.exe/libyosys.dll with:
|
||||
# .../ld.exe: error: export ordinal too large: 67035
|
||||
# The cause is unknown.
|
||||
message(WARNING "MinGW GCC is supported starting with version 16.0.0")
|
||||
endif()
|
||||
|
||||
# Required dependencies.
|
||||
find_package(FLEX)
|
||||
set_package_properties(FLEX PROPERTIES
|
||||
URL "https://github.com/westes/flex"
|
||||
DESCRIPTION "The Fast Lexical Analyzer"
|
||||
PURPOSE "Compiling the Verilog lexer"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(BISON)
|
||||
set_package_properties(BISON PROPERTIES
|
||||
URL "https://www.gnu.org/software/bison/"
|
||||
DESCRIPTION "The Yacc-compatible Parser Generator"
|
||||
PURPOSE "Compiling the Verilog parser"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
find_package(Python3 3.7 COMPONENTS Interpreter)
|
||||
set_package_properties(Python3 PROPERTIES
|
||||
URL "https://www.python.org/"
|
||||
DESCRIPTION "Dynamic programming language (Interpreter)"
|
||||
PURPOSE "Generating data files\n Running external SMT2 solvers"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
|
||||
# Optional dependencies.
|
||||
check_glob()
|
||||
check_system()
|
||||
check_popen()
|
||||
find_package(Threads QUIET)
|
||||
check_pthread_create()
|
||||
find_package(Dlfcn QUIET)
|
||||
|
||||
find_package(PkgConfig)
|
||||
set_package_properties(PkgConfig PROPERTIES
|
||||
URL "https://www.freedesktop.org/wiki/Software/pkg-config/"
|
||||
DESCRIPTION "Library metadata manager"
|
||||
PURPOSE "Discovering dependencies"
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
|
||||
pkg_config_import(zlib)
|
||||
set_package_properties(zlib PROPERTIES
|
||||
URL "https://github.com/madler/zlib"
|
||||
DESCRIPTION "A massively spiffy yet delicately unobtrusive compression library"
|
||||
PURPOSE "Handling Gzip and FST file formats"
|
||||
)
|
||||
|
||||
pkg_config_import(libffi)
|
||||
set_package_properties(libffi PROPERTIES
|
||||
URL "https://sourceware.org/libffi/"
|
||||
DESCRIPTION "A Portable Foreign Function Interface Library"
|
||||
PURPOSE "Implementing Verilog DPI-C"
|
||||
)
|
||||
|
||||
pkg_config_import(editline MODULES libedit)
|
||||
set_package_properties(editline PROPERTIES
|
||||
URL "https://www.thrysoee.dk/editline/"
|
||||
DESCRIPTION "Line editing and history library (BSD)"
|
||||
PURPOSE "Enhancing the command prompt"
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
|
||||
pkg_config_import(readline)
|
||||
set_package_properties(readline PROPERTIES
|
||||
URL "https://tiswww.case.edu/php/chet/readline/rltop.html"
|
||||
DESCRIPTION "Line editing and history library (GPL)"
|
||||
PURPOSE "Enhancing the command prompt"
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
|
||||
# See https://core.tcl-lang.org/tips/doc/trunk/tip/538.md
|
||||
pkg_config_import(tcl MODULES tcl)
|
||||
set_package_properties(tcl PROPERTIES
|
||||
URL "https://www.tcl-lang.org/"
|
||||
DESCRIPTION "Dynamic programming language"
|
||||
PURPOSE "Parsing SDC constraint files\n Binding Yosys API"
|
||||
)
|
||||
|
||||
if (tcl_FOUND)
|
||||
get_target_property(tcl_options PkgConfig::tcl INTERFACE_COMPILE_OPTIONS)
|
||||
if (tcl_options MATCHES "TCL_WITH_EXTERNAL_TOMMATH")
|
||||
pkg_config_import(libtommath)
|
||||
set_package_properties(libtommath PROPERTIES
|
||||
URL "https://www.libtom.net/LibTomMath/"
|
||||
DESCRIPTION "Multiple-precision integer library"
|
||||
PURPOSE "Required by this build of Tcl"
|
||||
TYPE REQUIRED
|
||||
)
|
||||
# Unfortunately the pkg-config file for Tcl includes libtommath as a private dependency,
|
||||
# while it should be public since it is exposed in the public API and necessary for its use.
|
||||
target_link_libraries(PkgConfig::tcl INTERFACE PkgConfig::libtommath)
|
||||
else()
|
||||
# Vendored within Tcl itself.
|
||||
set(libtommath_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (YOSYS_WITH_PYTHON)
|
||||
find_package(Python3Devel REQUIRED)
|
||||
set_property(GLOBAL PROPERTY _CMAKE_Python3Devel_REQUIRED_VERSION "== ${Python3_VERSION}")
|
||||
set_package_properties(Python3Devel PROPERTIES
|
||||
URL "https://www.python.org/"
|
||||
DESCRIPTION "Dynamic programming language (Embedding)"
|
||||
PURPOSE "Binding Yosys API"
|
||||
)
|
||||
|
||||
find_package(PyosysEnv REQUIRED)
|
||||
set_package_properties(PyosysEnv PROPERTIES
|
||||
DESCRIPTION "Pyosys wrapper generator environment"
|
||||
PURPOSE "Either 'uv' or 'pybind11>3,<4 cxxheaderparser'"
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(GTest)
|
||||
set_package_properties(GTest PROPERTIES
|
||||
URL "https://google.github.io/googletest/"
|
||||
DESCRIPTION "C++ testing and mocking framework by Google"
|
||||
PURPOSE "Running unit tests"
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
|
||||
# Configure features based on dependency availability.
|
||||
message(VERBOSE "Conditional features:")
|
||||
condition(YOSYS_ENABLE_GLOB HAVE_GLOB)
|
||||
condition(YOSYS_ENABLE_SPAWN HAVE_SYSTEM AND HAVE_POPEN)
|
||||
condition(YOSYS_ENABLE_THREADS Threads_FOUND AND HAVE_PTHREAD_CREATE AND NOT YOSYS_DISABLE_THREADS)
|
||||
condition(YOSYS_ENABLE_PLUGINS Dlfcn_FOUND)
|
||||
condition(YOSYS_ENABLE_ABC NOT YOSYS_WITHOUT_ABC)
|
||||
condition(YOSYS_ENABLE_ZLIB zlib_FOUND AND NOT YOSYS_WITHOUT_ZLIB)
|
||||
condition(YOSYS_ENABLE_LIBFFI Dlfcn_FOUND AND libffi_FOUND AND NOT YOSYS_WITHOUT_LIBFFI)
|
||||
condition(YOSYS_ENABLE_READLINE readline_FOUND AND NOT YOSYS_WITHOUT_READLINE)
|
||||
condition(YOSYS_ENABLE_EDITLINE editline_FOUND AND NOT YOSYS_WITHOUT_EDITLINE AND NOT YOSYS_ENABLE_READLINE)
|
||||
condition(YOSYS_ENABLE_TCL tcl_FOUND AND libtommath_FOUND AND NOT YOSYS_WITHOUT_TCL)
|
||||
condition(YOSYS_ENABLE_PYTHON Python3Devel_FOUND AND PyosysEnv_FOUND AND YOSYS_WITH_PYTHON)
|
||||
condition(YOSYS_ENABLE_VERIFIC YOSYS_VERIFIC_DIR AND zlib_FOUND)
|
||||
|
||||
# Describe dependencies and features
|
||||
# CMake 4.0 would let us use proper conditions, but that's too new for now.
|
||||
add_feature_info(have_glob YOSYS_ENABLE_GLOB "Glob expansion in filenames")
|
||||
add_feature_info(have_spawn YOSYS_ENABLE_SPAWN "Passes that invoke external tools")
|
||||
add_feature_info(have_threads YOSYS_ENABLE_THREADS "Multithreaded netlist operations")
|
||||
add_feature_info(have_plugins YOSYS_ENABLE_PLUGINS "Dynamically loadable binary plugins")
|
||||
add_feature_info(with_abc YOSYS_ENABLE_ABC "Production-quality logic synthesis flow")
|
||||
add_feature_info(with_zlib YOSYS_ENABLE_ZLIB "Transparent Gzip decompression and FST file format support")
|
||||
add_feature_info(with_libffi YOSYS_ENABLE_LIBFFI "Verilog DPI-C foreign function interface")
|
||||
add_feature_info(with_readline YOSYS_ENABLE_READLINE "Using readline for prompt editing and history")
|
||||
add_feature_info(with_editline YOSYS_ENABLE_EDITLINE "Using editline for prompt editing and history")
|
||||
add_feature_info(with_tcl YOSYS_ENABLE_TCL "Tcl scripting and SDC parsing")
|
||||
add_feature_info(with_python YOSYS_ENABLE_PYTHON "Python scripting and embedding")
|
||||
add_feature_info(with_verific YOSYS_ENABLE_VERIFIC "Verific frontend integration")
|
||||
message(STATUS "")
|
||||
feature_summary(WHAT PACKAGES_FOUND
|
||||
DEFAULT_DESCRIPTION)
|
||||
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND
|
||||
DEFAULT_DESCRIPTION QUIET_ON_EMPTY FATAL_ON_MISSING_REQUIRED_PACKAGES
|
||||
)
|
||||
feature_summary(WHAT PACKAGES_NOT_FOUND
|
||||
DEFAULT_DESCRIPTION QUIET_ON_EMPTY
|
||||
)
|
||||
feature_summary(WHAT ENABLED_FEATURES
|
||||
DEFAULT_DESCRIPTION QUIET_ON_EMPTY)
|
||||
feature_summary(WHAT DISABLED_FEATURES
|
||||
DEFAULT_DESCRIPTION QUIET_ON_EMPTY)
|
||||
|
||||
# Describe project version.
|
||||
yosys_extract_version()
|
||||
|
||||
# Describe ABC integration.
|
||||
if (YOSYS_ENABLE_ABC AND NOT YOSYS_ENABLE_SPAWN AND NOT YOSYS_ABC_EXECUTABLE STREQUAL "INTEGRATED-NOTFOUND")
|
||||
message(WARNING "ABC support on this platform forces -DYOSYS_ABC_EXECUTABLE=INTEGRATED-NOTFOUND")
|
||||
set(YOSYS_ABC_EXECUTABLE "INTEGRATED-NOTFOUND" CACHE FILEPATH "" FORCE)
|
||||
endif()
|
||||
|
||||
set(YOSYS_LINK_ABC 0)
|
||||
if (YOSYS_ENABLE_ABC)
|
||||
if (NOT YOSYS_ABC_EXECUTABLE AND NOT YOSYS_SKIP_ABC_SUBMODULE_CHECK)
|
||||
yosys_check_abc_submodule()
|
||||
endif()
|
||||
if (YOSYS_ABC_EXECUTABLE STREQUAL "INTEGRATED-NOTFOUND")
|
||||
set(YOSYS_LINK_ABC 1)
|
||||
message(STATUS "Building ABC: (integrated)")
|
||||
elseif (YOSYS_ABC_EXECUTABLE STREQUAL "")
|
||||
set(abc_filename ${YOSYS_PROGRAM_PREFIX}yosys-abc${CMAKE_EXECUTABLE_SUFFIX})
|
||||
message(STATUS "Building ABC: ${YOSYS_INSTALL_FULL_BINDIR}/${abc_filename}")
|
||||
else()
|
||||
message(STATUS "External ABC: ${YOSYS_ABC_EXECUTABLE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Ensure invalid dependencies fail at configuration time, not link time.
|
||||
set(CMAKE_LINK_LIBRARIES_ONLY_TARGETS ON)
|
||||
|
||||
# Pseudo-library that injects common compilation options into every Yosys component.
|
||||
add_library(yosys_common INTERFACE)
|
||||
target_compile_definitions(yosys_common INTERFACE
|
||||
_YOSYS_
|
||||
$<$<CONFIG:Debug,RelWithDebInfo>:DEBUG>
|
||||
)
|
||||
target_include_directories(yosys_common INTERFACE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
if (SANITIZE)
|
||||
target_compile_options(yosys_common INTERFACE
|
||||
${sanitize_options}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Two pseudo-components used for dependency tracking only.
|
||||
yosys_core(essentials BOOTSTRAP)
|
||||
yosys_core(everything BOOTSTRAP)
|
||||
|
||||
# All of the source code.
|
||||
add_subdirectory(libs)
|
||||
add_subdirectory(kernel)
|
||||
add_subdirectory(passes)
|
||||
add_subdirectory(frontends)
|
||||
add_subdirectory(backends)
|
||||
add_subdirectory(techlibs)
|
||||
if (YOSYS_ENABLE_PYTHON)
|
||||
add_subdirectory(pyosys)
|
||||
endif()
|
||||
|
||||
# ABC submodule.
|
||||
if (YOSYS_ENABLE_ABC AND NOT YOSYS_ABC_EXECUTABLE)
|
||||
set(YOSYS_ABC_INSTALL NO)
|
||||
if (YOSYS_ABC_EXECUTABLE STREQUAL "" AND (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY))
|
||||
set(YOSYS_ABC_INSTALL YES)
|
||||
endif()
|
||||
yosys_abc_target(libyosys-abc yosys-abc
|
||||
INSTALL_IF ${YOSYS_ABC_INSTALL}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Compute a transitive closure of enabled components.
|
||||
yosys_expand_components(library_components essentials ${YOSYS_COMPONENTS})
|
||||
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||
yosys_expand_components(driver_components driver ${YOSYS_COMPONENTS})
|
||||
endif()
|
||||
|
||||
# Main Yosys executable (compiler driver).
|
||||
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||
yosys_cxx_executable(yosys
|
||||
OUTPUT_NAME yosys
|
||||
INSTALL_IF ${YOSYS_INSTALL_DRIVER}
|
||||
)
|
||||
yosys_link_components(yosys PRIVATE ${driver_components})
|
||||
set_property(TARGET yosys PROPERTY ENABLE_EXPORTS ON)
|
||||
if (MINGW)
|
||||
target_link_options(yosys PRIVATE LINKER:--export-all-symbols)
|
||||
set_target_properties(yosys PROPERTIES
|
||||
# Final name: `yosys.exe.a` (linked to explicitly)
|
||||
IMPORT_PREFIX ""
|
||||
IMPORT_SUFFIX ".exe.a"
|
||||
)
|
||||
if (YOSYS_INSTALL_DRIVER)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/yosys.exe.a DESTINATION ${YOSYS_INSTALL_LIBDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_compile_options(yosys PRIVATE -fsanitize=undefined)
|
||||
endif()
|
||||
|
||||
# Yosys components as a library.
|
||||
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(libyosys_type SHARED)
|
||||
else()
|
||||
set(libyosys_type STATIC)
|
||||
endif()
|
||||
yosys_cxx_library(libyosys ${libyosys_type}
|
||||
OUTPUT_NAME libyosys
|
||||
INSTALL_IF ${YOSYS_INSTALL_LIBRARY}
|
||||
)
|
||||
yosys_link_components(libyosys PRIVATE ${library_components})
|
||||
add_library(Yosys::libyosys ALIAS libyosys)
|
||||
if (MINGW)
|
||||
set_target_properties(libyosys PROPERTIES
|
||||
# Final name: `libyosys.dll.a` (linked to via `-lyosys`)
|
||||
IMPORT_PREFIX ""
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Yosys data files (mainly headers and technological libraries).
|
||||
if (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY)
|
||||
yosys_install_component_data(${library_components} DESTINATION ${YOSYS_INSTALL_DATADIR})
|
||||
endif()
|
||||
|
||||
# Python binary extension (for using Yosys as a Python library).
|
||||
if (YOSYS_ENABLE_PYTHON)
|
||||
yosys_cxx_library(pyosys MODULE
|
||||
OUTPUT_NAME pyosys
|
||||
)
|
||||
yosys_link_components(pyosys PRIVATE ${library_components})
|
||||
set_target_properties(pyosys PROPERTIES EXCLUDE_FROM_ALL FALSE) # build but not install
|
||||
if (YOSYS_ENABLE_ABC AND YOSYS_ABC_EXECUTABLE STREQUAL "")
|
||||
add_dependencies(pyosys yosys-abc)
|
||||
endif()
|
||||
|
||||
if (YOSYS_INSTALL_PYTHON)
|
||||
string(REPLACE "-" "_" PYOSYS_MODULE_PREFIX "${YOSYS_PROGRAM_PREFIX}")
|
||||
if (YOSYS_INSTALL_PYTHON_SITEDIR STREQUAL "")
|
||||
set(YOSYS_INSTALL_PYTHON_SITEDIR ${Python3_SITEARCH})
|
||||
endif()
|
||||
set(pyosys_install_dir ${YOSYS_INSTALL_PYTHON_SITEDIR}/${PYOSYS_MODULE_PREFIX}pyosys)
|
||||
install(FILES pyosys/modinit.py
|
||||
RENAME __init__.py
|
||||
DESTINATION ${pyosys_install_dir}
|
||||
)
|
||||
install(FILES $<TARGET_FILE:pyosys>
|
||||
RENAME libyosys${CMAKE_SHARED_MODULE_SUFFIX}
|
||||
DESTINATION ${pyosys_install_dir}
|
||||
)
|
||||
if (YOSYS_ENABLE_ABC AND YOSYS_ABC_EXECUTABLE STREQUAL "")
|
||||
# If ABC is vendored it needs to be installed as a part of pyosys.
|
||||
install(TARGETS yosys-abc
|
||||
DESTINATION ${pyosys_install_dir}
|
||||
)
|
||||
endif()
|
||||
yosys_install_component_data(${library_components} DESTINATION ${pyosys_install_dir}/share)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Plugin build tool.
|
||||
yosys_config_script(BUILD)
|
||||
if (YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY)
|
||||
yosys_config_script(INSTALL)
|
||||
endif()
|
||||
|
||||
# Configuration for Makefile-based steps.
|
||||
# (The use of `${makefile_vars}` in `add_custom_{target,command}()` adds dependencies for
|
||||
# all of the targets specified via `$<TARGET_FILE:tgt>`.)
|
||||
set(makefile_vars
|
||||
BUILD_DIR=${CMAKE_BINARY_DIR}
|
||||
PROGRAM_PREFIX=${YOSYS_PROGRAM_PREFIX}
|
||||
ABC=$<IF:$<TARGET_EXISTS:yosys-abc>,$<TARGET_FILE:yosys-abc>,${YOSYS_ABC_EXECUTABLE}>
|
||||
YOSYS=$<TARGET_FILE:yosys>
|
||||
YOSYS_CONFIG=${CMAKE_BINARY_DIR}/${YOSYS_PROGRAM_PREFIX}yosys-config
|
||||
YOSYS_FILTERLIB=$<$<TARGET_EXISTS:yosys-filterlib>:$<TARGET_FILE:yosys-filterlib>>
|
||||
YOSYS_SMTBMC=${CMAKE_BINARY_DIR}/${YOSYS_PROGRAM_PREFIX}yosys-smtbmc
|
||||
YOSYS_WITNESS=${CMAKE_BINARY_DIR}/${YOSYS_PROGRAM_PREFIX}yosys-witness
|
||||
)
|
||||
set(makefile_depends
|
||||
# abc is implied via $<TARGET_FILE>
|
||||
# yosys is implied via $<TARGET_FILE>
|
||||
# yosys-filterlib is implied via $<TARGET_FILE>
|
||||
$<$<TARGET_EXISTS:yosys-smtbmc>:yosys-smtbmc>
|
||||
$<$<TARGET_EXISTS:yosys-witness>:yosys-witness>
|
||||
)
|
||||
|
||||
if (NOT YOSYS_BUILD_PYTHON_ONLY)
|
||||
# Tests.
|
||||
add_subdirectory(tests/unit)
|
||||
|
||||
add_custom_target(test-unit
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --test-dir tests/unit --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(test-vanilla
|
||||
COMMAND make vanilla-test ${makefile_vars}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests
|
||||
DEPENDS ${makefile_depends}
|
||||
)
|
||||
|
||||
add_custom_target(test
|
||||
DEPENDS test-unit test-vanilla
|
||||
)
|
||||
|
||||
# Docs.
|
||||
add_custom_target(docs-prepare
|
||||
COMMAND make gen ${makefile_vars}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
|
||||
DEPENDS ${makefile_depends}
|
||||
)
|
||||
foreach (format html latexpdf)
|
||||
add_custom_target(docs-${format}
|
||||
COMMAND make ${format}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
|
||||
DEPENDS docs-prepare
|
||||
)
|
||||
endforeach()
|
||||
add_custom_target(test-docs
|
||||
COMMAND make test ${makefile_vars}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs
|
||||
DEPENDS ${makefile_depends}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Utilities.
|
||||
add_custom_target(print-version
|
||||
COMMAND ${CMAKE_COMMAND} -E echo ${YOSYS_VERSION}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
yosys_expand_components(all_components everything QUIET)
|
||||
list(TRANSFORM all_components PREPEND "COMMAND;${CMAKE_COMMAND};-E;echo;" OUTPUT_VARIABLE echo_all_components)
|
||||
add_custom_target(print-yosys-components
|
||||
${echo_all_components}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
math(EXPR YOSYS_VERSION_MINOR_next "${YOSYS_VERSION_MINOR} + 1")
|
||||
add_custom_target(increment-minor-version
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"set(YOSYS_VERSION_MAJOR ${YOSYS_VERSION_MAJOR})"
|
||||
> ${CMAKE_SOURCE_DIR}/cmake/YosysVersionData.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"set(YOSYS_VERSION_MINOR ${YOSYS_VERSION_MINOR_next})"
|
||||
>> ${CMAKE_SOURCE_DIR}/cmake/YosysVersionData.cmake
|
||||
VERBATIM
|
||||
)
|
||||
|
|
@ -5,59 +5,11 @@ first time contributing to an open source project, please take a look at the
|
|||
following guide about the basics:
|
||||
https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project.
|
||||
|
||||
## Asking questions
|
||||
Check out our [Contributing guidelines](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html) to learn the best ways to
|
||||
|
||||
If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/).
|
||||
The Discourse is also a great place to ask questions about developing or
|
||||
contributing to Yosys.
|
||||
+ get help
|
||||
+ report bugs
|
||||
+ contribute code
|
||||
+ review code
|
||||
|
||||
We have open [dev 'jour fixe' (JF) meetings](https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing) 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.
|
||||
|
||||
## 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.
|
||||
|
||||
### Bug reports
|
||||
|
||||
Learn more [here](https://yosyshq.readthedocs.io/projects/yosys/en/latest/yosys_internals/extending_yosys/contributing.html#reporting-bugs) about how to report bugs. We fix well-reported bugs the fastest.
|
||||
|
||||
## Contributing code
|
||||
|
||||
If you're adding complex functionality, or modifying core parts of Yosys,
|
||||
we highly recommend discussing your motivation and approach
|
||||
ahead of time on the [Discourse forum](https://yosyshq.discourse.group/).
|
||||
|
||||
### Using pull requests
|
||||
|
||||
If you are working on something to add to Yosys, or fix something that isn't
|
||||
working quite right,
|
||||
make a [pull request (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 above to find the best way to [ask us questions](#asking-questions).
|
||||
|
||||
### Continuous integration
|
||||
|
||||
[Continuous Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools
|
||||
automatically compile Yosys and run it with the full suite of tests.
|
||||
If you're a first time contributor, a maintainer has to trigger a run for you.
|
||||
We test on various platforms, compilers. Sanitizer builds are only tested
|
||||
on the main branch.
|
||||
|
||||
### 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 beginning 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.
|
||||
|
||||
|
||||
### Coding style
|
||||
|
||||
Learn more [here](https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html).
|
||||
If you're reading this file offline and don't have internet access, you can [read the contributing.rst file locally](docs/source/yosys_internals/extending_yosys/contributing.rst).
|
||||
|
|
|
|||
112
README.md
112
README.md
|
|
@ -75,10 +75,11 @@ or
|
|||
$ cd yosys
|
||||
$ git submodule update --init --recursive
|
||||
|
||||
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.
|
||||
TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
|
||||
Xdot (graphviz) is used by the ``show`` command in yosys to display schematics.
|
||||
A C++ compiler with C++20 support is required as well as some standard tools
|
||||
such as GNU Flex, GNU Bison (>=3.8), CMake (>=3.27), Make (or other CMake
|
||||
generator such as Ninja), and Python (>=3.11). Some additional tools: readline,
|
||||
libffi, Tcl and zlib; will be used if available but are optional. Graphviz and
|
||||
Xdot are used by the `show` command to display schematics.
|
||||
|
||||
For example on Ubuntu Linux 22.04 LTS the following commands will install all
|
||||
prerequisites for building yosys:
|
||||
|
|
@ -86,45 +87,66 @@ prerequisites for building yosys:
|
|||
$ sudo apt-get install gawk git make python3 lld bison clang flex \
|
||||
libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev \
|
||||
graphviz xdot
|
||||
$ curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
The environment variable `CXX` can be used to control the C++ compiler used, or
|
||||
run one of the following to override it:
|
||||
**NOTE**: By default, Ubuntu 22.04 LTS is limited to CMake 3.22 via `apt`. To
|
||||
install a newer version and meet the minimum required for building Yosys, use
|
||||
`sudo snap install cmake --classic`.
|
||||
|
||||
$ make config-clang
|
||||
$ make config-gcc
|
||||
CMake is used for build configuration, and requires a separate build directory:
|
||||
|
||||
The Makefile has many variables influencing the build process. These can be
|
||||
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:
|
||||
$ cmake -B build .
|
||||
|
||||
$ make CXX=$CXX
|
||||
Once generated, available build variables can be inspected and modified with
|
||||
`ccmake` or opening the generated `build/CMakeCache.txt` file:
|
||||
|
||||
For other compilers and build configurations it might be necessary to make some
|
||||
changes to the config section of the Makefile. It's also an alternative way to
|
||||
set the make variables mentioned above.
|
||||
$ ccmake build #..or..
|
||||
$ vi build/CMakeCache.txt
|
||||
|
||||
$ vi Makefile # ..or..
|
||||
$ vi Makefile.conf
|
||||
When setting one-off variables, CMake provides the `-D <var>=<value>` command
|
||||
line option. For example, disabling zlib support:
|
||||
|
||||
To build Yosys simply type 'make' in this directory.
|
||||
$ cmake -B build . -DYOSYS_WITHOUT_ZLIB=ON
|
||||
|
||||
$ make
|
||||
$ sudo make install
|
||||
For a more persistent configuration, we recommend creating and using a
|
||||
`CMakeUserPresets.json` file in the root `yosys` directory. Below is an example
|
||||
file which enables ccache and sets the default compiler to clang when calling
|
||||
`cmake --preset clang`:
|
||||
|
||||
Tests are located in the tests subdirectory and can be executed using the test
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"binaryDir": "build",
|
||||
"generator": "Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"YOSYS_COMPILER_LAUNCHER": "ccache"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Once generated, the build system can be run as follows:
|
||||
|
||||
$ cmake --build build #..or..
|
||||
$ cd build
|
||||
$ cmake --build .
|
||||
|
||||
To quickly install Yosys with the default settings:
|
||||
|
||||
$ cmake -B build . -DCMAKE_BUILD_TYPE=Release
|
||||
$ cmake --build build --config Release --parallel $(nproc)
|
||||
$ sudo cmake --install build --strip
|
||||
|
||||
Tests are located in the tests subdirectory and can be executed using the `test`
|
||||
target. Note that you need gawk, a recent version of iverilog, and gtest.
|
||||
Execute tests via:
|
||||
|
||||
$ make test
|
||||
|
||||
To use a separate (out-of-tree) build directory, provide a path to the Makefile.
|
||||
|
||||
$ mkdir build; cd build
|
||||
$ make -f ../Makefile
|
||||
|
||||
Out-of-tree builds require a clean source tree.
|
||||
$ cmake --build build --target test --parallel $(nproc)
|
||||
|
||||
|
||||
Getting Started
|
||||
|
|
@ -134,7 +156,7 @@ Yosys can be used with the interactive command shell, with
|
|||
synthesis scripts or with command line arguments. Let's perform
|
||||
a simple synthesis job using the interactive command shell:
|
||||
|
||||
$ ./yosys
|
||||
$ ./build/yosys
|
||||
yosys>
|
||||
|
||||
the command ``help`` can be used to print a list of all available
|
||||
|
|
@ -256,7 +278,7 @@ following are used for building the website:
|
|||
|
||||
Or for MacOS, using homebrew:
|
||||
|
||||
$ brew install pdf2svg libfaketime
|
||||
$ brew install pdf2svg libfaketime
|
||||
|
||||
PDFLaTeX, included with most LaTeX distributions, is also needed during the
|
||||
build process for the website. Or, run the following:
|
||||
|
|
@ -265,24 +287,20 @@ build process for the website. Or, run the following:
|
|||
|
||||
Or for MacOS, using homebrew:
|
||||
|
||||
$ brew install basictex
|
||||
$ sudo tlmgr update --self
|
||||
$ sudo tlmgr install collection-latexextra latexmk tex-gyre
|
||||
$ brew install basictex
|
||||
$ sudo tlmgr update --self
|
||||
$ sudo tlmgr install collection-latexextra latexmk tex-gyre
|
||||
|
||||
The Python package, Sphinx, is needed along with those listed in
|
||||
`docs/source/requirements.txt`:
|
||||
|
||||
$ pip install -U sphinx -r docs/source/requirements.txt
|
||||
|
||||
From the root of the repository, run `make docs`. This will build/rebuild yosys
|
||||
as necessary before generating the website documentation from the yosys help
|
||||
commands. To build for pdf instead of html, call
|
||||
`make docs DOC_TARGET=latexpdf`.
|
||||
DOCS (e.g.)
|
||||
|
||||
$ cmake --build build --target docs-html --parallel
|
||||
|
||||
This will build/rebuild yosys as necessary before generating the website
|
||||
documentation from the yosys help commands. To build for pdf instead of html,
|
||||
use the `docs-latexpdf` target.
|
||||
|
||||
It is recommended to use the `ENABLE_HELP_SOURCE` make option for Yosys builds
|
||||
that will be used to build the documentation. This option enables source
|
||||
location tracking for passes and improves the command reference through grouping
|
||||
related commands and allowing for the documentation to link to the corresponding
|
||||
source files. Without this, a warning will be raised during the Sphinx build
|
||||
about `Found commands assigned to group unknown` and `make docs` is configured
|
||||
to fail on warnings by default.
|
||||
|
|
|
|||
2
abc
2
abc
|
|
@ -1 +1 @@
|
|||
Subproject commit 223d685c5d8e22b90362524bd7189720a6621aeb
|
||||
Subproject commit 72d015f6567281d84bd4fe6328ce4b7233b596ca
|
||||
18
backends/CMakeLists.txt
Normal file
18
backends/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
add_subdirectory(aiger)
|
||||
add_subdirectory(aiger2)
|
||||
add_subdirectory(blif)
|
||||
add_subdirectory(btor)
|
||||
add_subdirectory(cxxrtl)
|
||||
add_subdirectory(edif)
|
||||
add_subdirectory(firrtl)
|
||||
add_subdirectory(functional)
|
||||
add_subdirectory(intersynth)
|
||||
add_subdirectory(jny)
|
||||
add_subdirectory(json)
|
||||
add_subdirectory(rtlil)
|
||||
add_subdirectory(simplec)
|
||||
add_subdirectory(smt2)
|
||||
add_subdirectory(smv)
|
||||
add_subdirectory(spice)
|
||||
add_subdirectory(table)
|
||||
add_subdirectory(verilog)
|
||||
8
backends/aiger/CMakeLists.txt
Normal file
8
backends/aiger/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
yosys_backend(aiger
|
||||
aiger.cc
|
||||
REQUIRES
|
||||
json11
|
||||
)
|
||||
yosys_backend(xaiger
|
||||
xaiger.cc
|
||||
)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
OBJS += backends/aiger/aiger.o
|
||||
OBJS += backends/aiger/xaiger.o
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ struct AigerWriter
|
|||
if (cell->type == ID($scopeinfo))
|
||||
continue;
|
||||
|
||||
log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
||||
log_error("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell);
|
||||
}
|
||||
|
||||
for (auto bit : unused_bits)
|
||||
|
|
@ -349,10 +349,10 @@ struct AigerWriter
|
|||
if (!undriven_bits.empty()) {
|
||||
undriven_bits.sort();
|
||||
for (auto bit : undriven_bits) {
|
||||
log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
|
||||
log_warning("Treating undriven bit %s.%s like $anyseq.\n", module, log_signal(bit));
|
||||
input_bits.insert(bit);
|
||||
}
|
||||
log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module));
|
||||
log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), module);
|
||||
}
|
||||
|
||||
init_map.sort();
|
||||
|
|
@ -635,35 +635,35 @@ struct AigerWriter
|
|||
int a = aig_map.at(sig[i]);
|
||||
log_assert((a & 1) == 0);
|
||||
if (GetSize(wire) != 1)
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i));
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", wire, i));
|
||||
else
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire)));
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", wire));
|
||||
}
|
||||
|
||||
if (wire->port_output) {
|
||||
int o = ordered_outputs.at(SigSpec(wire, i));
|
||||
if (GetSize(wire) != 1)
|
||||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i));
|
||||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", wire, i));
|
||||
else
|
||||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
|
||||
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", wire));
|
||||
}
|
||||
|
||||
if (init_inputs.count(sig[i])) {
|
||||
int a = init_inputs.at(sig[i]);
|
||||
log_assert((a & 1) == 0);
|
||||
if (GetSize(wire) != 1)
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", wire, i));
|
||||
else
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
|
||||
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", wire));
|
||||
}
|
||||
|
||||
if (ordered_latches.count(sig[i])) {
|
||||
int l = ordered_latches.at(sig[i]);
|
||||
const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
|
||||
if (GetSize(wire) != 1)
|
||||
symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i));
|
||||
symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, wire, i));
|
||||
else
|
||||
symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire)));
|
||||
symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, wire));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -705,30 +705,30 @@ struct AigerWriter
|
|||
int index = no_startoffset ? i : (wire->start_offset+i);
|
||||
|
||||
if (verbose_map)
|
||||
wire_lines[a] += stringf("wire %d %d %s\n", a, index, log_id(wire));
|
||||
wire_lines[a] += stringf("wire %d %d %s\n", a, index, wire);
|
||||
|
||||
if (wire->port_input) {
|
||||
log_assert((a & 1) == 0);
|
||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, log_id(wire));
|
||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, index, wire);
|
||||
}
|
||||
|
||||
if (wire->port_output) {
|
||||
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, wire);
|
||||
}
|
||||
|
||||
if (init_inputs.count(sig[i])) {
|
||||
int a = init_inputs.at(sig[i]);
|
||||
log_assert((a & 1) == 0);
|
||||
init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, log_id(wire));
|
||||
init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, index, wire);
|
||||
}
|
||||
|
||||
if (ordered_latches.count(sig[i])) {
|
||||
int l = ordered_latches.at(sig[i]);
|
||||
if (zinit_mode && (aig_latchinit.at(l) == 1))
|
||||
latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, log_id(wire));
|
||||
latch_lines[l] += stringf("invlatch %d %d %s\n", l, index, wire);
|
||||
else
|
||||
latch_lines[l] += stringf("latch %d %d %s\n", l, index, log_id(wire));
|
||||
latch_lines[l] += stringf("latch %d %d %s\n", l, index, wire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -930,7 +930,9 @@ struct AigerBackend : public Backend {
|
|||
log(" make indexes zero based, enable using map files with smt solvers.\n");
|
||||
log("\n");
|
||||
log(" -ywmap <filename>\n");
|
||||
log(" write a map file for conversion to and from yosys witness traces.\n");
|
||||
log(" write a map file for conversion to and from yosys witness traces,\n");
|
||||
log(" also allows for mapping AIGER bad-state properties and invariant\n");
|
||||
log(" constraints back to individual formal properties by name.\n");
|
||||
log("\n");
|
||||
log(" -I, -O, -B, -L\n");
|
||||
log(" If the design contains no input/output/assert/flip-flop then create one\n");
|
||||
|
|
@ -1025,12 +1027,12 @@ struct AigerBackend : public Backend {
|
|||
log_error("Can't find top module in current design!\n");
|
||||
|
||||
if (!design->selected_whole_module(top_module))
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module));
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", top_module);
|
||||
|
||||
if (!top_module->processes.empty())
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", log_id(top_module));
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in AIGER backend!\n", top_module);
|
||||
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", top_module);
|
||||
|
||||
AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode);
|
||||
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ struct XAigerWriter
|
|||
if (ys_debug(1)) {
|
||||
static pool<std::pair<IdString,TimingInfo::NameBit>> seen;
|
||||
if (seen.emplace(inst_module->name, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n",
|
||||
log_id(cell->type), log_id(i.first.name), offset, d);
|
||||
cell->type.unescape(), i.first.name.unescape(), offset, d);
|
||||
}
|
||||
#endif
|
||||
arrival_times[rhs[offset]] = d;
|
||||
|
|
@ -285,7 +285,7 @@ struct XAigerWriter
|
|||
auto is_input = (port_wire && port_wire->port_input) || !cell_known || cell->input(c.first);
|
||||
auto is_output = (port_wire && port_wire->port_output) || !cell_known || cell->output(c.first);
|
||||
if (!is_input && !is_output)
|
||||
log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", log_id(c.first), log_id(cell), log_id(cell->type));
|
||||
log_error("Connection '%s' on cell '%s' (type '%s') not recognised!\n", c.first.unescape(), cell, cell->type.unescape());
|
||||
|
||||
if (is_input)
|
||||
for (auto b : c.second) {
|
||||
|
|
@ -303,7 +303,7 @@ struct XAigerWriter
|
|||
}
|
||||
}
|
||||
|
||||
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
||||
//log_warning("Unsupported cell type: %s (%s)\n", cell->type.unescape(), cell);
|
||||
}
|
||||
|
||||
dict<IdString, std::vector<IdString>> box_ports;
|
||||
|
|
@ -325,12 +325,12 @@ struct XAigerWriter
|
|||
if (w->get_bool_attribute(ID::abc9_carry)) {
|
||||
if (w->port_input) {
|
||||
if (carry_in != IdString())
|
||||
log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(box_module));
|
||||
log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", box_module);
|
||||
carry_in = port_name;
|
||||
}
|
||||
if (w->port_output) {
|
||||
if (carry_out != IdString())
|
||||
log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", log_id(box_module));
|
||||
log_error("Module '%s' contains more than one 'abc9_carry' output port.\n", box_module);
|
||||
carry_out = port_name;
|
||||
}
|
||||
}
|
||||
|
|
@ -339,9 +339,9 @@ struct XAigerWriter
|
|||
}
|
||||
|
||||
if (carry_in != IdString() && carry_out == IdString())
|
||||
log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(box_module));
|
||||
log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", box_module);
|
||||
if (carry_in == IdString() && carry_out != IdString())
|
||||
log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(box_module));
|
||||
log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", box_module);
|
||||
if (carry_in != IdString()) {
|
||||
r.first->second.push_back(carry_in);
|
||||
r.first->second.push_back(carry_out);
|
||||
|
|
@ -612,7 +612,7 @@ struct XAigerWriter
|
|||
write_r_buffer(mergeability);
|
||||
|
||||
State init = init_map.at(q, State::Sx);
|
||||
log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init));
|
||||
log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", cell, cell->type.unescape(), log_signal(init));
|
||||
if (init == State::S1)
|
||||
write_s_buffer(1);
|
||||
else if (init == State::S0)
|
||||
|
|
@ -692,12 +692,12 @@ struct XAigerWriter
|
|||
if (input_bits.count(b)) {
|
||||
int a = aig_map.at(b);
|
||||
log_assert((a & 1) == 0);
|
||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, log_id(wire));
|
||||
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, wire->start_offset+i, wire);
|
||||
}
|
||||
|
||||
if (output_bits.count(b)) {
|
||||
int o = ordered_outputs.at(b);
|
||||
output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire));
|
||||
output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, wire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -709,7 +709,7 @@ struct XAigerWriter
|
|||
|
||||
int box_count = 0;
|
||||
for (auto cell : box_list)
|
||||
f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name));
|
||||
f << stringf("box %d %d %s\n", box_count++, 0, cell->name.unescape());
|
||||
|
||||
output_lines.sort();
|
||||
for (auto &it : output_lines)
|
||||
|
|
@ -774,12 +774,12 @@ struct XAigerBackend : public Backend {
|
|||
log_error("Can't find top module in current design!\n");
|
||||
|
||||
if (!design->selected_whole_module(top_module))
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(top_module));
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", top_module);
|
||||
|
||||
if (!top_module->processes.empty())
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", log_id(top_module));
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in XAIGER backend!\n", top_module);
|
||||
if (!top_module->memories.empty())
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", log_id(top_module));
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in XAIGER backend!\n", top_module);
|
||||
|
||||
XAigerWriter writer(top_module, dff_mode);
|
||||
writer.write_aiger(*f, ascii_mode);
|
||||
|
|
|
|||
5
backends/aiger2/CMakeLists.txt
Normal file
5
backends/aiger2/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
yosys_backend(aiger2
|
||||
aiger.cc
|
||||
PROVIDES
|
||||
write_xaiger2
|
||||
)
|
||||
|
|
@ -1 +0,0 @@
|
|||
OBJS += backends/aiger2/aiger.o
|
||||
|
|
@ -21,9 +21,12 @@
|
|||
// - gracefully handling inout ports (an error message probably)
|
||||
// - undriven wires
|
||||
// - zero-width operands
|
||||
// - decide how to unify this with cellaigs
|
||||
// - break up Index into something smaller
|
||||
// - (C++20) remove snprintf-into-std::ostream weirdness
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/rtlil.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
|
|
@ -45,8 +48,22 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
// TODO
|
||||
//#define ARITH_OPS ID($add), ID($sub), ID($neg)
|
||||
|
||||
#define KNOWN_OPS BITWISE_OPS, REDUCE_OPS, LOGIC_OPS, GATE_OPS, ID($pos), CMP_OPS, \
|
||||
ID($pmux), ID($bmux) /*, ARITH_OPS*/
|
||||
static constexpr auto known_ops = []() constexpr {
|
||||
StaticCellTypes::Categories::Category c{};
|
||||
for (auto id : {BITWISE_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {REDUCE_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {LOGIC_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {GATE_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {CMP_OPS})
|
||||
c.set_id(id);
|
||||
for (auto id : {ID($pos), ID($pmux), ID($bmux)})
|
||||
c.set_id(id);
|
||||
return c;
|
||||
}();
|
||||
|
||||
template<typename Writer, typename Lit, Lit CFALSE, Lit CTRUE>
|
||||
struct Index {
|
||||
|
|
@ -92,7 +109,7 @@ struct Index {
|
|||
int pos = index_wires(info, m);
|
||||
|
||||
for (auto cell : m->cells()) {
|
||||
if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
|
||||
if (known_ops(cell->type) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port)))
|
||||
continue;
|
||||
|
||||
Module *submodule = m->design->module(cell->type);
|
||||
|
|
@ -104,7 +121,7 @@ struct Index {
|
|||
pos += index_module(submodule);
|
||||
} else {
|
||||
if (allow_blackboxes) {
|
||||
info.found_blackboxes.insert(cell);
|
||||
info.found_blackboxes.insert(cell);
|
||||
} else {
|
||||
// Even if we don't allow blackboxes these might still be
|
||||
// present outside of any traversed input cones, so we
|
||||
|
|
@ -115,7 +132,7 @@ struct Index {
|
|||
continue;
|
||||
if (!submodule || submodule->get_blackbox_attribute())
|
||||
log_warning("Unsupported cell type: %s (%s in %s)\n",
|
||||
log_id(cell->type), log_id(cell), log_id(m));
|
||||
cell->type.unescape(), cell, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -163,6 +180,11 @@ struct Index {
|
|||
if (!strashing) {
|
||||
return (static_cast<Writer*>(this))->emit_gate(a, b);
|
||||
} else {
|
||||
// AigMaker::node2index
|
||||
|
||||
// In XAIGER, the ordering of inputs is used to distinguish between AND
|
||||
// and XOR gates. AND gates have their first input literal be larger
|
||||
// than their second, and vice-versa for XORs.
|
||||
if (a < b) std::swap(a, b);
|
||||
auto pair = std::make_pair(a, b);
|
||||
|
||||
|
|
@ -183,7 +205,9 @@ struct Index {
|
|||
|
||||
Lit OR(Lit a, Lit b)
|
||||
{
|
||||
return NOT(AND(NOT(a), NOT(b)));
|
||||
Lit not_a = NOT(a);
|
||||
Lit not_b = NOT(b);
|
||||
return NOT(AND(not_a, not_b));
|
||||
}
|
||||
|
||||
Lit MUX(Lit a, Lit b, Lit s)
|
||||
|
|
@ -197,17 +221,24 @@ struct Index {
|
|||
return b;
|
||||
}
|
||||
|
||||
return OR(AND(a, NOT(s)), AND(b, s));
|
||||
Lit not_s = NOT(s);
|
||||
Lit a_active = AND(a, not_s);
|
||||
Lit b_active = AND(b, s);
|
||||
return OR(a_active, b_active);
|
||||
}
|
||||
|
||||
Lit XOR(Lit a, Lit b)
|
||||
{
|
||||
return OR(AND(a, NOT(b)), AND(NOT(a), b));
|
||||
Lit not_a = NOT(a);
|
||||
Lit not_b = NOT(b);
|
||||
Lit a_and_not_b = AND(a, not_b);
|
||||
Lit not_a_and_b = AND(not_a, b);
|
||||
return OR(a_and_not_b, not_a_and_b);
|
||||
}
|
||||
|
||||
Lit XNOR(Lit a, Lit b)
|
||||
{
|
||||
return NOT(OR(AND(a, NOT(b)), AND(NOT(a), b)));
|
||||
return NOT(XOR(a, b));
|
||||
}
|
||||
|
||||
Lit CARRY(Lit a, Lit b, Lit c)
|
||||
|
|
@ -219,7 +250,10 @@ struct Index {
|
|||
return AND(a, b);
|
||||
}
|
||||
}
|
||||
return OR(AND(a, b), AND(c, OR(a, b)));
|
||||
Lit a_or_b = OR(a, b);
|
||||
Lit a_or_b_and_c = AND(c, a_or_b);
|
||||
Lit a_and_b = AND(a, b);
|
||||
return OR(a_and_b, a_or_b_and_c);
|
||||
}
|
||||
|
||||
Lit REDUCE(std::vector<Lit> lits, bool op_xor=false)
|
||||
|
|
@ -269,7 +303,7 @@ struct Index {
|
|||
} else if (cell->type.in(ID($lt), ID($le), ID($gt), ID($ge))) {
|
||||
if (cell->type.in(ID($gt), ID($ge)))
|
||||
std::swap(aport, bport);
|
||||
int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE;
|
||||
int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE;
|
||||
Lit a = Writer::EMPTY_LIT;
|
||||
Lit b = Writer::EMPTY_LIT;
|
||||
// TODO: this might not be the most economic structure; revisit at a later date
|
||||
|
|
@ -367,7 +401,7 @@ struct Index {
|
|||
} else if (cell->type.in(ID($xor), ID($_XOR_))) {
|
||||
return XOR(a, b);
|
||||
} else if (cell->type.in(ID($xnor), ID($_XNOR_))) {
|
||||
return NOT(XOR(a, b));
|
||||
return XNOR(a, b);
|
||||
} else if (cell->type.in(ID($_ANDNOT_))) {
|
||||
return AND(a, NOT(b));
|
||||
} else if (cell->type.in(ID($_ORNOT_))) {
|
||||
|
|
@ -387,7 +421,9 @@ struct Index {
|
|||
if (oport == ID::Y) {
|
||||
return XOR(ab, c);
|
||||
} else /* oport == ID::X */ {
|
||||
return OR(AND(a, b), AND(c, ab));
|
||||
Lit a_and_b = AND(a, b);
|
||||
Lit c_and_ab = AND(c, ab);
|
||||
return OR(a_and_b, c_and_ab);
|
||||
}
|
||||
} else if (cell->type.in(ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_))) {
|
||||
Lit c, d;
|
||||
|
|
@ -398,10 +434,15 @@ struct Index {
|
|||
else
|
||||
d = cell->type == ID($_AOI3_) ? CTRUE : CFALSE;
|
||||
|
||||
if (/* aoi */ cell->type.in(ID($_AOI3_), ID($_AOI4_)))
|
||||
return NOT(OR(AND(a, b), AND(c, d)));
|
||||
else
|
||||
return NOT(AND(OR(a, b), OR(c, d)));
|
||||
if (/* aoi */ cell->type.in(ID($_AOI3_), ID($_AOI4_))) {
|
||||
Lit a_and_b = AND(a, b);
|
||||
Lit c_and_d = AND(c, d);
|
||||
return NOT(OR(a_and_b, c_and_d));
|
||||
} else {
|
||||
Lit a_or_b = OR(a, b);
|
||||
Lit c_or_d = OR(c, d);
|
||||
return NOT(AND(a_or_b, c_or_d));
|
||||
}
|
||||
} else {
|
||||
log_abort();
|
||||
}
|
||||
|
|
@ -422,7 +463,11 @@ struct Index {
|
|||
sels.push_back(NOT(s));
|
||||
}
|
||||
|
||||
return OR(AND(REDUCE(sels), a), NOT(REDUCE(bar)));
|
||||
Lit reduce_sels = REDUCE(sels);
|
||||
Lit reduce_sels_and_a = AND(reduce_sels, a);
|
||||
Lit reduce_bar = NOT(REDUCE(bar));
|
||||
|
||||
return OR(reduce_sels_and_a, reduce_bar);
|
||||
} else if (cell->type == ID($bmux)) {
|
||||
SigSpec aport = cell->getPort(ID::A);
|
||||
SigSpec sport = cell->getPort(ID::S);
|
||||
|
|
@ -492,7 +537,7 @@ struct Index {
|
|||
Design *design = index.design;
|
||||
auto &minfo = leaf_minfo(index);
|
||||
if (!minfo.suboffsets.count(cell))
|
||||
log_error("Reached unsupport cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module));
|
||||
log_error("Reached unsupported cell %s (%s in %s)\n", cell->type.unescape(), cell, cell->module);
|
||||
Module *def = design->module(cell->type);
|
||||
log_assert(def);
|
||||
levels.push_back(Level(index.modules.at(def), cell));
|
||||
|
|
@ -511,13 +556,13 @@ struct Index {
|
|||
{
|
||||
std::string ret;
|
||||
bool first = true;
|
||||
for (auto pair : levels) {
|
||||
for (auto [minfo, cell] : levels) {
|
||||
if (!first)
|
||||
ret += ".";
|
||||
if (!pair.second)
|
||||
ret += RTLIL::unescape_id(pair.first.module->name);
|
||||
if (!cell)
|
||||
ret += minfo.module->name.unescape();
|
||||
else
|
||||
ret += RTLIL::unescape_id(pair.second->name);
|
||||
ret += cell->name.unescape();
|
||||
first = false;
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -526,8 +571,8 @@ struct Index {
|
|||
int hash() const
|
||||
{
|
||||
int hash = 0;
|
||||
for (auto pair : levels)
|
||||
hash += (uintptr_t) pair.second;
|
||||
for (auto [_, cell] : levels)
|
||||
hash += (uintptr_t) cell;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -536,9 +581,12 @@ struct Index {
|
|||
if (levels.size() != other.levels.size())
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < levels.size(); i++)
|
||||
if (levels[i].second != other.levels[i].second)
|
||||
for (int i = 0; i < levels.size(); i++) {
|
||||
auto* cell = levels[i].second;
|
||||
auto* other_cell = other.levels[i].second;
|
||||
if (cell != other_cell)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -579,7 +627,7 @@ struct Index {
|
|||
// an output of a cell
|
||||
Cell *driver = bit.wire->driverCell();
|
||||
|
||||
if (driver->type.in(KNOWN_OPS)) {
|
||||
if (known_ops(driver->type)) {
|
||||
ret = impl_op(cursor, driver, bit.wire->driverPort(), bit.offset);
|
||||
} else {
|
||||
Module *def = cursor.enter(*this, driver);
|
||||
|
|
@ -588,10 +636,10 @@ struct Index {
|
|||
Wire *w = def->wire(portname);
|
||||
if (!w)
|
||||
log_error("Output port %s on instance %s of %s doesn't exist\n",
|
||||
log_id(portname), log_id(driver), log_id(def));
|
||||
portname.unescape(), driver, def);
|
||||
if (bit.offset >= w->width)
|
||||
log_error("Bit position %d of output port %s on instance %s of %s is out of range (port has width %d)\n",
|
||||
bit.offset, log_id(portname), log_id(driver), log_id(def), w->width);
|
||||
bit.offset, portname.unescape(), driver, def, w->width);
|
||||
ret = visit(cursor, SigBit(w, bit.offset));
|
||||
}
|
||||
cursor.exit(*this);
|
||||
|
|
@ -607,11 +655,11 @@ struct Index {
|
|||
IdString portname = bit.wire->name;
|
||||
if (!instance->hasPort(portname))
|
||||
log_error("Input port %s on instance %s of %s unconnected\n",
|
||||
log_id(portname), log_id(instance), log_id(instance->type));
|
||||
portname.unescape(), instance, instance->type);
|
||||
auto &port = instance->getPort(portname);
|
||||
if (bit.offset >= port.size())
|
||||
log_error("Bit %d of input port %s on instance %s of %s unconnected\n",
|
||||
bit.offset, log_id(portname), log_id(instance), log_id(instance->type));
|
||||
bit.offset, portname.unescape(), instance, instance->type.unescape());
|
||||
ret = visit(cursor, port[bit.offset]);
|
||||
}
|
||||
cursor.enter(*this, instance);
|
||||
|
|
@ -701,6 +749,9 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
nands++;
|
||||
lit_counter += 2;
|
||||
|
||||
// In XAIGER, the ordering of inputs is used to distinguish between AND
|
||||
// and XOR gates. AND gates have their first input literal be larger
|
||||
// than their second, and vice-versa for XORs.
|
||||
if (a < b) std::swap(a, b);
|
||||
encode(out - a);
|
||||
encode(a - b);
|
||||
|
|
@ -717,7 +768,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
log_assert(lit_counter == (Lit) (ninputs + nlatches + nands) * 2 + 2);
|
||||
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf) - 1, "aig %08d %08d %08d %08d %08d\n",
|
||||
snprintf(buf, sizeof(buf), "aig %08d %08d %08d %08d %08d\n",
|
||||
ninputs + nlatches + nands, ninputs, nlatches, noutputs, nands);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
|
|
@ -730,15 +781,16 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
// populate inputs
|
||||
std::vector<SigBit> inputs;
|
||||
for (auto id : top->ports) {
|
||||
Wire *w = top->wire(id);
|
||||
log_assert(w);
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
pi_literal(SigBit(w, i)) = lit_counter;
|
||||
inputs.push_back(SigBit(w, i));
|
||||
lit_counter += 2;
|
||||
ninputs++;
|
||||
}
|
||||
Wire *w = top->wire(id);
|
||||
log_assert(w);
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
auto bit = SigBit(w, i);
|
||||
pi_literal(bit) = lit_counter;
|
||||
inputs.push_back(bit);
|
||||
lit_counter += 2;
|
||||
ninputs++;
|
||||
}
|
||||
}
|
||||
|
||||
this->f = f;
|
||||
|
|
@ -746,35 +798,38 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
write_header();
|
||||
// insert padding where output literals will go (once known)
|
||||
for (auto id : top->ports) {
|
||||
Wire *w = top->wire(id);
|
||||
log_assert(w);
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w)) {
|
||||
(void) bit;
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
|
||||
f->write(buf, strlen(buf));
|
||||
noutputs++;
|
||||
Wire *w = top->wire(id);
|
||||
log_assert(w);
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w)) {
|
||||
(void) bit;
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%08d\n", 0);
|
||||
f->write(buf, strlen(buf));
|
||||
noutputs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto data_start = f->tellp();
|
||||
|
||||
// now the guts
|
||||
std::vector<std::pair<SigBit, int>> outputs;
|
||||
for (auto w : top->wires())
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w))
|
||||
outputs.push_back({bit, eval_po(bit)});
|
||||
}
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w))
|
||||
// Each call to eval_po eventually reaches emit_gate and
|
||||
// encode which writes to f.
|
||||
outputs.push_back({bit, eval_po(bit)});
|
||||
}
|
||||
|
||||
auto data_end = f->tellp();
|
||||
|
||||
// revisit header and the list of outputs
|
||||
f->seekp(file_start);
|
||||
write_header();
|
||||
for (auto pair : outputs) {
|
||||
for (auto [_, po] : outputs) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", pair.second);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", po);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
// double check we arrived at the same offset for the
|
||||
|
|
@ -783,12 +838,13 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
|
||||
f->seekp(data_end);
|
||||
int i = 0;
|
||||
for (auto pair : outputs) {
|
||||
if (SigSpec(pair.first).is_wire()) {
|
||||
for (auto [bit, _] : outputs) {
|
||||
if (SigSpec(bit).is_wire()) {
|
||||
// primary output symbol
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf) - 1, "o%d ", i);
|
||||
snprintf(buf, sizeof(buf), "o%d ", i);
|
||||
f->write(buf, strlen(buf));
|
||||
std::string name = RTLIL::unescape_id(pair.first.wire->name);
|
||||
std::string name = bit.wire->name.unescape();
|
||||
f->write(name.data(), name.size());
|
||||
f->put('\n');
|
||||
}
|
||||
|
|
@ -797,10 +853,11 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
i = 0;
|
||||
for (auto bit : inputs) {
|
||||
if (SigSpec(bit).is_wire()) {
|
||||
// primary input symbol
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf) - 1, "i%d ", i);
|
||||
snprintf(buf, sizeof(buf), "i%d ", i);
|
||||
f->write(buf, strlen(buf));
|
||||
std::string name = RTLIL::unescape_id(bit.wire->name);
|
||||
std::string name = bit.wire->name.unescape();
|
||||
f->write(name.data(), name.size());
|
||||
f->put('\n');
|
||||
}
|
||||
|
|
@ -871,33 +928,34 @@ struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
|
|||
Wire *w = top->wire(id);
|
||||
log_assert(w);
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++)
|
||||
pi_literal(SigBit(w, i)) = 0;
|
||||
for (int i = 0; i < w->width; i++)
|
||||
pi_literal(SigBit(w, i)) = 0;
|
||||
}
|
||||
|
||||
HierCursor cursor;
|
||||
for (auto box : top_minfo->found_blackboxes) {
|
||||
Module *def = design->module(box->type);
|
||||
if (!(def && def->has_attribute(ID::abc9_box_id)))
|
||||
for (auto &conn : box->connections_)
|
||||
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
|
||||
for (auto bit : conn.second)
|
||||
pi_literal(bit, &cursor) = 0;
|
||||
for (auto &conn : box->connections_)
|
||||
if (box->port_dir(conn.first) != RTLIL::PD_INPUT)
|
||||
for (auto bit : conn.second)
|
||||
pi_literal(bit, &cursor) = 0;
|
||||
}
|
||||
|
||||
for (auto w : top->wires())
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w))
|
||||
(void) eval_po(bit);
|
||||
for (auto w : top->wires()) {
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w))
|
||||
(void) eval_po(bit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto box : top_minfo->found_blackboxes) {
|
||||
Module *def = design->module(box->type);
|
||||
if (!(def && def->has_attribute(ID::abc9_box_id)))
|
||||
for (auto &conn : box->connections_)
|
||||
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
|
||||
for (auto bit : conn.second)
|
||||
(void) eval_po(bit);
|
||||
for (auto &conn : box->connections_)
|
||||
if (box->port_dir(conn.first) == RTLIL::PD_INPUT)
|
||||
for (auto bit : conn.second)
|
||||
(void) eval_po(bit);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -916,15 +974,15 @@ struct XAigerWriter : AigerWriter {
|
|||
std::vector<HierBit> pos;
|
||||
std::vector<HierBit> pis;
|
||||
|
||||
// * The aiger output port sequence is COs (inputs to modeled boxes),
|
||||
// inputs to opaque boxes, then module outputs. COs going first is
|
||||
// required by abc.
|
||||
// * proper_pos_counter counts ports which follow after COs
|
||||
// * The mapping file `pseudopo` and `po` statements use indexing relative
|
||||
// to the first port following COs.
|
||||
// * If a module output is directly driven by an opaque box, the emission
|
||||
// of the po statement in the mapping file is skipped. This is done to
|
||||
// aid re-integration of the mapped result.
|
||||
// * The aiger output port sequence is COs (inputs to modeled boxes),
|
||||
// inputs to opaque boxes, then module outputs. COs going first is
|
||||
// required by abc.
|
||||
// * proper_pos_counter counts ports which follow after COs
|
||||
// * The mapping file `pseudopo` and `po` statements use indexing relative
|
||||
// to the first port following COs.
|
||||
// * If a module output is directly driven by an opaque box, the emission
|
||||
// of the po statement in the mapping file is skipped. This is done to
|
||||
// aid re-integration of the mapped result.
|
||||
int proper_pos_counter = 0;
|
||||
|
||||
pool<SigBit> driven_by_opaque_box;
|
||||
|
|
@ -990,7 +1048,7 @@ struct XAigerWriter : AigerWriter {
|
|||
} else if (!is_input && !inputs) {
|
||||
for (auto &bit : conn.second) {
|
||||
if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output))
|
||||
log_error("Bad connection %s/%s ~ %s\n", log_id(box), log_id(conn.first), log_signal(conn.second));
|
||||
log_error("Bad connection %s/%s ~ %s\n", box, conn.first.unescape(), log_signal(conn.second));
|
||||
|
||||
|
||||
ensure_pi(bit, cursor);
|
||||
|
|
@ -1015,9 +1073,9 @@ struct XAigerWriter : AigerWriter {
|
|||
void prep_boxes(int pending_pos_num)
|
||||
{
|
||||
XAigerAnalysis analysis;
|
||||
log_debug("preforming analysis on '%s'\n", log_id(top));
|
||||
log_debug("preforming analysis on '%s'\n", top);
|
||||
analysis.analyze(top);
|
||||
log_debug("analysis on '%s' done\n", log_id(top));
|
||||
log_debug("analysis on '%s' done\n", top);
|
||||
|
||||
// boxes which have timing data, maybe a whitebox model
|
||||
std::vector<std::tuple<HierCursor, Cell *, Module *>> nonopaque_boxes;
|
||||
|
|
@ -1030,8 +1088,8 @@ struct XAigerWriter : AigerWriter {
|
|||
|
||||
for (auto box : minfo.found_blackboxes) {
|
||||
log_debug(" - %s.%s (type %s): ", cursor.path(),
|
||||
RTLIL::unescape_id(box->name),
|
||||
log_id(box->type));
|
||||
box,
|
||||
box->type.unescape());
|
||||
|
||||
Module *box_module = design->module(box->type), *box_derived;
|
||||
|
||||
|
|
@ -1100,7 +1158,7 @@ struct XAigerWriter : AigerWriter {
|
|||
} else {
|
||||
// FIXME: hierarchical path
|
||||
log_warning("connection on port %s[%d] of instance %s (type %s) missing, using 1'bx\n",
|
||||
log_id(port_id), i, log_id(box), log_id(box->type));
|
||||
port_id.unescape(), i, box, box->type.unescape());
|
||||
bit = RTLIL::Sx;
|
||||
}
|
||||
|
||||
|
|
@ -1135,7 +1193,7 @@ struct XAigerWriter : AigerWriter {
|
|||
} else {
|
||||
// FIXME: hierarchical path
|
||||
log_warning("connection on port %s[%d] of instance %s (type %s) missing\n",
|
||||
log_id(port_id), i, log_id(box), log_id(box->type));
|
||||
port_id.unescape(), i, box, box->type.unescape());
|
||||
pad_pi();
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1152,7 +1210,7 @@ struct XAigerWriter : AigerWriter {
|
|||
holes_wb->setPort(port_id, w);
|
||||
} else {
|
||||
log_error("Ambiguous port direction on %s/%s\n",
|
||||
log_id(box->type), log_id(port_id));
|
||||
box->type.unescape(), port_id.unescape());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1202,29 +1260,29 @@ struct XAigerWriter : AigerWriter {
|
|||
reset_counters();
|
||||
|
||||
for (auto w : top->wires())
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++)
|
||||
ensure_pi(SigBit(w, i));
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++)
|
||||
ensure_pi(SigBit(w, i));
|
||||
|
||||
int proper_po_num = 0;
|
||||
for (auto w : top->wires())
|
||||
if (w->port_output)
|
||||
proper_po_num += w->width;
|
||||
if (w->port_output)
|
||||
proper_po_num += w->width;
|
||||
|
||||
prep_boxes(proper_po_num);
|
||||
for (auto w : top->wires())
|
||||
if (w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
// When a module output is directly driven by an opaque box, we
|
||||
// don't emit it to the mapping file to aid re-integration, but we
|
||||
// do emit a proper PO.
|
||||
if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) {
|
||||
map_file << "po " << proper_pos_counter << " " << i
|
||||
<< " " << w->name.c_str() << "\n";
|
||||
}
|
||||
proper_pos_counter++;
|
||||
pos.push_back(std::make_pair(SigBit(w, i), HierCursor{}));
|
||||
}
|
||||
if (w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
// When a module output is directly driven by an opaque box, we
|
||||
// don't emit it to the mapping file to aid re-integration, but we
|
||||
// do emit a proper PO.
|
||||
if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) {
|
||||
map_file << "po " << proper_pos_counter << " " << i
|
||||
<< " " << w->name.c_str() << "\n";
|
||||
}
|
||||
proper_pos_counter++;
|
||||
pos.push_back(std::make_pair(SigBit(w, i), HierCursor{}));
|
||||
}
|
||||
|
||||
this->f = f;
|
||||
// start with the header
|
||||
|
|
@ -1234,7 +1292,7 @@ struct XAigerWriter : AigerWriter {
|
|||
// insert padding where output literals will go (once known)
|
||||
for (auto _ : pos) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", 0);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
auto data_start = f->tellp();
|
||||
|
|
@ -1251,35 +1309,36 @@ struct XAigerWriter : AigerWriter {
|
|||
write_header();
|
||||
for (auto lit : outlits) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", lit);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", lit);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
// double check we arrived at the same offset for the
|
||||
// main data section
|
||||
log_assert(data_start == f->tellp());
|
||||
|
||||
// extensions
|
||||
// XAIGER extensions
|
||||
f->seekp(0, std::ios::end);
|
||||
|
||||
f->put('c');
|
||||
f->put('c'); // 'c': comment (marks beginning of extensions)
|
||||
|
||||
// insert empty 'r' and 's' sections (abc crashes if we provide 'a' without those)
|
||||
f->put('r');
|
||||
write_be32(*f, 4);
|
||||
write_be32(*f, 0);
|
||||
f->put('s');
|
||||
write_be32(*f, 4);
|
||||
write_be32(*f, 0);
|
||||
f->put('r'); // 'r': register classes
|
||||
write_be32(*f, 4); // length in bytes
|
||||
write_be32(*f, 0); // no register classes
|
||||
|
||||
f->put('h');
|
||||
f->put('s'); // 's': register initial values
|
||||
write_be32(*f, 4); // length in bytes
|
||||
write_be32(*f, 0); // no register initial values
|
||||
|
||||
f->put('h'); // 'h': hierarchy information
|
||||
// TODO: get rid of std::string copy
|
||||
std::string h_buffer_str = h_buffer.str();
|
||||
write_be32(*f, h_buffer_str.size());
|
||||
f->write(h_buffer_str.data(), h_buffer_str.size());
|
||||
write_be32(*f, h_buffer_str.size()); // length in bytes
|
||||
f->write(h_buffer_str.data(), h_buffer_str.size()); // data
|
||||
|
||||
#if 1
|
||||
f->put('a');
|
||||
write_be32(*f, 0); // size to be filled later
|
||||
f->put('a'); // 'a': additional AIG (used for holes)
|
||||
write_be32(*f, 0); // length in bytes (to be filled later)
|
||||
auto holes_aiger_start = f->tellp();
|
||||
{
|
||||
AigerWriter holes_writer;
|
||||
|
|
@ -1291,7 +1350,7 @@ struct XAigerWriter : AigerWriter {
|
|||
auto holes_aiger_size = f->tellp() - holes_aiger_start;
|
||||
f->seekp(holes_aiger_start, std::ios::beg);
|
||||
f->seekp(-4, std::ios::cur);
|
||||
write_be32(*f, holes_aiger_size);
|
||||
write_be32(*f, holes_aiger_size); // length in bytes
|
||||
#endif
|
||||
f->seekp(0, std::ios::end);
|
||||
|
||||
|
|
@ -1331,41 +1390,50 @@ struct Aiger2Backend : Backend {
|
|||
log(" perform structural hashing while writing\n");
|
||||
log("\n");
|
||||
log(" -flatten\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log("This command is able to ingest all combinational cells except for:\n");
|
||||
log("\n");
|
||||
pool<IdString> supported = {KNOWN_OPS};
|
||||
CellTypes ct;
|
||||
ct.setup_internals_eval();
|
||||
log(" ");
|
||||
int col = 0;
|
||||
for (auto pair : ct.cell_types)
|
||||
if (!supported.count(pair.first)) {
|
||||
if (col + pair.first.size() + 2 > 72) {
|
||||
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||
auto &cell = StaticCellTypes::builder.cells[i];
|
||||
if (!cell.features.is_evaluable)
|
||||
continue;
|
||||
if (cell.features.is_stdcell)
|
||||
continue;
|
||||
if (known_ops(cell.type))
|
||||
continue;
|
||||
std::string name = cell.type.unescape();
|
||||
if (col + name.size() + 2 > 72) {
|
||||
log("\n ");
|
||||
col = 0;
|
||||
}
|
||||
col += pair.first.size() + 2;
|
||||
log("%s, ", log_id(pair.first));
|
||||
col += name.size() + 2;
|
||||
log("%s, ", name.c_str());
|
||||
}
|
||||
log("\n");
|
||||
log("\n");
|
||||
log("And all combinational gates except for:\n");
|
||||
log("\n");
|
||||
CellTypes ct2;
|
||||
ct2.setup_stdcells();
|
||||
log(" ");
|
||||
col = 0;
|
||||
for (auto pair : ct2.cell_types)
|
||||
if (!supported.count(pair.first)) {
|
||||
if (col + pair.first.size() + 2 > 72) {
|
||||
for (size_t i = 0; i < StaticCellTypes::builder.count; i++) {
|
||||
auto &cell = StaticCellTypes::builder.cells[i];
|
||||
if (!cell.features.is_evaluable)
|
||||
continue;
|
||||
if (!cell.features.is_stdcell)
|
||||
continue;
|
||||
if (known_ops(cell.type))
|
||||
continue;
|
||||
std::string name = cell.type.unescape();
|
||||
if (col + name.size() + 2 > 72) {
|
||||
log("\n ");
|
||||
col = 0;
|
||||
}
|
||||
col += pair.first.size() + 2;
|
||||
log("%s, ", log_id(pair.first));
|
||||
col += name.size() + 2;
|
||||
log("%s, ", name.c_str());
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
|
|
@ -1423,20 +1491,20 @@ struct XAiger2Backend : Backend {
|
|||
log(" perform structural hashing while writing\n");
|
||||
log("\n");
|
||||
log(" -flatten\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log(" -mapping_prep\n");
|
||||
log(" after the file is written, prepare the module for reintegration of\n");
|
||||
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
|
||||
log(" whiteboxed are removed from the design as well as all wires which only\n");
|
||||
log(" connect to removed cells\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
log(" -map2 <file>\n");
|
||||
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
||||
log(" reintegrate a mapping\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log(" allow descending into submodules and write a flattened view of the design\n");
|
||||
log(" hierarchy starting at the selected top\n");
|
||||
log("\n");
|
||||
log(" -mapping_prep\n");
|
||||
log(" after the file is written, prepare the module for reintegration of\n");
|
||||
log(" a mapping in a subsequent command. all cells which are not blackboxed nor\n");
|
||||
log(" whiteboxed are removed from the design as well as all wires which only\n");
|
||||
log(" connect to removed cells\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
log(" -map2 <file>\n");
|
||||
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
||||
log(" reintegrate a mapping\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
3
backends/blif/CMakeLists.txt
Normal file
3
backends/blif/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
yosys_backend(blif
|
||||
blif.cc
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/blif/blif.o
|
||||
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ struct BlifDumper
|
|||
RTLIL::Module *module;
|
||||
RTLIL::Design *design;
|
||||
BlifDumperConfig *config;
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
|
||||
SigMap sigmap;
|
||||
dict<SigBit, int> init_bits;
|
||||
|
|
@ -91,7 +91,7 @@ struct BlifDumper
|
|||
|
||||
const std::string str(RTLIL::IdString id)
|
||||
{
|
||||
std::string str = RTLIL::unescape_id(id);
|
||||
std::string str = id.unescape();
|
||||
for (size_t i = 0; i < str.size(); i++)
|
||||
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
|
||||
str[i] = '?';
|
||||
|
|
@ -108,7 +108,7 @@ struct BlifDumper
|
|||
return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef";
|
||||
}
|
||||
|
||||
std::string str = RTLIL::unescape_id(sig.wire->name);
|
||||
std::string str = sig.wire->name.unescape();
|
||||
for (size_t i = 0; i < str.size(); i++)
|
||||
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
|
||||
str[i] = '?';
|
||||
|
|
@ -150,7 +150,7 @@ struct BlifDumper
|
|||
void dump_params(const char *command, dict<IdString, Const> ¶ms)
|
||||
{
|
||||
for (auto ¶m : params) {
|
||||
f << stringf("%s %s ", command, log_id(param.first));
|
||||
f << stringf("%s %s ", command, param.first.unescape());
|
||||
if (param.second.flags & RTLIL::CONST_FLAG_STRING) {
|
||||
std::string str = param.second.decode_string();
|
||||
f << stringf("\"");
|
||||
|
|
@ -678,9 +678,9 @@ struct BlifBackend : public Backend {
|
|||
continue;
|
||||
|
||||
if (module->processes.size() != 0)
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", log_id(module->name));
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", module->name.unescape());
|
||||
if (module->memories.size() != 0)
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", log_id(module->name));
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", module->name.unescape());
|
||||
|
||||
if (module->name == RTLIL::escape_id(top_module_name)) {
|
||||
BlifDumper::dump(*f, module, design, config);
|
||||
|
|
|
|||
7
backends/btor/CMakeLists.txt
Normal file
7
backends/btor/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
yosys_backend(btor
|
||||
btor.cc
|
||||
REQUIRES
|
||||
bmuxmap
|
||||
demuxmap
|
||||
bwmuxmap
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/btor/btor.o
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ struct BtorWorker
|
|||
template<typename T>
|
||||
string getinfo(T *obj, bool srcsym = false)
|
||||
{
|
||||
string infostr = log_id(obj);
|
||||
string infostr = obj->name.unescape();
|
||||
if (!srcsym && !print_internal_names && infostr[0] == '$') return "";
|
||||
if (obj->attributes.count(ID::src)) {
|
||||
string src = obj->attributes.at(ID::src).decode_string().c_str();
|
||||
|
|
@ -243,12 +243,12 @@ struct BtorWorker
|
|||
if (cell_recursion_guard.count(cell)) {
|
||||
string cell_list;
|
||||
for (auto c : cell_recursion_guard)
|
||||
cell_list += stringf("\n %s", log_id(c));
|
||||
log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list);
|
||||
cell_list += stringf("\n %s", c);
|
||||
log_error("Found topological loop while processing cell %s. Active cells:%s\n", cell, cell_list);
|
||||
}
|
||||
|
||||
cell_recursion_guard.insert(cell);
|
||||
btorf_push(log_id(cell));
|
||||
btorf_push(cell->name.unescape());
|
||||
|
||||
if (cell->type.in(ID($add), ID($sub), ID($mul), ID($and), ID($or), ID($xor), ID($xnor), ID($shl), ID($sshl), ID($shr), ID($sshr), ID($shift), ID($shiftx),
|
||||
ID($concat), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_)))
|
||||
|
|
@ -726,7 +726,7 @@ struct BtorWorker
|
|||
if (symbol.empty() || (!print_internal_names && symbol[0] == '$'))
|
||||
btorf("%d state %d\n", nid, sid);
|
||||
else
|
||||
btorf("%d state %d %s\n", nid, sid, log_id(symbol));
|
||||
btorf("%d state %d %s\n", nid, sid, symbol.unescape());
|
||||
|
||||
if (cell->get_bool_attribute(ID(clk2fflogic)))
|
||||
ywmap_state(cell->getPort(ID::D)); // For a clk2fflogic FF the named signal is the D input not the Q output
|
||||
|
|
@ -804,12 +804,12 @@ struct BtorWorker
|
|||
|
||||
if (asyncwr && syncwr)
|
||||
log_error("Memory %s.%s has mixed async/sync write ports.\n",
|
||||
log_id(module), log_id(mem->memid));
|
||||
module, mem->memid.unescape());
|
||||
|
||||
for (auto &port : mem->rd_ports) {
|
||||
if (port.clk_enable)
|
||||
log_error("Memory %s.%s has sync read ports. Please use memory_nordff to convert them first.\n",
|
||||
log_id(module), log_id(mem->memid));
|
||||
module, mem->memid.unescape());
|
||||
}
|
||||
|
||||
int data_sid = get_bv_sid(mem->width);
|
||||
|
|
@ -871,7 +871,7 @@ struct BtorWorker
|
|||
if (mem->memid[0] == '$')
|
||||
btorf("%d state %d\n", nid, sid);
|
||||
else
|
||||
btorf("%d state %d %s\n", nid, sid, log_id(mem->memid));
|
||||
btorf("%d state %d %s\n", nid, sid, mem->memid.unescape());
|
||||
|
||||
ywmap_state(cell);
|
||||
|
||||
|
|
@ -948,21 +948,20 @@ struct BtorWorker
|
|||
|
||||
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_btor`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
|
||||
cell->type.unescape(), module, cell);
|
||||
okay:
|
||||
btorf_pop(log_id(cell));
|
||||
btorf_pop(cell->name.unescape());
|
||||
cell_recursion_guard.erase(cell);
|
||||
}
|
||||
|
||||
|
|
@ -1167,7 +1166,7 @@ struct BtorWorker
|
|||
f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename)
|
||||
{
|
||||
if (!info_filename.empty())
|
||||
infof("name %s\n", log_id(module));
|
||||
infof("name %s\n", module);
|
||||
|
||||
if (!ywmap_filename.empty())
|
||||
ywmap_json.write_to_file(ywmap_filename);
|
||||
|
|
@ -1257,19 +1256,19 @@ struct BtorWorker
|
|||
if (!wire->port_id || !wire->port_output)
|
||||
continue;
|
||||
|
||||
btorf_push(stringf("output %s", log_id(wire)));
|
||||
btorf_push(stringf("output %s", wire));
|
||||
|
||||
int nid = get_sig_nid(wire);
|
||||
btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire));
|
||||
|
||||
btorf_pop(stringf("output %s", log_id(wire)));
|
||||
btorf_pop(stringf("output %s", wire));
|
||||
}
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
if (cell->type == ID($assume))
|
||||
{
|
||||
btorf_push(log_id(cell));
|
||||
btorf_push(cell->name.unescape());
|
||||
|
||||
int sid = get_bv_sid(1);
|
||||
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
||||
|
|
@ -1284,12 +1283,12 @@ struct BtorWorker
|
|||
|
||||
if (ywmap_json.active()) ywmap_assumes.emplace_back(cell);
|
||||
|
||||
btorf_pop(log_id(cell));
|
||||
btorf_pop(cell->name.unescape());
|
||||
}
|
||||
|
||||
if (cell->type == ID($assert))
|
||||
{
|
||||
btorf_push(log_id(cell));
|
||||
btorf_push(cell->name.unescape());
|
||||
|
||||
int sid = get_bv_sid(1);
|
||||
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
||||
|
|
@ -1313,12 +1312,12 @@ struct BtorWorker
|
|||
}
|
||||
}
|
||||
|
||||
btorf_pop(log_id(cell));
|
||||
btorf_pop(cell->name.unescape());
|
||||
}
|
||||
|
||||
if (cell->type == ID($cover) && cover_mode)
|
||||
{
|
||||
btorf_push(log_id(cell));
|
||||
btorf_push(cell->name.unescape());
|
||||
|
||||
int sid = get_bv_sid(1);
|
||||
int nid_a = get_sig_nid(cell->getPort(ID::A));
|
||||
|
|
@ -1334,7 +1333,7 @@ struct BtorWorker
|
|||
btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true));
|
||||
}
|
||||
|
||||
btorf_pop(log_id(cell));
|
||||
btorf_pop(cell->name.unescape());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1343,7 +1342,7 @@ struct BtorWorker
|
|||
if (wire->port_id || wire->name[0] == '$')
|
||||
continue;
|
||||
|
||||
btorf_push(stringf("wire %s", log_id(wire)));
|
||||
btorf_push(stringf("wire %s", wire));
|
||||
|
||||
int sid = get_bv_sid(GetSize(wire));
|
||||
int nid = get_sig_nid(sigmap(wire));
|
||||
|
|
@ -1356,7 +1355,7 @@ struct BtorWorker
|
|||
if (info_clocks.count(nid))
|
||||
info_clocks[this_nid] |= info_clocks[nid];
|
||||
|
||||
btorf_pop(stringf("wire %s", log_id(wire)));
|
||||
btorf_pop(stringf("wire %s", wire));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1370,14 +1369,14 @@ struct BtorWorker
|
|||
int nid = it.first;
|
||||
Cell *cell = it.second;
|
||||
|
||||
btorf_push(stringf("next %s", log_id(cell)));
|
||||
btorf_push(stringf("next %s", cell));
|
||||
|
||||
SigSpec sig = sigmap(cell->getPort(ID::D));
|
||||
int nid_q = get_sig_nid(sig);
|
||||
int sid = get_bv_sid(GetSize(sig));
|
||||
btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell));
|
||||
|
||||
btorf_pop(stringf("next %s", log_id(cell)));
|
||||
btorf_pop(stringf("next %s", cell));
|
||||
}
|
||||
|
||||
vector<pair<int, Mem*>> mtodo;
|
||||
|
|
@ -1388,7 +1387,7 @@ struct BtorWorker
|
|||
int nid = it.first;
|
||||
Mem *mem = it.second;
|
||||
|
||||
btorf_push(stringf("next %s", log_id(mem->memid)));
|
||||
btorf_push(stringf("next %s", mem->memid.unescape()));
|
||||
|
||||
int abits = ceil_log2(mem->size);
|
||||
|
||||
|
|
@ -1436,7 +1435,7 @@ struct BtorWorker
|
|||
int nid2 = next_nid++;
|
||||
btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, (mem->cell ? getinfo(mem->cell) : getinfo(mem->mem)));
|
||||
|
||||
btorf_pop(stringf("next %s", log_id(mem->memid)));
|
||||
btorf_pop(stringf("next %s", mem->memid.unescape()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1630,7 +1629,7 @@ struct BtorBackend : public Backend {
|
|||
log_cmd_error("No top module found.\n");
|
||||
|
||||
*f << stringf("; BTOR description generated by %s for module %s.\n",
|
||||
yosys_maybe_version(), log_id(topmod));
|
||||
yosys_maybe_version(), topmod);
|
||||
|
||||
BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename);
|
||||
|
||||
|
|
|
|||
19
backends/cxxrtl/CMakeLists.txt
Normal file
19
backends/cxxrtl/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
yosys_backend(cxxrtl
|
||||
cxxrtl_backend.cc
|
||||
DATA_DIR
|
||||
include/backends/cxxrtl
|
||||
DATA_FILES
|
||||
runtime/README.txt
|
||||
runtime/cxxrtl/cxxrtl.h
|
||||
runtime/cxxrtl/cxxrtl_vcd.h
|
||||
runtime/cxxrtl/cxxrtl_time.h
|
||||
runtime/cxxrtl/cxxrtl_replay.h
|
||||
runtime/cxxrtl/capi/cxxrtl_capi.cc
|
||||
runtime/cxxrtl/capi/cxxrtl_capi.h
|
||||
runtime/cxxrtl/capi/cxxrtl_capi_vcd.cc
|
||||
runtime/cxxrtl/capi/cxxrtl_capi_vcd.h
|
||||
REQUIRES
|
||||
hierarchy
|
||||
flatten
|
||||
proc
|
||||
)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
OBJS += backends/cxxrtl/cxxrtl_backend.o
|
||||
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl.h))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl_vcd.h))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl_time.h))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/cxxrtl_replay.h))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.cc))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi_vcd.cc))
|
||||
$(eval $(call add_include_file,backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi_vcd.h))
|
||||
|
|
@ -251,7 +251,7 @@ CxxrtlPortType cxxrtl_port_type(RTLIL::Module *module, RTLIL::IdString port)
|
|||
bool is_sync = output_wire->get_bool_attribute(ID(cxxrtl_sync));
|
||||
if (is_comb && is_sync)
|
||||
log_cmd_error("Port `%s.%s' is marked as both `cxxrtl_comb` and `cxxrtl_sync`.\n",
|
||||
log_id(module), log_signal(output_wire));
|
||||
module, log_signal(output_wire));
|
||||
else if (is_comb)
|
||||
return CxxrtlPortType::COMB;
|
||||
else if (is_sync)
|
||||
|
|
@ -851,7 +851,7 @@ struct CxxrtlWorker {
|
|||
return {};
|
||||
|
||||
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", module);
|
||||
|
||||
std::vector<std::string> param_names = split_by(module->get_string_attribute(ID(cxxrtl_template)), " \t");
|
||||
for (const auto ¶m_name : param_names) {
|
||||
|
|
@ -861,7 +861,7 @@ struct CxxrtlWorker {
|
|||
if (!isupper(param_name[0]))
|
||||
log_cmd_error("Attribute `cxxrtl_template' of module `%s' includes a parameter `%s', "
|
||||
"which does not start with an uppercase letter.\n",
|
||||
log_id(module), param_name.c_str());
|
||||
module, param_name.c_str());
|
||||
}
|
||||
return param_names;
|
||||
}
|
||||
|
|
@ -907,12 +907,12 @@ struct CxxrtlWorker {
|
|||
RTLIL::IdString id_param_name = '\\' + param_name;
|
||||
if (!cell->hasParam(id_param_name))
|
||||
log_cmd_error("Cell `%s.%s' does not have a parameter `%s', which is required by the templated module `%s'.\n",
|
||||
log_id(cell->module), log_id(cell), param_name.c_str(), log_id(cell_module));
|
||||
cell->module, cell, param_name.c_str(), cell_module);
|
||||
RTLIL::Const param_value = cell->getParam(id_param_name);
|
||||
if (((param_value.flags & ~RTLIL::CONST_FLAG_SIGNED) != 0) || param_value.as_int() < 0)
|
||||
log_cmd_error("Parameter `%s' of cell `%s.%s', which is required by the templated module `%s', "
|
||||
"is not a positive integer.\n",
|
||||
param_name.c_str(), log_id(cell->module), log_id(cell), log_id(cell_module));
|
||||
param_name.c_str(), cell->module, cell, cell_module);
|
||||
params += std::to_string(cell->getParam(id_param_name).as_int());
|
||||
}
|
||||
params += ">";
|
||||
|
|
@ -2576,7 +2576,7 @@ struct CxxrtlWorker {
|
|||
}
|
||||
dec_indent();
|
||||
|
||||
log_debug("Debug information statistics for module `%s':\n", log_id(module));
|
||||
log_debug("Debug information statistics for module `%s':\n", module);
|
||||
log_debug(" Scopes: %zu", count_scopes);
|
||||
log_debug(" Public wires: %zu, of which:\n", count_public_wires);
|
||||
log_debug(" Member wires: %zu, of which:\n", count_member_wires);
|
||||
|
|
@ -2776,7 +2776,8 @@ struct CxxrtlWorker {
|
|||
{
|
||||
RTLIL::Module *top_module = nullptr;
|
||||
std::vector<RTLIL::Module*> modules;
|
||||
TopoSort<RTLIL::Module*> topo_design;
|
||||
using Order = IdString::compare_ptr_by_name<RTLIL::NamedObject>;
|
||||
TopoSort<RTLIL::Module*, Order> topo_design;
|
||||
for (auto module : design->modules()) {
|
||||
if (!design->selected_module(module))
|
||||
continue;
|
||||
|
|
@ -2939,7 +2940,7 @@ struct CxxrtlWorker {
|
|||
RTLIL::Const edge_attr = wire->attributes[ID(cxxrtl_edge)];
|
||||
if (!(edge_attr.flags & RTLIL::CONST_FLAG_STRING) || (int)edge_attr.decode_string().size() != GetSize(wire))
|
||||
log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' is not a string with one character per bit.\n",
|
||||
log_id(module), log_signal(wire));
|
||||
module, log_signal(wire));
|
||||
|
||||
std::string edges = wire->get_string_attribute(ID(cxxrtl_edge));
|
||||
for (int i = 0; i < GetSize(wire); i++) {
|
||||
|
|
@ -2952,7 +2953,7 @@ struct CxxrtlWorker {
|
|||
default:
|
||||
log_cmd_error("Attribute `cxxrtl_edge' of port `%s.%s' contains specifiers "
|
||||
"other than '-', 'p', 'n', or 'a'.\n",
|
||||
log_id(module), log_signal(wire));
|
||||
module, log_signal(wire));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2977,7 +2978,7 @@ struct CxxrtlWorker {
|
|||
|
||||
for (auto cell : module->cells()) {
|
||||
if (!cell->known())
|
||||
log_cmd_error("Unknown cell `%s'.\n", log_id(cell->type));
|
||||
log_cmd_error("Unknown cell `%s'.\n", cell->type.unescape());
|
||||
|
||||
if (cell->is_mem_cell())
|
||||
continue;
|
||||
|
|
@ -2986,7 +2987,7 @@ struct CxxrtlWorker {
|
|||
if (cell_module &&
|
||||
cell_module->get_blackbox_attribute() &&
|
||||
!cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
|
||||
log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", log_id(cell->type));
|
||||
log_cmd_error("External blackbox cell `%s' is not marked as a CXXRTL blackbox.\n", cell->type.unescape());
|
||||
|
||||
if (cell_module &&
|
||||
cell_module->get_bool_attribute(ID(cxxrtl_blackbox)) &&
|
||||
|
|
@ -3115,9 +3116,9 @@ struct CxxrtlWorker {
|
|||
}
|
||||
if (!feedback_wires.empty()) {
|
||||
has_feedback_arcs = true;
|
||||
log("Module `%s' contains feedback arcs through wires:\n", log_id(module));
|
||||
log("Module `%s' contains feedback arcs through wires:\n", module);
|
||||
for (auto wire : feedback_wires)
|
||||
log(" %s\n", log_id(wire));
|
||||
log(" %s\n", wire);
|
||||
}
|
||||
|
||||
// Conservatively assign wire types. Assignment of types BUFFERED and MEMBER is final, but assignment
|
||||
|
|
@ -3188,7 +3189,7 @@ struct CxxrtlWorker {
|
|||
if (wire->name.isPublic() && !inline_public) continue;
|
||||
if (flow.is_inlinable(wire, live_wires[wire])) {
|
||||
if (flow.wire_comb_defs[wire].size() > 1)
|
||||
log_cmd_error("Wire %s.%s has multiple drivers!\n", log_id(module), log_id(wire));
|
||||
log_cmd_error("Wire %s.%s has multiple drivers!\n", module, wire);
|
||||
log_assert(flow.wire_comb_defs[wire].size() == 1);
|
||||
FlowGraph::Node *node = *flow.wire_comb_defs[wire].begin();
|
||||
switch (node->type) {
|
||||
|
|
@ -3236,9 +3237,9 @@ struct CxxrtlWorker {
|
|||
buffered_comb_wires.insert(wire);
|
||||
if (!buffered_comb_wires.empty()) {
|
||||
has_buffered_comb_wires = true;
|
||||
log("Module `%s' contains buffered combinatorial wires:\n", log_id(module));
|
||||
log("Module `%s' contains buffered combinatorial wires:\n", module);
|
||||
for (auto wire : buffered_comb_wires)
|
||||
log(" %s\n", log_id(wire));
|
||||
log(" %s\n", wire);
|
||||
}
|
||||
|
||||
// Record whether eval() requires only one delta cycle in this module.
|
||||
|
|
@ -3419,7 +3420,7 @@ struct CxxrtlWorker {
|
|||
|
||||
if (!design->selected_whole_module(module))
|
||||
if (design->selected_module(module))
|
||||
log_cmd_error("Can't handle partially selected module `%s'!\n", id2cstr(module->name));
|
||||
log_cmd_error("Can't handle partially selected module `%s'!\n", module);
|
||||
if (!design->selected_module(module))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ struct value : public expr_base<value<Bits>> {
|
|||
int64_t divisor_shift = divisor.ctlz() - dividend.ctlz();
|
||||
assert(divisor_shift >= 0);
|
||||
divisor = divisor.shl(value<Bits>{(chunk::type) divisor_shift});
|
||||
for (size_t step = 0; step <= divisor_shift; step++) {
|
||||
for (size_t step = 0; step <= (uint64_t) divisor_shift; step++) {
|
||||
quotient = quotient.shl(value<Bits>{1u});
|
||||
if (!dividend.ucmp(divisor)) {
|
||||
dividend = dividend.sub(divisor);
|
||||
|
|
@ -1119,7 +1119,7 @@ struct fmt_part {
|
|||
|
||||
case STRING: {
|
||||
buf.reserve(Bits/8);
|
||||
for (int i = 0; i < Bits; i += 8) {
|
||||
for (size_t i = 0; i < Bits; i += 8) {
|
||||
char ch = 0;
|
||||
for (int j = 0; j < 8 && i + j < int(Bits); j++)
|
||||
if (val.bit(i + j))
|
||||
|
|
|
|||
3
backends/edif/CMakeLists.txt
Normal file
3
backends/edif/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
yosys_backend(edif
|
||||
edif.cc
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/edif/edif.o
|
||||
|
||||
|
|
@ -23,16 +23,18 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true)
|
||||
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br)
|
||||
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false)
|
||||
#define EDIF_DEF(_id) edif_names(_id.unescape(), true)
|
||||
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(_id.unescape(), true, _ren, _bl, _br)
|
||||
#define EDIF_REF(_id) edif_names(_id.unescape(), false)
|
||||
#define EDIF_DEF_STR(_id) edif_names(RTLIL::unescape_id(_id), true)
|
||||
#define EDIF_REF_STR(_id) edif_names(RTLIL::unescape_id(_id), false)
|
||||
|
||||
struct EdifNames
|
||||
{
|
||||
|
|
@ -138,7 +140,7 @@ struct EdifBackend : public Backend {
|
|||
bool lsbidx = false;
|
||||
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
|
||||
bool nogndvcc = false, gndvccy = false, keepmode = false;
|
||||
CellTypes ct(design);
|
||||
NewCellTypes ct(design);
|
||||
EdifNames edif_names;
|
||||
|
||||
size_t argidx;
|
||||
|
|
@ -207,9 +209,9 @@ struct EdifBackend : public Backend {
|
|||
top_module_name = module->name.str();
|
||||
|
||||
if (module->processes.size() != 0)
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name));
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", module->name.unescape());
|
||||
if (module->memories.size() != 0)
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name));
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", module->name.unescape());
|
||||
|
||||
for (auto cell : module->cells())
|
||||
{
|
||||
|
|
@ -227,7 +229,7 @@ struct EdifBackend : public Backend {
|
|||
if (top_module_name.empty())
|
||||
log_error("No module found in design!\n");
|
||||
|
||||
*f << stringf("(edif %s\n", EDIF_DEF(top_module_name));
|
||||
*f << stringf("(edif %s\n", EDIF_DEF_STR(top_module_name));
|
||||
*f << stringf(" (edifVersion 2 0 0)\n");
|
||||
*f << stringf(" (edifLevel 0)\n");
|
||||
*f << stringf(" (keywordMap (keywordLevel 0))\n");
|
||||
|
|
@ -317,12 +319,12 @@ struct EdifBackend : public Backend {
|
|||
for (auto &dep : it.second)
|
||||
if (module_deps.count(dep) > 0)
|
||||
goto not_ready_yet;
|
||||
// log("Next in topological sort: %s\n", log_id(it.first->name));
|
||||
// log("Next in topological sort: %s\n", it.first->name.unescape());
|
||||
sorted_modules.push_back(it.first);
|
||||
not_ready_yet:;
|
||||
}
|
||||
if (sorted_modules_idx == sorted_modules.size())
|
||||
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name));
|
||||
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape());
|
||||
while (sorted_modules_idx < sorted_modules.size())
|
||||
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
|
||||
}
|
||||
|
|
@ -486,7 +488,7 @@ struct EdifBackend : public Backend {
|
|||
for (int i = 0; i < GetSize(sig); i++)
|
||||
if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1)
|
||||
log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n",
|
||||
i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i]));
|
||||
i, module, cell, p.first.unescape(), log_signal(sig[i]));
|
||||
else {
|
||||
int member_idx = lsbidx ? i : GetSize(sig)-i-1;
|
||||
auto m = design->module(cell->type);
|
||||
|
|
@ -534,7 +536,7 @@ struct EdifBackend : public Backend {
|
|||
if (netname[i] == ' ' || netname[i] == '\\')
|
||||
netname.erase(netname.begin() + i--);
|
||||
}
|
||||
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
|
||||
*f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
|
||||
for (auto &ref : it.second)
|
||||
*f << stringf(" %s\n", ref.first);
|
||||
if (sig.wire == NULL) {
|
||||
|
|
@ -572,7 +574,7 @@ struct EdifBackend : public Backend {
|
|||
|
||||
if (keepmode)
|
||||
{
|
||||
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
|
||||
*f << stringf(" (net %s (joined\n", EDIF_DEF_STR(netname));
|
||||
|
||||
auto &refs = net_join_db.at(mapped_sig);
|
||||
for (auto &ref : refs)
|
||||
|
|
@ -588,7 +590,7 @@ struct EdifBackend : public Backend {
|
|||
}
|
||||
else
|
||||
{
|
||||
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF(netname));
|
||||
log_warning("Ignoring conflicting 'keep' property on net %s. Use -keep to generate the extra net nevertheless.\n", EDIF_DEF_STR(netname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -599,8 +601,8 @@ struct EdifBackend : public Backend {
|
|||
}
|
||||
*f << stringf(" )\n");
|
||||
|
||||
*f << stringf(" (design %s\n", EDIF_DEF(top_module_name));
|
||||
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name));
|
||||
*f << stringf(" (design %s\n", EDIF_DEF_STR(top_module_name));
|
||||
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF_STR(top_module_name));
|
||||
*f << stringf(" )\n");
|
||||
|
||||
*f << stringf(")\n");
|
||||
|
|
|
|||
8
backends/firrtl/CMakeLists.txt
Normal file
8
backends/firrtl/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
yosys_backend(firrtl
|
||||
firrtl.cc
|
||||
REQUIRES
|
||||
pmuxtree
|
||||
bmuxmap
|
||||
demuxmap
|
||||
bwmuxmap
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/firrtl/firrtl.o
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ const char *make_id(IdString id)
|
|||
if (namecache.count(id) != 0)
|
||||
return namecache.at(id).c_str();
|
||||
|
||||
string new_id = log_id(id);
|
||||
string new_id = id.unescape();
|
||||
|
||||
for (int i = 0; i < GetSize(new_id); i++)
|
||||
{
|
||||
|
|
@ -263,7 +263,7 @@ void emit_extmodule(RTLIL::Cell *cell, RTLIL::Module *mod_instance, std::ostream
|
|||
|
||||
if (wire->port_input && wire->port_output)
|
||||
{
|
||||
log_error("Module port %s.%s is inout!\n", log_id(mod_instance), log_id(wire));
|
||||
log_error("Module port %s.%s is inout!\n", mod_instance, wire);
|
||||
}
|
||||
|
||||
const std::string portDecl = stringf("%s%s %s: UInt<%d> %s\n",
|
||||
|
|
@ -559,12 +559,12 @@ struct FirrtlWorker
|
|||
if (wire->attributes.count(ID::init)) {
|
||||
log_warning("Initial value (%s) for (%s.%s) not supported\n",
|
||||
wire->attributes.at(ID::init).as_string().c_str(),
|
||||
log_id(module), log_id(wire));
|
||||
module, wire);
|
||||
}
|
||||
if (wire->port_id)
|
||||
{
|
||||
if (wire->port_input && wire->port_output)
|
||||
log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire));
|
||||
log_error("Module port %s.%s is inout!\n", module, wire);
|
||||
port_decls.push_back(stringf("%s%s %s: UInt<%d> %s\n", indent, wire->port_input ? "input" : "output",
|
||||
wireName, wire->width, wireFileinfo.c_str()));
|
||||
}
|
||||
|
|
@ -833,7 +833,7 @@ struct FirrtlWorker
|
|||
primop = "shl";
|
||||
int shiftAmount = b_sig.as_int();
|
||||
if (shiftAmount < 0) {
|
||||
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell));
|
||||
log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, module, cell);
|
||||
}
|
||||
b_expr = std::to_string(shiftAmount);
|
||||
firrtl_width = a_width + shiftAmount;
|
||||
|
|
@ -844,7 +844,7 @@ struct FirrtlWorker
|
|||
firrtl_width = a_width + (1 << b_width) - 1;
|
||||
}
|
||||
} else {
|
||||
log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell));
|
||||
log_error("Non power 2: %s.%s\n", module, cell);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -905,7 +905,7 @@ struct FirrtlWorker
|
|||
{
|
||||
bool clkpol = cell->parameters.at(ID::CLK_POLARITY).as_bool();
|
||||
if (clkpol == false)
|
||||
log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell));
|
||||
log_error("Negative edge clock on FF %s.%s.\n", module, cell);
|
||||
|
||||
int width = cell->parameters.at(ID::WIDTH).as_int();
|
||||
string expr = make_expr(cell->getPort(ID::D));
|
||||
|
|
@ -983,7 +983,7 @@ struct FirrtlWorker
|
|||
|
||||
if (cell->type == ID($scopeinfo))
|
||||
continue;
|
||||
log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
|
||||
log_error("Cell type not supported: %s (%s.%s)\n", cell->type.unescape(), module, cell);
|
||||
}
|
||||
|
||||
for (auto &mem : memories) {
|
||||
|
|
@ -991,10 +991,10 @@ struct FirrtlWorker
|
|||
|
||||
Const init_data = mem.get_init_data();
|
||||
if (!init_data.is_fully_undef())
|
||||
log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(mem.memid));
|
||||
log_error("Memory with initialization data: %s.%s\n", module, mem.memid.unescape());
|
||||
|
||||
if (mem.start_offset != 0)
|
||||
log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(mem.memid));
|
||||
log_error("Memory with nonzero offset: %s.%s\n", module, mem.memid.unescape());
|
||||
|
||||
for (int i = 0; i < GetSize(mem.rd_ports); i++)
|
||||
{
|
||||
|
|
@ -1002,7 +1002,7 @@ struct FirrtlWorker
|
|||
string port_name(stringf("%s.r%d", mem_id, i));
|
||||
|
||||
if (port.clk_enable)
|
||||
log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
||||
log_error("Clocked read port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||
|
||||
std::ostringstream rpe;
|
||||
|
||||
|
|
@ -1023,12 +1023,12 @@ struct FirrtlWorker
|
|||
string port_name(stringf("%s.w%d", mem_id, i));
|
||||
|
||||
if (!port.clk_enable)
|
||||
log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
||||
log_error("Unclocked write port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||
if (!port.clk_polarity)
|
||||
log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
||||
log_error("Negedge write port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||
for (int i = 1; i < GetSize(port.en); i++)
|
||||
if (port.en[0] != port.en[i])
|
||||
log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
|
||||
log_error("Complex write enable on port %d on memory %s.%s.\n", i, module, mem.memid.unescape());
|
||||
|
||||
std::ostringstream wpe;
|
||||
|
||||
|
|
|
|||
12
backends/functional/CMakeLists.txt
Normal file
12
backends/functional/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
yosys_backend(functional_cxx
|
||||
cxx.cc
|
||||
)
|
||||
yosys_backend(functional_smt2
|
||||
smtlib.cc
|
||||
)
|
||||
yosys_backend(functional_rosette
|
||||
smtlib_rosette.cc
|
||||
)
|
||||
yosys_test_pass(generic
|
||||
test_generic.cc
|
||||
)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
OBJS += backends/functional/cxx.o
|
||||
OBJS += backends/functional/smtlib.o
|
||||
OBJS += backends/functional/smtlib_rosette.o
|
||||
OBJS += backends/functional/test_generic.o
|
||||
|
|
@ -89,7 +89,7 @@ struct CxxStruct {
|
|||
}
|
||||
f.print("\n\t\ttemplate <typename T> void visit(T &&fn) {{\n");
|
||||
for (auto p : types) {
|
||||
f.print("\t\t\tfn(\"{}\", {});\n", RTLIL::unescape_id(p.first), scope(p.first, p.first));
|
||||
f.print("\t\t\tfn(\"{}\", {});\n", p.first.unescape(), scope(p.first, p.first));
|
||||
}
|
||||
f.print("\t\t}}\n");
|
||||
f.print("\t}};\n\n");
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public:
|
|||
SmtStruct(std::string name, SmtScope &scope) : scope(scope), name(name) {}
|
||||
void insert(IdString field_name, SmtSort sort) {
|
||||
field_names(field_name);
|
||||
auto accessor = scope.unique_name("\\" + name + "_" + RTLIL::unescape_id(field_name));
|
||||
auto accessor = scope.unique_name("\\" + name + "_" + field_name.unescape());
|
||||
fields.emplace_back(Field{sort, accessor});
|
||||
}
|
||||
void write_definition(SExprWriter &w) {
|
||||
|
|
@ -99,7 +99,7 @@ public:
|
|||
w.open(list(name));
|
||||
for(auto field_name : field_names) {
|
||||
w << fn(field_name);
|
||||
w.comment(RTLIL::unescape_id(field_name), true);
|
||||
w.comment(field_name.unescape(), true);
|
||||
}
|
||||
w.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ public:
|
|||
w.open(list(name));
|
||||
for(auto field_name : field_names) {
|
||||
w << fn(field_name);
|
||||
w.comment(RTLIL::unescape_id(field_name), true);
|
||||
w.comment(field_name.unescape(), true);
|
||||
}
|
||||
w.close();
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ struct SmtrModule {
|
|||
w.push();
|
||||
w.open(list());
|
||||
w.open(list("assoc-result"));
|
||||
w << list("assoc", "\"" + RTLIL::unescape_id(input->name) + "\"", inputs_name);
|
||||
w << list("assoc", "\"" + input->name.unescape() + "\"", inputs_name);
|
||||
w.pop();
|
||||
w.open(list("if", "assoc-result"));
|
||||
w << list("cdr", "assoc-result");
|
||||
|
|
@ -298,7 +298,7 @@ struct SmtrModule {
|
|||
w << list(*output_helper_name, outputs_name);
|
||||
w.open(list("list"));
|
||||
for (auto output : ir.outputs()) {
|
||||
w << list("cons", "\"" + RTLIL::unescape_id(output->name) + "\"", output_struct.access("outputs", output->name));
|
||||
w << list("cons", "\"" + output->name.unescape() + "\"", output_struct.access("outputs", output->name));
|
||||
}
|
||||
w.pop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,11 +146,11 @@ struct FunctionalTestGeneric : public Pass
|
|||
log("Dumping module `%s'.\n", module->name);
|
||||
auto fir = Functional::IR::from_module(module);
|
||||
for(auto node : fir)
|
||||
std::cout << RTLIL::unescape_id(node.name()) << " = " << node.to_string([](auto n) { return RTLIL::unescape_id(n.name()); }) << "\n";
|
||||
std::cout << node.name().unescape() << " = " << node.to_string([](auto n) { return n.name().unescape(); }) << "\n";
|
||||
for(auto output : fir.all_outputs())
|
||||
std::cout << RTLIL::unescape_id(output->kind) << " " << RTLIL::unescape_id(output->name) << " = " << RTLIL::unescape_id(output->value().name()) << "\n";
|
||||
std::cout << output->kind.unescape() << " " << output->name.unescape() << " = " << output->value().name().unescape() << "\n";
|
||||
for(auto state : fir.all_states())
|
||||
std::cout << RTLIL::unescape_id(state->kind) << " " << RTLIL::unescape_id(state->name) << " = " << RTLIL::unescape_id(state->next_value().name()) << "\n";
|
||||
std::cout << state->kind.unescape() << " " << state->name.unescape() << " = " << state->next_value().name().unescape() << "\n";
|
||||
}
|
||||
}
|
||||
} FunctionalCxxBackend;
|
||||
|
|
|
|||
3
backends/intersynth/CMakeLists.txt
Normal file
3
backends/intersynth/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
yosys_backend(intersynth
|
||||
intersynth.cc
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/intersynth/intersynth.o
|
||||
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ static std::string netname(std::set<std::string> &conntypes_code, std::set<std::
|
|||
return stringf("CONST_%d_0x%x", sig.size(), sig.as_int());
|
||||
}
|
||||
|
||||
return RTLIL::unescape_id(sig.as_wire()->name);
|
||||
return sig.as_wire()->name.unescape();
|
||||
}
|
||||
|
||||
struct IntersynthBackend : public Backend {
|
||||
|
|
@ -117,7 +117,7 @@ struct IntersynthBackend : public Backend {
|
|||
|
||||
std::set<std::string> conntypes_code, celltypes_code;
|
||||
std::string netlists_code;
|
||||
CellTypes ct(design);
|
||||
NewCellTypes ct(design);
|
||||
|
||||
for (auto lib : libs)
|
||||
ct.setup_design(lib);
|
||||
|
|
@ -133,26 +133,26 @@ struct IntersynthBackend : public Backend {
|
|||
|
||||
if (selected && !design->selected_whole_module(module->name)) {
|
||||
if (design->selected_module(module->name))
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name));
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape());
|
||||
continue;
|
||||
}
|
||||
|
||||
log("Generating netlist %s.\n", log_id(module->name));
|
||||
log("Generating netlist %s.\n", module->name.unescape());
|
||||
|
||||
if (module->memories.size() != 0 || module->processes.size() != 0)
|
||||
log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n");
|
||||
|
||||
std::set<std::string> constcells_code;
|
||||
netlists_code += stringf("# Netlist of module %s\n", log_id(module->name));
|
||||
netlists_code += stringf("netlist %s\n", log_id(module->name));
|
||||
netlists_code += stringf("# Netlist of module %s\n", module->name.unescape());
|
||||
netlists_code += stringf("netlist %s\n", module->name.unescape());
|
||||
|
||||
// Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports
|
||||
for (auto wire : module->wires()) {
|
||||
if (wire->port_input || wire->port_output) {
|
||||
celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n",
|
||||
log_id(wire->name), wire->width, wire->port_input ? "*" : "",
|
||||
wire->port_input ? "input" : "output", log_id(wire->name), wire->width, log_id(wire->name)));
|
||||
netlists_code += stringf("node %s %s PORT %s\n", log_id(wire->name), log_id(wire->name),
|
||||
wire->name.unescape(), wire->width, wire->port_input ? "*" : "",
|
||||
wire->port_input ? "input" : "output", wire->name.unescape(), wire->width, wire->name.unescape()));
|
||||
netlists_code += stringf("node %s %s PORT %s\n", wire->name.unescape(), wire->name.unescape(),
|
||||
netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -163,26 +163,26 @@ struct IntersynthBackend : public Backend {
|
|||
std::string celltype_code, node_code;
|
||||
|
||||
if (!ct.cell_known(cell->type))
|
||||
log_error("Found unknown cell type %s in module!\n", log_id(cell->type));
|
||||
log_error("Found unknown cell type %s in module!\n", cell->type.unescape());
|
||||
|
||||
celltype_code = stringf("celltype %s", log_id(cell->type));
|
||||
node_code = stringf("node %s %s", log_id(cell->name), log_id(cell->type));
|
||||
celltype_code = stringf("celltype %s", cell->type.unescape());
|
||||
node_code = stringf("node %s %s", cell->name.unescape(), cell->type.unescape());
|
||||
for (auto &port : cell->connections()) {
|
||||
RTLIL::SigSpec sig = sigmap(port.second);
|
||||
if (sig.size() != 0) {
|
||||
conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size()));
|
||||
celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", log_id(port.first));
|
||||
node_code += stringf(" %s %s", log_id(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig));
|
||||
celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", port.first.unescape());
|
||||
node_code += stringf(" %s %s", port.first.unescape(), netname(conntypes_code, celltypes_code, constcells_code, sig));
|
||||
}
|
||||
}
|
||||
for (auto ¶m : cell->parameters) {
|
||||
celltype_code += stringf(" cfg:%d %s", int(param.second.size()), log_id(param.first));
|
||||
celltype_code += stringf(" cfg:%d %s", int(param.second.size()), param.first.unescape());
|
||||
if (param.second.size() != 32) {
|
||||
node_code += stringf(" %s '", log_id(param.first));
|
||||
node_code += stringf(" %s '", param.first.unescape());
|
||||
for (int i = param.second.size()-1; i >= 0; i--)
|
||||
node_code += param.second[i] == State::S1 ? "1" : "0";
|
||||
} else
|
||||
node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int());
|
||||
node_code += stringf(" %s 0x%x", param.first.unescape(), param.second.as_int());
|
||||
}
|
||||
|
||||
celltypes_code.insert(celltype_code + "\n");
|
||||
|
|
|
|||
5
backends/jny/CMakeLists.txt
Normal file
5
backends/jny/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
yosys_backend(jny
|
||||
jny.cc
|
||||
PROVIDES
|
||||
jny
|
||||
)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
OBJS += backends/jny/jny.o
|
||||
|
|
@ -91,7 +91,7 @@ struct JnyWriter
|
|||
{
|
||||
_cells.clear();
|
||||
for (auto cell : mod->cells()) {
|
||||
const auto cell_type = escape_string(RTLIL::unescape_id(cell->type));
|
||||
const auto cell_type = escape_string(cell->type.unescape());
|
||||
|
||||
if (_cells.find(cell_type) == _cells.end())
|
||||
_cells.emplace(cell_type, std::vector<Cell*>());
|
||||
|
|
@ -214,7 +214,7 @@ struct JnyWriter
|
|||
void write_cell_conn(const std::pair<RTLIL::IdString, RTLIL::SigSpec>& sig, uint16_t indent_level = 0) {
|
||||
const auto _indent = gen_indent(indent_level);
|
||||
f << _indent << " {\n";
|
||||
f << _indent << " \"name\": \"" << escape_string(RTLIL::unescape_id(sig.first)) << "\",\n";
|
||||
f << _indent << " \"name\": \"" << escape_string(sig.first.unescape()) << "\",\n";
|
||||
f << _indent << " \"signals\": [\n";
|
||||
|
||||
write_sigspec(sig.second, indent_level + 2);
|
||||
|
|
@ -232,7 +232,7 @@ struct JnyWriter
|
|||
const auto _indent = gen_indent(indent_level);
|
||||
|
||||
f << _indent << "{\n";
|
||||
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(mod->name)));
|
||||
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(mod->name.unescape()));
|
||||
f << _indent << " \"cell_sorts\": [\n";
|
||||
|
||||
bool first_sort{true};
|
||||
|
|
@ -275,12 +275,12 @@ struct JnyWriter
|
|||
const auto _indent = gen_indent(indent_level);
|
||||
|
||||
bool first_port{true};
|
||||
for (auto con : port_cell->connections()) {
|
||||
for (auto& con : port_cell->connections()) {
|
||||
if (!first_port)
|
||||
f << ",\n";
|
||||
|
||||
f << _indent << " {\n";
|
||||
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(RTLIL::unescape_id(con.first)));
|
||||
f << stringf(" %s\"name\": \"%s\",\n", _indent, escape_string(con.first.unescape()));
|
||||
f << _indent << " \"direction\": \"";
|
||||
if (port_cell->input(con.first))
|
||||
f << "i";
|
||||
|
|
@ -351,10 +351,10 @@ struct JnyWriter
|
|||
f << stringf(",\n");
|
||||
const auto param_val = param.second;
|
||||
if (!param_val.empty()) {
|
||||
f << stringf(" %s\"%s\": ", _indent, escape_string(RTLIL::unescape_id(param.first)));
|
||||
f << stringf(" %s\"%s\": ", _indent, escape_string(param.first.unescape()));
|
||||
write_param_val(param_val);
|
||||
} else {
|
||||
f << stringf(" %s\"%s\": true", _indent, escape_string(RTLIL::unescape_id(param.first)));
|
||||
f << stringf(" %s\"%s\": true", _indent, escape_string(param.first.unescape()));
|
||||
}
|
||||
|
||||
first_param = false;
|
||||
|
|
@ -366,7 +366,7 @@ struct JnyWriter
|
|||
log_assert(cell != nullptr);
|
||||
|
||||
f << _indent << " {\n";
|
||||
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(RTLIL::unescape_id(cell->name)));
|
||||
f << stringf(" %s\"name\": \"%s\"", _indent, escape_string(cell->name.unescape()));
|
||||
|
||||
if (_include_connections) {
|
||||
f << ",\n" << _indent << " \"connections\": [\n";
|
||||
|
|
|
|||
5
backends/json/CMakeLists.txt
Normal file
5
backends/json/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
yosys_backend(json
|
||||
json.cc
|
||||
PROVIDES
|
||||
json
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/json/json.o
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ struct JsonWriter
|
|||
|
||||
string get_name(IdString name)
|
||||
{
|
||||
return get_string(RTLIL::unescape_id(name));
|
||||
return get_string(name.unescape());
|
||||
}
|
||||
|
||||
string get_bits(SigSpec sig)
|
||||
|
|
@ -152,7 +152,7 @@ struct JsonWriter
|
|||
sigidcounter = 2;
|
||||
|
||||
if (module->has_processes()) {
|
||||
log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module));
|
||||
log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", module);
|
||||
}
|
||||
|
||||
f << stringf(" %s: {\n", get_name(module->name));
|
||||
|
|
@ -316,13 +316,13 @@ struct JsonWriter
|
|||
f << stringf(" /* %3d */ [ ", node_idx);
|
||||
if (node.portbit >= 0)
|
||||
f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "",
|
||||
log_id(node.portname), node.portbit);
|
||||
node.portname.unescape(), node.portbit);
|
||||
else if (node.left_parent < 0 && node.right_parent < 0)
|
||||
f << stringf("\"%s\"", node.inverter ? "true" : "false");
|
||||
else
|
||||
f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent);
|
||||
for (auto &op : node.outports)
|
||||
f << stringf(", \"%s\", %d", log_id(op.first), op.second);
|
||||
f << stringf(", \"%s\", %d", op.first.unescape(), op.second);
|
||||
f << stringf(" ]");
|
||||
node_idx++;
|
||||
}
|
||||
|
|
|
|||
11
backends/rtlil/CMakeLists.txt
Normal file
11
backends/rtlil/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
yosys_backend(rtlil
|
||||
rtlil_backend.cc
|
||||
rtlil_backend.h
|
||||
PROVIDES
|
||||
dump
|
||||
DATA_DIR
|
||||
include/backends/rtlil
|
||||
DATA_FILES
|
||||
rtlil_backend.h
|
||||
ESSENTIAL
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/rtlil/rtlil_backend.o
|
||||
|
||||
3
backends/simplec/CMakeLists.txt
Normal file
3
backends/simplec/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
yosys_backend(simplec
|
||||
simplec.cc
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/simplec/simplec.o
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ struct HierDirtyFlags
|
|||
for (Cell *cell : module->cells()) {
|
||||
Module *mod = module->design->module(cell->type);
|
||||
if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this,
|
||||
prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name));
|
||||
prefix + cid(cell->name) + ".", log_prefix + "." + prefix + cell->name.unescape());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,23 +354,23 @@ struct SimplecWorker
|
|||
struct_declarations.push_back(" // Input Ports");
|
||||
for (Wire *w : mod->wires())
|
||||
if (w->port_input)
|
||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w)));
|
||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w));
|
||||
|
||||
struct_declarations.push_back("");
|
||||
struct_declarations.push_back(" // Output Ports");
|
||||
for (Wire *w : mod->wires())
|
||||
if (!w->port_input && w->port_output)
|
||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w)));
|
||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w));
|
||||
|
||||
struct_declarations.push_back("");
|
||||
struct_declarations.push_back(" // Internal Wires");
|
||||
for (Wire *w : mod->wires())
|
||||
if (!w->port_input && !w->port_output)
|
||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), log_id(w)));
|
||||
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width), cid(w->name), w));
|
||||
|
||||
for (Cell *c : mod->cells())
|
||||
if (design->module(c->type))
|
||||
struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), log_id(c)));
|
||||
struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type), cid(c->name), c));
|
||||
|
||||
struct_declarations.push_back(stringf("};"));
|
||||
struct_declarations.push_back("#endif");
|
||||
|
|
@ -391,7 +391,7 @@ struct SimplecWorker
|
|||
|
||||
log_assert(y.wire);
|
||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
||||
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||
|
||||
work->set_dirty(y);
|
||||
return;
|
||||
|
|
@ -418,7 +418,7 @@ struct SimplecWorker
|
|||
|
||||
log_assert(y.wire);
|
||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
||||
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||
|
||||
work->set_dirty(y);
|
||||
return;
|
||||
|
|
@ -441,7 +441,7 @@ struct SimplecWorker
|
|||
|
||||
log_assert(y.wire);
|
||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
||||
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||
|
||||
work->set_dirty(y);
|
||||
return;
|
||||
|
|
@ -466,7 +466,7 @@ struct SimplecWorker
|
|||
|
||||
log_assert(y.wire);
|
||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
||||
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||
|
||||
work->set_dirty(y);
|
||||
return;
|
||||
|
|
@ -490,13 +490,13 @@ struct SimplecWorker
|
|||
|
||||
log_assert(y.wire);
|
||||
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
|
||||
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
|
||||
stringf(" // %s (%s)", cell, cell->type.unescape()));
|
||||
|
||||
work->set_dirty(y);
|
||||
return;
|
||||
}
|
||||
|
||||
log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type));
|
||||
log_error("No C model for %s available at the moment (FIXME).\n", cell->type.unescape());
|
||||
}
|
||||
|
||||
void eval_dirty(HierDirtyFlags *work)
|
||||
|
|
@ -517,7 +517,7 @@ struct SimplecWorker
|
|||
if (chunk.wire == nullptr)
|
||||
continue;
|
||||
if (verbose)
|
||||
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
|
||||
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix, chunk.wire, chunk.offset+chunk.width-1, chunk.offset);
|
||||
funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix, log_signal(chunk)));
|
||||
}
|
||||
|
||||
|
|
@ -539,8 +539,8 @@ struct SimplecWorker
|
|||
work->parent->set_dirty(parent_bit);
|
||||
|
||||
if (verbose)
|
||||
log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset,
|
||||
work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset);
|
||||
log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset,
|
||||
work->parent->log_prefix.c_str(), parent_bit.wire, parent_bit.offset);
|
||||
}
|
||||
|
||||
for (auto &port : bit2cell[work->module][bit])
|
||||
|
|
@ -556,12 +556,12 @@ struct SimplecWorker
|
|||
child->set_dirty(child_bit);
|
||||
|
||||
if (verbose)
|
||||
log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, log_id(bit.wire), bit.offset,
|
||||
work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset);
|
||||
log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix, bit.wire, bit.offset,
|
||||
work->log_prefix.c_str(), std::get<0>(port), child_bit.wire, child_bit.offset);
|
||||
} else {
|
||||
if (verbose)
|
||||
log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, log_id(std::get<0>(port)),
|
||||
work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
|
||||
log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix, std::get<0>(port),
|
||||
work->log_prefix.c_str(), bit.wire, bit.offset);
|
||||
work->set_dirty(std::get<0>(port));
|
||||
}
|
||||
}
|
||||
|
|
@ -576,10 +576,10 @@ struct SimplecWorker
|
|||
if (cell == nullptr || topoidx.at(cell) < topoidx.at(c))
|
||||
cell = c;
|
||||
|
||||
string hiername = work->log_prefix + "." + log_id(cell);
|
||||
string hiername = work->log_prefix + "." + cell->name.unescape();
|
||||
|
||||
if (verbose)
|
||||
log(" Evaluating %s (%s, best of %d).\n", hiername, log_id(cell->type), GetSize(work->dirty_cells));
|
||||
log(" Evaluating %s (%s, best of %d).\n", hiername, cell->type.unescape(), GetSize(work->dirty_cells));
|
||||
|
||||
if (activated_cells.count(hiername))
|
||||
reactivated_cells.insert(hiername);
|
||||
|
|
@ -618,8 +618,8 @@ struct SimplecWorker
|
|||
|
||||
if (verbose)
|
||||
log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
|
||||
work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset,
|
||||
work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
|
||||
work->log_prefix.c_str(), canonical_bit.wire, canonical_bit.offset,
|
||||
work->log_prefix.c_str(), bit.wire, bit.offset);
|
||||
}
|
||||
|
||||
work->sticky_dirty_bits.clear();
|
||||
|
|
@ -716,7 +716,7 @@ struct SimplecWorker
|
|||
{
|
||||
create_module_struct(mod);
|
||||
|
||||
HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name));
|
||||
HierDirtyFlags work(mod, IdString(), nullptr, "state->", mod->name.unescape());
|
||||
|
||||
make_init_func(&work);
|
||||
make_eval_func(&work);
|
||||
|
|
|
|||
20
backends/smt2/CMakeLists.txt
Normal file
20
backends/smt2/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
yosys_backend(smt2
|
||||
smt2.cc
|
||||
REQUIRES
|
||||
json11
|
||||
DATA_DIR
|
||||
python3
|
||||
DATA_FILES
|
||||
smtio.py
|
||||
ywio.py
|
||||
REQUIRES
|
||||
bmuxmap
|
||||
demuxmap
|
||||
)
|
||||
|
||||
yosys_python_executable(yosys-smtbmc smtbmc.py
|
||||
INSTALL_IF YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY
|
||||
)
|
||||
yosys_python_executable(yosys-witness witness.py
|
||||
INSTALL_IF YOSYS_INSTALL_DRIVER OR YOSYS_INSTALL_LIBRARY
|
||||
)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
|
||||
OBJS += backends/smt2/smt2.o
|
||||
|
||||
ifneq ($(CONFIG),mxe)
|
||||
ifneq ($(CONFIG),emcc)
|
||||
|
||||
# MSYS targets support yosys-smtbmc, but require a launcher script
|
||||
ifeq ($(CONFIG),$(filter $(CONFIG),msys2 msys2-64))
|
||||
TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc.exe $(PROGRAM_PREFIX)yosys-smtbmc-script.py
|
||||
TARGETS += $(PROGRAM_PREFIX)yosys-witness.exe $(PROGRAM_PREFIX)yosys-witness-script.py
|
||||
# Needed to find the Python interpreter for yosys-smtbmc scripts.
|
||||
# Override if necessary, it is only used for msys2 targets.
|
||||
PYTHON := $(shell cygpath -w -m $(PREFIX)/bin/python3)
|
||||
|
||||
$(PROGRAM_PREFIX)yosys-smtbmc-script.py: backends/smt2/smtbmc.py
|
||||
$(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' \
|
||||
-e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@
|
||||
|
||||
$(PROGRAM_PREFIX)yosys-witness-script.py: backends/smt2/witness.py
|
||||
$(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' \
|
||||
-e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@
|
||||
|
||||
$(PROGRAM_PREFIX)yosys-smtbmc.exe: misc/launcher.c $(PROGRAM_PREFIX)yosys-smtbmc-script.py
|
||||
$(P) $(CXX) -DGUI=0 -O -s -o $@ $<
|
||||
|
||||
$(PROGRAM_PREFIX)yosys-witness.exe: misc/launcher.c $(PROGRAM_PREFIX)yosys-witness-script.py
|
||||
$(P) $(CXX) -DGUI=0 -O -s -o $@ $<
|
||||
# Other targets
|
||||
else
|
||||
TARGETS += $(PROGRAM_PREFIX)yosys-smtbmc $(PROGRAM_PREFIX)yosys-witness
|
||||
|
||||
$(PROGRAM_PREFIX)yosys-smtbmc: backends/smt2/smtbmc.py
|
||||
$(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' < $< > $@.new
|
||||
$(Q) chmod +x $@.new
|
||||
$(Q) mv $@.new $@
|
||||
|
||||
$(PROGRAM_PREFIX)yosys-witness: backends/smt2/witness.py
|
||||
$(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/$(PROGRAM_PREFIX)yosys/python3"]]|;' < $< > $@.new
|
||||
$(Q) chmod +x $@.new
|
||||
$(Q) mv $@.new $@
|
||||
endif
|
||||
|
||||
$(eval $(call add_share_file,share/python3,backends/smt2/smtio.py))
|
||||
$(eval $(call add_share_file,share/python3,backends/smt2/ywio.py))
|
||||
endif
|
||||
endif
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include "kernel/mem.h"
|
||||
#include "libs/json11/json11.hpp"
|
||||
|
|
@ -32,7 +32,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
struct Smt2Worker
|
||||
{
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
SigMap sigmap;
|
||||
RTLIL::Module *module;
|
||||
bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode;
|
||||
|
|
@ -60,7 +60,7 @@ struct Smt2Worker
|
|||
const char *get_id(IdString n)
|
||||
{
|
||||
if (ids.count(n) == 0) {
|
||||
std::string str = log_id(n);
|
||||
std::string str = n.unescape();
|
||||
for (int i = 0; i < GetSize(str); i++) {
|
||||
if (str[i] == '\\')
|
||||
str[i] = '/';
|
||||
|
|
@ -207,7 +207,7 @@ struct Smt2Worker
|
|||
}
|
||||
else if (is_output || !is_input)
|
||||
log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n",
|
||||
log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type));
|
||||
conn.first.unescape(), module, cell, cell->type.unescape());
|
||||
|
||||
if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_)) && conn.first.in(ID::CLK, ID::C))
|
||||
{
|
||||
|
|
@ -448,7 +448,7 @@ struct Smt2Worker
|
|||
}
|
||||
|
||||
if (verbose)
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||
|
||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
||||
get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(bit)));
|
||||
|
|
@ -498,7 +498,7 @@ struct Smt2Worker
|
|||
processed_expr = stringf("((_ extract %d 0) %s)", GetSize(sig_y)-1, processed_expr);
|
||||
|
||||
if (verbose)
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||
|
||||
if (type == 'b') {
|
||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
||||
|
|
@ -529,7 +529,7 @@ struct Smt2Worker
|
|||
processed_expr += ch;
|
||||
|
||||
if (verbose)
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||
|
||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool %s) ; %s\n",
|
||||
get_id(module), idcounter, get_id(module), processed_expr.c_str(), log_signal(sig_y)));
|
||||
|
|
@ -541,7 +541,7 @@ struct Smt2Worker
|
|||
{
|
||||
if (verbose)
|
||||
log("%*s=> export_cell %s (%s) [%s]\n", 2+2*GetSize(recursive_cells), "",
|
||||
log_id(cell), log_id(cell->type), exported_cells.count(cell) ? "old" : "new");
|
||||
cell, cell->type.unescape(), exported_cells.count(cell) ? "old" : "new");
|
||||
|
||||
if (recursive_cells.count(cell))
|
||||
log_error("Found logic loop in module %s! See cell %s.\n", get_id(module), get_id(cell));
|
||||
|
|
@ -750,7 +750,7 @@ struct Smt2Worker
|
|||
get_bv(sig_b.extract(i*width, width)).c_str(), processed_expr.c_str());
|
||||
|
||||
if (verbose)
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", log_id(cell));
|
||||
log("%*s-> import cell: %s\n", 2+2*GetSize(recursive_cells), "", cell);
|
||||
|
||||
RTLIL::SigSpec sig = sigmap(cell->getPort(ID::Y));
|
||||
decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
||||
|
|
@ -786,9 +786,9 @@ struct Smt2Worker
|
|||
has_async_wr = true;
|
||||
}
|
||||
if (has_async_wr && has_sync_wr)
|
||||
log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module));
|
||||
log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", cell, module);
|
||||
|
||||
decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(mem->memid), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync"));
|
||||
decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", mem->memid.unescape(), abits, mem->width, GetSize(mem->rd_ports), GetSize(mem->wr_ports), has_async_wr ? "async" : "sync"));
|
||||
decls.push_back(witness_memory(get_id(mem->memid), cell, mem));
|
||||
|
||||
string memstate;
|
||||
|
|
@ -813,7 +813,7 @@ struct Smt2Worker
|
|||
|
||||
if (port.clk_enable)
|
||||
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
|
||||
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module));
|
||||
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module);
|
||||
|
||||
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
||||
get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
|
||||
|
|
@ -857,7 +857,7 @@ struct Smt2Worker
|
|||
|
||||
if (port.clk_enable)
|
||||
log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
|
||||
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), log_id(mem->memid), log_id(module));
|
||||
"Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(port.data), mem->memid.unescape(), module);
|
||||
|
||||
decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
|
||||
get_id(module), i, get_id(mem->memid), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
|
||||
|
|
@ -928,30 +928,30 @@ struct Smt2Worker
|
|||
|
||||
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smt2`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type, module, cell);
|
||||
}
|
||||
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type, module, cell);
|
||||
}
|
||||
|
||||
void verify_smtlib2_module()
|
||||
{
|
||||
if (!module->get_blackbox_attribute())
|
||||
log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", log_id(module));
|
||||
log_error("Module %s with smtlib2_module attribute must also have blackbox attribute.\n", module);
|
||||
if (module->cells().size() > 0)
|
||||
log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", log_id(module));
|
||||
log_error("Module %s with smtlib2_module attribute must not have any cells inside it.\n", module);
|
||||
for (auto wire : module->wires())
|
||||
if (!wire->port_id)
|
||||
log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", log_id(module),
|
||||
log_id(wire));
|
||||
log_error("Wire %s.%s must be input or output since module has smtlib2_module attribute.\n", module,
|
||||
wire);
|
||||
}
|
||||
|
||||
void run()
|
||||
|
|
@ -991,8 +991,8 @@ struct Smt2Worker
|
|||
}
|
||||
bool is_smtlib2_comb_expr = wire->has_attribute(ID::smtlib2_comb_expr);
|
||||
if (is_smtlib2_comb_expr && !is_smtlib2_module)
|
||||
log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", log_id(module),
|
||||
log_id(wire));
|
||||
log_error("smtlib2_comb_expr is only valid in a module with the smtlib2_module attribute: wire %s.%s", module,
|
||||
wire);
|
||||
if (wire->port_id || is_register || contains_clock || wire->get_bool_attribute(ID::keep) || (wiresmode && wire->name.isPublic())) {
|
||||
RTLIL::SigSpec sig = sigmap(wire);
|
||||
std::vector<std::string> comments;
|
||||
|
|
@ -1023,10 +1023,10 @@ struct Smt2Worker
|
|||
smtlib2_comb_expr =
|
||||
"(let (\n" + smtlib2_inputs + ")\n" + wire->get_string_attribute(ID::smtlib2_comb_expr) + "\n)";
|
||||
if (wire->port_input || !wire->port_output)
|
||||
log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", log_id(module), log_id(wire));
|
||||
log_error("smtlib2_comb_expr is only valid on output: wire %s.%s", module, wire);
|
||||
if (!bvmode && GetSize(sig) > 1)
|
||||
log_error("smtlib2_comb_expr is unsupported on multi-bit wires when -nobv is specified: wire %s.%s",
|
||||
log_id(module), log_id(wire));
|
||||
module, wire);
|
||||
|
||||
comments.push_back(witness_signal("blackbox", wire->width, 0, get_id(wire), -1, wire));
|
||||
}
|
||||
|
|
@ -1075,7 +1075,7 @@ struct Smt2Worker
|
|||
if (wire->attributes.count(ID::init)) {
|
||||
if (is_smtlib2_module)
|
||||
log_error("init attribute not allowed on wires in module with smtlib2_module attribute: wire %s.%s",
|
||||
log_id(module), log_id(wire));
|
||||
module, wire);
|
||||
|
||||
RTLIL::SigSpec sig = sigmap(wire);
|
||||
Const val = wire->attributes.at(ID::init);
|
||||
|
|
@ -1381,7 +1381,7 @@ struct Smt2Worker
|
|||
}
|
||||
}
|
||||
|
||||
if (verbose) log("=> finalizing SMT2 representation of %s.\n", log_id(module));
|
||||
if (verbose) log("=> finalizing SMT2 representation of %s.\n", module);
|
||||
|
||||
for (auto c : hiercells) {
|
||||
assert_list.push_back(stringf("(|%s_a| (|%s_h %s| state))", get_id(c->type), get_id(module), get_id(c->name)));
|
||||
|
|
@ -1867,12 +1867,12 @@ struct Smt2Backend : public Backend {
|
|||
for (auto &dep : it.second)
|
||||
if (module_deps.count(dep) > 0)
|
||||
goto not_ready_yet;
|
||||
// log("Next in topological sort: %s\n", log_id(it.first->name));
|
||||
// log("Next in topological sort: %s\n", it.first->name.unescape());
|
||||
sorted_modules.push_back(it.first);
|
||||
not_ready_yet:;
|
||||
}
|
||||
if (sorted_modules_idx == sorted_modules.size())
|
||||
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name));
|
||||
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", module_deps.begin()->first->name.unescape());
|
||||
while (sorted_modules_idx < sorted_modules.size())
|
||||
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
|
||||
}
|
||||
|
|
@ -1902,7 +1902,7 @@ struct Smt2Backend : public Backend {
|
|||
if (module->has_processes_warn())
|
||||
continue;
|
||||
|
||||
log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module));
|
||||
log("Creating SMT-LIBv2 representation of module %s.\n", module);
|
||||
|
||||
Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache);
|
||||
worker.run();
|
||||
|
|
|
|||
4
backends/smt2/smtbmc.py
Normal file → Executable file
4
backends/smt2/smtbmc.py
Normal file → Executable file
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!@PYTHON_SHEBANG@
|
||||
#
|
||||
# yosys -- Yosys Open SYnthesis Suite
|
||||
#
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
#
|
||||
|
||||
import os, sys, getopt, re, bisect, json
|
||||
##yosys-sys-path##
|
||||
sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/@YOSYS_PROGRAM_PREFIX@yosys/python3"]]
|
||||
from smtio import SmtIo, SmtOpts, MkVcd
|
||||
from ywio import ReadWitness, WriteWitness, WitnessValues
|
||||
from collections import defaultdict
|
||||
|
|
|
|||
4
backends/smt2/witness.py
Normal file → Executable file
4
backends/smt2/witness.py
Normal file → Executable file
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!@PYTHON_SHEBANG@
|
||||
#
|
||||
# yosys -- Yosys Open SYnthesis Suite
|
||||
#
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
#
|
||||
|
||||
import os, sys, itertools, re
|
||||
##yosys-sys-path##
|
||||
sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/@YOSYS_PROGRAM_PREFIX@yosys/python3"]]
|
||||
import json
|
||||
import click
|
||||
|
||||
|
|
|
|||
7
backends/smv/CMakeLists.txt
Normal file
7
backends/smv/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
yosys_backend(smv
|
||||
smv.cc
|
||||
REQUIRES
|
||||
bmuxmap
|
||||
demuxmap
|
||||
bwmuxmap
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/smv/smv.o
|
||||
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
#include "kernel/rtlil.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
#include "kernel/log.h"
|
||||
#include <string>
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
|
||||
struct SmvWorker
|
||||
{
|
||||
CellTypes ct;
|
||||
NewCellTypes ct;
|
||||
SigMap sigmap;
|
||||
RTLIL::Module *module;
|
||||
std::ostream &f;
|
||||
|
|
@ -217,7 +217,7 @@ struct SmvWorker
|
|||
partial_assignment_wires.insert(wire);
|
||||
|
||||
if (wire->port_input)
|
||||
inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire)));
|
||||
inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, wire));
|
||||
|
||||
if (wire->attributes.count(ID::init))
|
||||
assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at(ID::init))));
|
||||
|
|
@ -579,18 +579,18 @@ struct SmvWorker
|
|||
if (cell->type[0] == '$') {
|
||||
if (cell->type.in(ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)) || cell->type.str().substr(0, 6) == "$_SDFF" || (cell->type.str().substr(0, 6) == "$_DFFE" && cell->type.str().size() == 10)) {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
if (cell->type.in(ID($sr), ID($dlatch), ID($adlatch), ID($dlatchsr)) || cell->type.str().substr(0, 8) == "$_DLATCH" || cell->type.str().substr(0, 5) == "$_SR_") {
|
||||
log_error("Unsupported cell type %s for cell %s.%s -- please run `clk2fflogic` before `write_smv`.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
log_error("Unsupported cell type %s for cell %s.%s.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
}
|
||||
|
||||
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
|
||||
|
|
@ -799,7 +799,7 @@ struct SmvBackend : public Backend {
|
|||
|
||||
*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", module);
|
||||
SmvWorker worker(module, verbose, *f);
|
||||
worker.run();
|
||||
|
||||
|
|
@ -819,7 +819,7 @@ struct SmvBackend : public Backend {
|
|||
*f << stringf("-- SMV description generated by %s\n", yosys_maybe_version());
|
||||
|
||||
for (auto module : modules) {
|
||||
log("Creating SMV representation of module %s.\n", log_id(module));
|
||||
log("Creating SMV representation of module %s.\n", module);
|
||||
SmvWorker worker(module, verbose, *f);
|
||||
worker.run();
|
||||
}
|
||||
|
|
|
|||
3
backends/spice/CMakeLists.txt
Normal file
3
backends/spice/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
yosys_backend(spice
|
||||
spice.cc
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/spice/spice.o
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ PRIVATE_NAMESPACE_BEGIN
|
|||
static string spice_id2str(IdString id)
|
||||
{
|
||||
static const char *escape_chars = "$\\[]()<>=";
|
||||
string s = RTLIL::unescape_id(id);
|
||||
string s = id.unescape();
|
||||
|
||||
for (auto &ch : s)
|
||||
if (strchr(escape_chars, ch) != nullptr) ch = '_';
|
||||
|
|
@ -82,7 +82,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De
|
|||
if (design->module(cell->type) == nullptr)
|
||||
{
|
||||
log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n",
|
||||
log_id(cell->type), log_id(module), log_id(cell));
|
||||
cell->type.unescape(), module, cell);
|
||||
for (auto &conn : cell->connections()) {
|
||||
RTLIL::SigSpec sig = sigmap(conn.second);
|
||||
port_sigs.push_back(sig);
|
||||
|
|
@ -224,9 +224,9 @@ struct SpiceBackend : public Backend {
|
|||
continue;
|
||||
|
||||
if (module->processes.size() != 0)
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", log_id(module));
|
||||
log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", module);
|
||||
if (module->memories.size() != 0)
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", log_id(module));
|
||||
log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", module);
|
||||
|
||||
if (module->name == RTLIL::escape_id(top_module_name)) {
|
||||
top_module = module;
|
||||
|
|
|
|||
3
backends/table/CMakeLists.txt
Normal file
3
backends/table/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
yosys_backend(table
|
||||
table.cc
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/table/table.o
|
||||
|
||||
|
|
@ -77,8 +77,8 @@ struct TableBackend : public Backend {
|
|||
if (wire->port_id == 0)
|
||||
continue;
|
||||
|
||||
*f << log_id(module) << "\t";
|
||||
*f << log_id(wire) << "\t";
|
||||
*f << module->name.unescape() << "\t";
|
||||
*f << wire->name.unescape() << "\t";
|
||||
*f << "-" << "\t";
|
||||
*f << "-" << "\t";
|
||||
|
||||
|
|
@ -97,10 +97,10 @@ struct TableBackend : public Backend {
|
|||
for (auto cell : module->cells())
|
||||
for (auto conn : cell->connections())
|
||||
{
|
||||
*f << log_id(module) << "\t";
|
||||
*f << log_id(cell) << "\t";
|
||||
*f << log_id(cell->type) << "\t";
|
||||
*f << log_id(conn.first) << "\t";
|
||||
*f << module->name.unescape() << "\t";
|
||||
*f << cell->name.unescape() << "\t";
|
||||
*f << cell->type.unescape() << "\t";
|
||||
*f << conn.first.unescape() << "\t";
|
||||
|
||||
if (cell->input(conn.first) && cell->output(conn.first))
|
||||
*f << "inout" << "\t";
|
||||
|
|
|
|||
8
backends/verilog/CMakeLists.txt
Normal file
8
backends/verilog/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
yosys_backend(verilog
|
||||
verilog_backend.cc
|
||||
verilog_backend.h
|
||||
REQUIRES
|
||||
bmuxmap
|
||||
demuxmap
|
||||
clean_zerowidth
|
||||
)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/verilog/verilog_backend.o
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ USING_YOSYS_NAMESPACE
|
|||
|
||||
using namespace VERILOG_BACKEND;
|
||||
|
||||
const pool<string> VERILOG_BACKEND::verilog_keywords() {
|
||||
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",
|
||||
|
|
@ -2406,7 +2406,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
|
|||
log_warning("Module %s contains RTLIL processes with sync rules. Such RTLIL "
|
||||
"processes can't always be mapped directly to Verilog always blocks. "
|
||||
"unintended changes in simulation behavior are possible! Use \"proc\" "
|
||||
"to convert processes to logic networks and registers.\n", log_id(module));
|
||||
"to convert processes to logic networks and registers.\n", module);
|
||||
|
||||
f << stringf("\n");
|
||||
for (auto it = module->processes.begin(); it != module->processes.end(); ++it)
|
||||
|
|
@ -2740,7 +2740,7 @@ struct VerilogBackend : public Backend {
|
|||
continue;
|
||||
if (selected && !design->selected_whole_module(module->name)) {
|
||||
if (design->selected_module(module->name))
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name));
|
||||
log_cmd_error("Can't handle partially selected module %s!\n", module->name.unescape());
|
||||
continue;
|
||||
}
|
||||
log("Dumping module `%s'.\n", module->name);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
YOSYS_NAMESPACE_BEGIN
|
||||
namespace VERILOG_BACKEND {
|
||||
|
||||
const pool<string> verilog_keywords();
|
||||
const pool<string> &verilog_keywords();
|
||||
bool char_is_verilog_escaped(char c);
|
||||
bool id_is_verilog_escaped(const std::string &str);
|
||||
|
||||
|
|
|
|||
40
cmake/CheckLibcFeatures.cmake
Normal file
40
cmake/CheckLibcFeatures.cmake
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
include(CMakePushCheckState)
|
||||
include(CheckSourceCompiles)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
function(check_glob)
|
||||
check_cxx_symbol_exists(glob "glob.h" HAVE_GLOB)
|
||||
return (PROPAGATE HAVE_BLOB)
|
||||
endfunction()
|
||||
|
||||
function(check_pthread_create)
|
||||
if (Threads_FOUND)
|
||||
# On WASI, `pthread_create()` is always available, but always fails on triples without threading
|
||||
# support. Probe for it while requesting the stub implementation to be hidden, otherwise we will
|
||||
# end up always crashing at runtime on thread creation.
|
||||
cmake_push_check_state(RESET)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_WASI_STRICT_PTHREAD)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
check_source_compiles(CXX [[
|
||||
#include <pthread.h>
|
||||
int main() {
|
||||
pthread_create(0, 0, 0, 0);
|
||||
}
|
||||
]] HAVE_PTHREAD_CREATE)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
return (PROPAGATE HAVE_PTHREAD_CREATE)
|
||||
endfunction()
|
||||
|
||||
function(check_system)
|
||||
check_cxx_symbol_exists(system "stdlib.h" HAVE_SYSTEM)
|
||||
endfunction()
|
||||
|
||||
function(check_popen)
|
||||
check_cxx_symbol_exists(popen "stdio.h" HAVE_POPEN)
|
||||
if (NOT HAVE_POPEN)
|
||||
unset(HAVE_POPEN CACHE)
|
||||
# https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/popen-wpopen
|
||||
check_cxx_symbol_exists(_popen "stdio.h" HAVE_POPEN)
|
||||
endif()
|
||||
endfunction()
|
||||
35
cmake/Condition.cmake
Normal file
35
cmake/Condition.cmake
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Syntax:
|
||||
#
|
||||
# condition(<var> <expr>...)
|
||||
#
|
||||
# If `<expr>...` is truthful (evaluated as in `if()`) then assigns 1 to `<var>`, else assigns 0.
|
||||
# The assigned value is `0`/`1` rather than `TRUE`/`FALSE` for ease of use in generator expressions.
|
||||
# Note that `<expr>...` *must* be unquoted.
|
||||
#
|
||||
# To understand how a certain outcome is reached, reconfigure the project with `--log-level VERBOSE`.
|
||||
#
|
||||
# Believe it or not, CMake doesn't have this built in!
|
||||
#
|
||||
macro(condition var)
|
||||
if (${ARGN})
|
||||
set(${var} 1)
|
||||
else()
|
||||
set(${var} 0)
|
||||
endif()
|
||||
|
||||
set(_debug_expr)
|
||||
foreach (token ${ARGN})
|
||||
if (DEFINED ${token})
|
||||
if (${${token}})
|
||||
list(APPEND _debug_expr "${token}:1")
|
||||
else()
|
||||
list(APPEND _debug_expr "${token}:0")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND _debug_expr "${token}")
|
||||
endif()
|
||||
endforeach()
|
||||
string(JOIN " " _debug_expr ${_debug_expr})
|
||||
message(VERBOSE " ${var} = ${${var}} (${_debug_expr})")
|
||||
unset(_debug_expr)
|
||||
endmacro()
|
||||
24
cmake/FindDlfcn.cmake
Normal file
24
cmake/FindDlfcn.cmake
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
include(CMakePushCheckState)
|
||||
include(CheckCXXSymbolExists)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if (WIN32 OR MSYS)
|
||||
# Windows; dlopen is available via a polyfill `libs/dlfcn-win32`.
|
||||
set(Dlfcn_LIBRARIES dlfcn)
|
||||
else()
|
||||
# Unix and Wasm; dlopen may or may not be available depending on platform.
|
||||
cmake_push_check_state(RESET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_DL_LIBS})
|
||||
check_cxx_symbol_exists(dlopen "dlfcn.h" HAVE_DLOPEN)
|
||||
cmake_pop_check_state()
|
||||
|
||||
if (HAVE_DLOPEN)
|
||||
add_library(dlfcn INTERFACE)
|
||||
target_link_libraries(dlfcn INTERFACE ${CMAKE_DL_LIBS})
|
||||
set(Dlfcn_LIBRARIES dlfcn)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package_handle_standard_args(Dlfcn
|
||||
REQUIRED_VARS Dlfcn_LIBRARIES
|
||||
)
|
||||
44
cmake/FindPyosysEnv.cmake
Normal file
44
cmake/FindPyosysEnv.cmake
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# We need a *third* `FindPython`-style call in this codebase because the host
|
||||
# `Python3_EXECUTABLE` may not have pybind11 and cxxheaderparser installed,
|
||||
# and installing it can be onerous. To work around this problem we try to detect
|
||||
# whether the host interpreter has the necessary dependencies first, and if it
|
||||
# does not, fall back to using `uv`.
|
||||
|
||||
foreach (strategy virtualenv host uv fail)
|
||||
if (strategy STREQUAL "virtualenv")
|
||||
set(PyosysEnv_PYTHON $ENV{VIRTUAL_ENV}/bin/python)
|
||||
elseif (strategy STREQUAL "host")
|
||||
set(PyosysEnv_PYTHON ${Python3_EXECUTABLE})
|
||||
elseif (strategy STREQUAL "uv")
|
||||
set(PyosysEnv_PYTHON uv run --no-project --with pybind11>3,<4 --with cxxheaderparser python)
|
||||
else()
|
||||
set(PyosysEnv_PYTHON)
|
||||
break()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${PyosysEnv_PYTHON} -m pybind11 --includes
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE output
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if (result EQUAL 0)
|
||||
string(REGEX REPLACE " ?-I" ";" pybind11_INCLUDE_DIR "${output}")
|
||||
list(FILTER pybind11_INCLUDE_DIR INCLUDE REGEX "/pybind11/")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${PyosysEnv_PYTHON} ${CMAKE_SOURCE_DIR}/pyosys/generator.py --help
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_QUIET
|
||||
ERROR_QUIET
|
||||
)
|
||||
if (result EQUAL 0)
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
find_package_handle_standard_args(PyosysEnv
|
||||
REQUIRED_VARS PyosysEnv_PYTHON pybind11_INCLUDE_DIR
|
||||
)
|
||||
28
cmake/FindPython3Devel.cmake
Normal file
28
cmake/FindPython3Devel.cmake
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Wrapper to improve behavior of `FindPython3` during cross-compilation.
|
||||
# Does not entirely fix the problem; CMake 4.0 introduces `Python_ARTIFACTS_PREFIX`, which will.
|
||||
|
||||
# Stash the package found status
|
||||
get_property(packages_found GLOBAL PROPERTY PACKAGES_FOUND)
|
||||
get_property(packages_not_found GLOBAL PROPERTY PACKAGES_NOT_FOUND)
|
||||
get_property(required_version GLOBAL PROPERTY _CMAKE_Python3_REQUIRED_VERSION)
|
||||
|
||||
# A hack to make pyosys buildable in wheel-only environments.
|
||||
# `Interpreter` is a part of the component set to ensure that a Python implementation without
|
||||
# an interpreter that's earlier in the search order won't be selected instead of the desired one.
|
||||
# (This is awful and should be removed once CMake 4.0 is here.)
|
||||
if (YOSYS_BUILD_PYTHON_ONLY)
|
||||
set(components Interpreter Development.Module)
|
||||
else()
|
||||
set(components Interpreter Development)
|
||||
endif()
|
||||
|
||||
# The `EXACT` specifier prevents the situation of `FindPython3` discovering a newer libpython-dev
|
||||
# than the interpreter found in the past, rejecting it because it is too new, and giving up.
|
||||
find_package(Python3 EXACT ${Python3_VERSION} COMPONENTS ${components})
|
||||
if (Python3_Development.Embed_FOUND OR Python3_Development.Module_FOUND)
|
||||
set(Python3Devel_FOUND YES)
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY PACKAGES_FOUND "${packages_found}")
|
||||
set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${packages_not_found}")
|
||||
set_property(GLOBAL PROPERTY _CMAKE_Python3_REQUIRED_VERSION "${required_version}")
|
||||
14
cmake/GetPyosysVersion.cmake
Normal file
14
cmake/GetPyosysVersion.cmake
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
cmake_minimum_required(VERSION 3.27)
|
||||
set(CMAKE_MESSAGE_LOG_LEVEL ERROR)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(YosysVersion)
|
||||
|
||||
yosys_extract_version()
|
||||
if (YOSYS_VERSION_COMMIT EQUAL "0")
|
||||
set(yosys_version "${YOSYS_VERSION_MAJOR}.${YOSYS_VERSION_MINOR}")
|
||||
elseif (YOSYS_VERSION_COMMIT STREQUAL "")
|
||||
set(yosys_version "${YOSYS_VERSION_MAJOR}.${YOSYS_VERSION_MINOR}.post9999")
|
||||
else()
|
||||
set(yosys_version "${YOSYS_VERSION_MAJOR}.${YOSYS_VERSION_MINOR}.post${YOSYS_VERSION_COMMIT}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${yosys_version}")
|
||||
43
cmake/PkgConfig.cmake
Normal file
43
cmake/PkgConfig.cmake
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Syntax:
|
||||
#
|
||||
# pkg_config_import(<package>)
|
||||
#
|
||||
# To use this command, `find_package(PkgConfig)` must be used beforehand, but it does
|
||||
# not have to succeed. If the `PkgConfig` package is not found, all imports silently fail.
|
||||
#
|
||||
# Imports `<package>` as a CMake `IMPORTED` target `PkgConfig::<package>`.
|
||||
# Updates the global `PACKAGES_FOUND` and `PACKAGES_NOT_FOUND` properties and defines
|
||||
# the `<package>_FOUND` variable.
|
||||
#
|
||||
function(pkg_config_import arg_PREFIX)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "MODULES")
|
||||
if (NOT arg_MODULES)
|
||||
set(arg_MODULES ${arg_PREFIX})
|
||||
endif()
|
||||
|
||||
if (PkgConfig_FOUND)
|
||||
# Once CMake 4.1 is available, this call should be replaced with `cmake_pkg_config()`.
|
||||
pkg_check_modules(${arg_PREFIX} IMPORTED_TARGET ${arg_MODULES})
|
||||
if (${arg_PREFIX}_FOUND)
|
||||
# We found the pkgconfig file, but is it actually a usable package?
|
||||
# The main cause of failure here would be cross-compiling, which pkg-config does not
|
||||
# handle very well (especially pre-`cmake_pkg_config()`).
|
||||
try_compile(is_usable
|
||||
SOURCE_FROM_CONTENT "main.cc" "int main() {}"
|
||||
LINK_LIBRARIES PkgConfig::${arg_PREFIX}
|
||||
LOG_DESCRIPTION "Checking if PkgConfig::${arg_PREFIX} is usable"
|
||||
)
|
||||
if (NOT is_usable)
|
||||
message(STATUS "Modules '${arg_MODULES}' unusable (bad \$PKG_CONFIG_LIBDIR?)")
|
||||
set(${arg_PREFIX}_FOUND 0)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (${arg_PREFIX}_FOUND)
|
||||
set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND ${arg_PREFIX})
|
||||
else()
|
||||
set_property(GLOBAL APPEND PROPERTY PACKAGES_NOT_FOUND ${arg_PREFIX})
|
||||
endif()
|
||||
return (PROPAGATE ${arg_PREFIX}_FOUND)
|
||||
endfunction()
|
||||
60
cmake/PmgenCommand.cmake
Normal file
60
cmake/PmgenCommand.cmake
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Syntax:
|
||||
#
|
||||
# pmgen_command(<output>
|
||||
# [<input>...]
|
||||
# [PREFIX <prefix>]
|
||||
# [DEBUG]
|
||||
# )
|
||||
#
|
||||
# Builds `<output>_pm.h` in the current binary directory from pmgen source files `<input>`, which must have
|
||||
# the `*.pmg` extension. If `<input>...` contains more than one file, `<prefix>` must be provided.
|
||||
#
|
||||
# Defines the following variables:
|
||||
# - `PMGEN_<output>_DEFINED`: Boolean indicating whether this command was successfully invoked.
|
||||
# - `PMGEN_<output>_OUTPUT`: The header file generated by `pmgen`.
|
||||
#
|
||||
# Usage example:
|
||||
#
|
||||
# pmgen_command(my_dsp
|
||||
# my_dsp.pmg
|
||||
# )
|
||||
# yosys_pass(my_dsp
|
||||
# my_dsp.cc
|
||||
# ${PMGEN_my_dsp_OUTPUT}
|
||||
# )
|
||||
#
|
||||
# Usage example with multiple files:
|
||||
#
|
||||
# pmgen_command(my_dsp
|
||||
# my_dsp_macc.pmg
|
||||
# my_dsp_carry.pmg
|
||||
# PREFIX
|
||||
# my_dsp
|
||||
# )
|
||||
#
|
||||
function(pmgen_command arg_NAME)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg "DEBUG" "PREFIX" "")
|
||||
set(arg_INPUTS ${arg_UNPARSED_ARGUMENTS})
|
||||
|
||||
set(pmgen_script ${CMAKE_SOURCE_DIR}/passes/pmgen/pmgen.py)
|
||||
set(pmgen_output ${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}_pm.h)
|
||||
cmake_path(RELATIVE_PATH pmgen_output BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE pmgen_output_rel)
|
||||
add_custom_command(
|
||||
DEPENDS ${pmgen_script} ${arg_INPUTS}
|
||||
OUTPUT ${pmgen_output}
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
${pmgen_script}
|
||||
"$<$<BOOL:${arg_DEBUG}>:-g>"
|
||||
"$<$<BOOL:${arg_PREFIX}>:-p;${arg_PREFIX}>"
|
||||
-o ${pmgen_output}
|
||||
${arg_INPUTS}
|
||||
COMMAND_EXPAND_LISTS
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
VERBATIM
|
||||
COMMENT "Compiling pattern matcher ${pmgen_output_rel}"
|
||||
)
|
||||
|
||||
# The usage of this command is somewhat inspired by `flex_target()` and `bison_target()`.
|
||||
set(PMGEN_${arg_NAME}_DEFINED TRUE)
|
||||
set(PMGEN_${arg_NAME}_OUTPUT ${pmgen_output} PARENT_SCOPE)
|
||||
endfunction()
|
||||
96
cmake/YosysAbc.cmake
Normal file
96
cmake/YosysAbc.cmake
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
include(CheckCompilerFlag)
|
||||
|
||||
define_property(TARGET PROPERTY YOSYS_IS_ABC)
|
||||
|
||||
function(target_safe_compile_options target scope)
|
||||
foreach (lang C CXX)
|
||||
foreach (flag ${ARGN})
|
||||
check_compiler_flag(${lang} ${flag} HAVE_${lang}_${flag})
|
||||
if (HAVE_${lang}_${flag})
|
||||
target_compile_options(${target} ${scope} $<$<COMPILE_LANGUAGE:${lang}>:${flag}>)
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(_yosys_abc_extract_makefile result vardecl filename)
|
||||
# Parse a Makefile fragment and extracts the first matching variable assignment into
|
||||
# a list of values.
|
||||
file(READ ${filename} contents)
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${filename})
|
||||
if ("${contents}" MATCHES "${vardecl}(\\\\\n|[ \t])*(([^\\\\\n]|\\\\\n)+)")
|
||||
string(REGEX REPLACE "(\\\\\n|[ \t])+" ";" ${result} "${CMAKE_MATCH_2}")
|
||||
endif()
|
||||
return (PROPAGATE ${result})
|
||||
endfunction()
|
||||
|
||||
function(yosys_abc_target arg_LIBNAME arg_EXENAME)
|
||||
cmake_parse_arguments(PARSE_ARGV 2 arg "" "INSTALL_IF" "")
|
||||
|
||||
# Instead of using either the ABC Make or CMake build system, we parse the source
|
||||
# of truth: ABC's `module.make` files. This turns out to be quite trivial.
|
||||
# This way, no assumptions about the environment are made, and Yosys can be compiled
|
||||
# on Windows without MSYS as a result (while benefitting other platforms as well).
|
||||
set(all_sources)
|
||||
_yosys_abc_extract_makefile(module_files "MODULES :=" ${CMAKE_SOURCE_DIR}/abc/Makefile)
|
||||
_yosys_abc_extract_makefile(module_files_cudd "MODULES \\+=" ${CMAKE_SOURCE_DIR}/abc/Makefile)
|
||||
list(REMOVE_ITEM module_files "$(wildcard" "src/ext*)")
|
||||
foreach (module_file ${module_files} ${module_files_cudd})
|
||||
_yosys_abc_extract_makefile(module_sources "SRC \\+=" ${CMAKE_SOURCE_DIR}/abc/${module_file}/module.make)
|
||||
list(APPEND all_sources ${module_sources})
|
||||
endforeach()
|
||||
list(TRANSFORM all_sources PREPEND abc/)
|
||||
|
||||
# Required to get `-DABC_NAMESPACE` below to work consistently.
|
||||
set_source_files_properties(${all_sources} PROPERTIES LANGUAGE CXX)
|
||||
|
||||
set(main_source abc/src/base/main/main.c)
|
||||
list(REMOVE_ITEM all_sources ${main_source})
|
||||
|
||||
find_package(Threads)
|
||||
yosys_cxx_library(${arg_LIBNAME} STATIC
|
||||
OUTPUT_NAME ${arg_LIBNAME}
|
||||
)
|
||||
target_sources(${arg_LIBNAME} PRIVATE ${all_sources})
|
||||
target_include_directories(${arg_LIBNAME} PRIVATE abc/src)
|
||||
target_compile_definitions(${arg_LIBNAME} PUBLIC
|
||||
WIN32_NO_DLL
|
||||
ABC_NAMESPACE=abc
|
||||
ABC_USE_STDINT_H=1
|
||||
ABC_USE_CUDD=1
|
||||
ABC_NO_DYNAMIC_LINKING
|
||||
$<${YOSYS_ENABLE_THREADS}:ABC_USE_PTHREADS>
|
||||
$<${YOSYS_ENABLE_READLINE}:ABC_USE_READLINE>
|
||||
ABC_NO_RLIMIT
|
||||
)
|
||||
target_safe_compile_options(${arg_LIBNAME} PRIVATE
|
||||
-fpermissive
|
||||
-fno-exceptions
|
||||
-Wno-write-strings
|
||||
-Wno-changes-meaning
|
||||
-Wno-attributes
|
||||
-Wno-deprecated-declarations
|
||||
-Wno-deprecated-comma-subscript
|
||||
-Wno-format
|
||||
-Wno-constant-logical-operand
|
||||
)
|
||||
target_link_libraries(${arg_LIBNAME} PUBLIC
|
||||
$<${YOSYS_ENABLE_THREADS}:Threads::Threads>
|
||||
$<${YOSYS_ENABLE_READLINE}:PkgConfig::readline>
|
||||
$<$<BOOL:${WIN32}>:-lshlwapi>
|
||||
)
|
||||
set_target_properties(${arg_LIBNAME} PROPERTIES
|
||||
YOSYS_IS_ABC ON
|
||||
)
|
||||
|
||||
yosys_cxx_executable(${arg_EXENAME}
|
||||
OUTPUT_NAME ${arg_EXENAME}
|
||||
INSTALL_IF "${arg_INSTALL_IF}"
|
||||
)
|
||||
target_sources(${arg_EXENAME} PRIVATE ${main_source})
|
||||
target_include_directories(${arg_EXENAME} PRIVATE abc/src)
|
||||
target_link_libraries(${arg_EXENAME} PRIVATE ${arg_LIBNAME})
|
||||
set_target_properties(${arg_EXENAME} PROPERTIES
|
||||
YOSYS_IS_ABC ON
|
||||
)
|
||||
endfunction()
|
||||
64
cmake/YosysAbcSubmodule.cmake
Normal file
64
cmake/YosysAbcSubmodule.cmake
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# depends on YosysVersion.cmake
|
||||
|
||||
function(yosys_check_abc_submodule)
|
||||
yosys_call_git(status)
|
||||
set(yosys_status "tarball")
|
||||
if (git_result EQUAL 0)
|
||||
set(yosys_status "git")
|
||||
endif()
|
||||
|
||||
yosys_call_git(submodule status abc)
|
||||
set(git_commit)
|
||||
if (EXISTS "${CMAKE_SOURCE_DIR}/abc/.gitcommit")
|
||||
file(READ "${CMAKE_SOURCE_DIR}/abc/.gitcommit" git_commit)
|
||||
string(STRIP "${git_commit}" git_commit)
|
||||
endif()
|
||||
set(abc_status "none")
|
||||
if (git_result EQUAL 0 AND git_output MATCHES "^ ")
|
||||
set(abc_status "git")
|
||||
elseif (git_result EQUAL 0 AND git_output MATCHES "^\\+")
|
||||
set(abc_status "git-changed")
|
||||
elseif (git_result EQUAL 0 AND git_output MATCHES "^U")
|
||||
set(abc_status "git-conflict")
|
||||
elseif (git_commit MATCHES "^[0-9a-fA-F]+$")
|
||||
set(abc_status "tarball")
|
||||
elseif (git_commit MATCHES "\\$Format:%[hH]\\$")
|
||||
set(abc_status "unknown")
|
||||
endif()
|
||||
|
||||
if (abc_status STREQUAL "git" OR abc_status STREQUAL "tarball")
|
||||
# Normal submodule or a tarball.
|
||||
elseif (abc_status STREQUAL "git-changed")
|
||||
message(FATAL_ERROR
|
||||
"'abc' submodule does not match expected commit.\n"
|
||||
"Run 'git submodule update' to check out the correct version.\n"
|
||||
"Note: If testing a different version of ABC, call 'git commit abc' "
|
||||
"in the Yosys source directory to update the expected commit.\n"
|
||||
)
|
||||
elseif (abc_status STREQUAL "git-conflict")
|
||||
message(FATAL_ERROR
|
||||
"'abc' submodule has merge conflicts.\n"
|
||||
"Please resolve merge conflicts before continuing.\n"
|
||||
)
|
||||
elseif (abc_status STREQUAL "unknown") # OK
|
||||
message(FATAL_ERROR
|
||||
"Error: 'abc' is not configured as a git submodule.\n"
|
||||
"To resolve this:\n"
|
||||
"1. Back up your changes: Save any modifications from the 'abc' directory to another location.\n"
|
||||
"2. Remove the existing 'abc' directory: Delete the 'abc' directory and all its contents.\n"
|
||||
"3. Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule.\n"
|
||||
"4. Reapply your changes: Move your saved changes back to the 'abc' directory, if necessary.\n"
|
||||
)
|
||||
elseif (yosys_status STREQUAL "git") # OK
|
||||
message(FATAL_ERROR
|
||||
"Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule.\n"
|
||||
)
|
||||
else() #
|
||||
message(FATAL_ERROR
|
||||
"${CMAKE_SOURCE_DIR} is not configured as a git repository, and 'abc' folder is missing.\n"
|
||||
"If you already have ABC, set 'YOSYS_ABC_EXECUTABLE' CMake variable to point to ABC executable.\n"
|
||||
"Otherwise, download release archive 'yosys.tar.gz' from https://github.com/YosysHQ/yosys/releases.\n"
|
||||
" ('Source code' archive does not contain submodules.)\n"
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
321
cmake/YosysComponent.cmake
Normal file
321
cmake/YosysComponent.cmake
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
set(namespace "yosys")
|
||||
|
||||
# Properties internal to the component system.
|
||||
define_property(TARGET PROPERTY YOSYS_COMPONENT)
|
||||
define_property(TARGET PROPERTY YOSYS_PROVIDES)
|
||||
define_property(TARGET PROPERTY YOSYS_REQUIRES)
|
||||
define_property(TARGET PROPERTY YOSYS_DATA_FILES)
|
||||
define_property(TARGET PROPERTY YOSYS_ENABLE_IF)
|
||||
|
||||
# Syntax:
|
||||
#
|
||||
# yosys_component(<prefix> <name> [INTERFACE]
|
||||
# [<source>...]
|
||||
# [DEFINITIONS <definition>...]
|
||||
# [INCLUDE_DIRS <directory>...]
|
||||
# [LIBRARIES <library>...]
|
||||
# [PROVIDES <provided>...]
|
||||
# [REQUIRES <required>...]
|
||||
# [DATA_DIR <data_dir>]
|
||||
# [DATA_FILES <data_file>...]
|
||||
# [DATA_EXPLICIT [<dest_file> <src_file>]...]
|
||||
# [ESSENTIAL]
|
||||
# [ENABLE_IF "<condition>"]
|
||||
# )
|
||||
#
|
||||
# Creates a target `yosys_<name>` (if `<prefix>` is empty) or `yosys_<prefix>_<name>` (if `<prefix>` is not empty).
|
||||
# This target is an library target with some Yosys-specific behavior that simplifies partitioning the compiler
|
||||
# into small pieces with explicitly defined compile-time and run-time dependency metadata. Circular dependencies
|
||||
# between compilation units in different components are allowed.
|
||||
#
|
||||
# Parameter description:
|
||||
# - `INTERFACE` should be specified for header-only libraries.
|
||||
# - `<source>...` is a shortcut for `target_sources(PRIVATE)`.
|
||||
# - `DEFINITIONS <definition>...` is a shortcut for `target_compile_definitions(PRIVATE)`.
|
||||
# - `INCLUDE_DIRS <directory>...` is a shortcut for `target_include_directories(PRIVATE)`.
|
||||
# - `LIBRARIES <library>...` is a shortcut for `target_link_libraries(PRIVATE)`.
|
||||
# - `PROVIDES <provided>...` creates aliases to each `<provided>` component name.
|
||||
# - `REQUIRES <required>...` ensures that if this target is linked into the Yosys binary, then every
|
||||
# `<required>` component is also linked in.
|
||||
# - `DATA_DIR <data_dir>` configures a base directory for installing data files; this directory
|
||||
# is (relative to the root build directory or the installation prefix) `share/<data_dir>` if
|
||||
# `DATA_DIR` is provided, and `share` if not.
|
||||
# - `DATA_FILES <data_file>...` installs each of `<data_file>` as `share/<data_dir>/<path>/<name>`,
|
||||
# where `<path>` is the directory name of `<data_file>` and `<name>` is the filename of `<data_file>`.
|
||||
# - `DATA_EXPLICIT [<dest_file> <src_file>]...` installs each `<src_file>` as `share/<data_dir>/<dest_file>`.
|
||||
# Where possible, `DATA_FILES` should be used instead.
|
||||
# - `ESSENTIAL` ensures that this target is always linked into the Yosys binary.
|
||||
# - `ENABLE_IF "<condition>"` marks the component as available only when `if(<condition>)` would run.
|
||||
#
|
||||
# Avoid using this function directly. Instead, use one of the wrappers below as follows:
|
||||
# - to define a normal pass, use `yosys_pass(<name>)` to add a component called `<name>`.
|
||||
# - to define a test pass, use `yosys_test_pass(<name>)` to add a component called `test_<name>`.
|
||||
# - to define a frontend, use `yosys_frontend(<name>)` to add a component called `read_<name>`.
|
||||
# - to define a backend, use `yosys_backend(<name>)` to add a component called `write_<name>`.
|
||||
# - if the component sources define more than one pass, use `PROVIDES` with names of the other passes.
|
||||
# - if the component uses `Pass::call()`, `Frontend::frontend_call()`, `Backend::backend_call()`, or other
|
||||
# similar functions, use `REQUIRES` with names of all possibly needed passes.
|
||||
# - if the component needs an essential pass, add the latter to `REQUIRES` anyway for completeness.
|
||||
# - if the component subclasses a `ScriptPass`, build Yosys, then run `misc/script_pass_depends.py <pass>`
|
||||
# to extract the names of all referenced passes.
|
||||
# - in general, component names should be the same as corresponding pass names (as used in the REPL),
|
||||
# but this is not a hard requirement and any suitable name can be used if desired.
|
||||
#
|
||||
function(yosys_component arg_PREFIX arg_NAME)
|
||||
cmake_parse_arguments(PARSE_ARGV 2 arg
|
||||
"INTERFACE;ESSENTIAL;BOOTSTRAP"
|
||||
"DATA_DIR;ENABLE_IF"
|
||||
"DEFINITIONS;INCLUDE_DIRS;LIBRARIES;DATA_FILES;DATA_EXPLICIT;PROVIDES;REQUIRES"
|
||||
)
|
||||
set(arg_SOURCES ${arg_UNPARSED_ARGUMENTS})
|
||||
if ("${arg_ENABLE_IF}" STREQUAL "")
|
||||
set(arg_ENABLE_IF TRUE)
|
||||
endif()
|
||||
|
||||
if (arg_PREFIX STREQUAL "")
|
||||
set(component "${arg_NAME}")
|
||||
else()
|
||||
set(component "${arg_PREFIX}_${arg_NAME}")
|
||||
endif()
|
||||
set(target "${namespace}_${component}")
|
||||
list(TRANSFORM arg_PROVIDES PREPEND ${namespace}_ OUTPUT_VARIABLE provides_targets)
|
||||
|
||||
# An OBJECT library is used to allow for circular symbol dependencies between any source files.
|
||||
# Unfortunately, public dependencies between OBJECT libraries aren't handled correctly, so we have
|
||||
# to do it ourselves.
|
||||
if (arg_SOURCES AND NOT arg_INTERFACE)
|
||||
add_library(${target} EXCLUDE_FROM_ALL OBJECT)
|
||||
target_sources(${target} PRIVATE ${arg_SOURCES})
|
||||
target_include_directories(${target} PRIVATE ${arg_INCLUDE_DIRS})
|
||||
target_compile_definitions(${target} PRIVATE ${arg_DEFINITIONS})
|
||||
target_link_libraries(${target} PUBLIC yosys_common ${arg_LIBRARIES})
|
||||
foreach (alias ${provides_targets})
|
||||
add_library(${alias} ALIAS ${target})
|
||||
endforeach()
|
||||
else()
|
||||
add_library(${target} EXCLUDE_FROM_ALL INTERFACE)
|
||||
endif()
|
||||
set_target_properties(${target} PROPERTIES
|
||||
YOSYS_COMPONENT YES
|
||||
YOSYS_PROVIDES "${arg_PROVIDES}"
|
||||
YOSYS_REQUIRES "${arg_REQUIRES}"
|
||||
YOSYS_DATA_FILES ""
|
||||
YOSYS_ENABLE_IF "${arg_ENABLE_IF}"
|
||||
)
|
||||
|
||||
set(share_file_pairs)
|
||||
foreach (share_file ${arg_DATA_FILES})
|
||||
list(APPEND share_file_pairs ${share_file} ${share_file})
|
||||
endforeach()
|
||||
list(APPEND share_file_pairs ${arg_DATA_EXPLICIT})
|
||||
if (share_file_pairs)
|
||||
set(data_depends)
|
||||
set(share_root ${CMAKE_BINARY_DIR}/share)
|
||||
while (share_file_pairs)
|
||||
list(LENGTH share_file_pairs share_file_unpaired)
|
||||
if (share_file_unpaired EQUAL 1)
|
||||
message(FATAL_ERROR "Unpaired DATA_EXPLICIT argument: ${share_file_pairs}")
|
||||
endif()
|
||||
list(POP_FRONT share_file_pairs dst_file src_file)
|
||||
cmake_path(ABSOLUTE_PATH src_file BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(out_dir ${arg_DATA_DIR})
|
||||
cmake_path(GET dst_file PARENT_PATH dst_parent)
|
||||
cmake_path(APPEND out_dir ${dst_parent})
|
||||
cmake_path(GET dst_file FILENAME dst_filename)
|
||||
cmake_path(APPEND out_dir ${dst_filename} OUTPUT_VARIABLE out_file)
|
||||
file(MAKE_DIRECTORY ${share_root}/${out_dir})
|
||||
add_custom_command(
|
||||
DEPENDS ${src_file}
|
||||
OUTPUT ${share_root}/${out_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${share_root}/${out_file}
|
||||
VERBATIM
|
||||
COMMENT "Copying share/${out_file}"
|
||||
)
|
||||
set_property(TARGET ${target} APPEND PROPERTY YOSYS_DATA_FILES ${out_file})
|
||||
list(APPEND data_depends ${share_root}/${out_file})
|
||||
endwhile()
|
||||
add_custom_target(${target}-data DEPENDS ${data_depends})
|
||||
add_dependencies(${target} ${target}-data)
|
||||
endif()
|
||||
|
||||
if (NOT arg_BOOTSTRAP)
|
||||
set_property(TARGET yosys_everything APPEND PROPERTY YOSYS_REQUIRES ${component})
|
||||
if (arg_ESSENTIAL)
|
||||
set_property(TARGET yosys_essentials APPEND PROPERTY YOSYS_REQUIRES ${component})
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Syntax:
|
||||
#
|
||||
# yosys_core(<name> [<option>...]) →
|
||||
# yosys_component("" <name> [<option>...])
|
||||
#
|
||||
# yosys_pass(<name> [<option>...]) →
|
||||
# yosys_component("" <name> [<option>...])
|
||||
#
|
||||
# yosys_test_pass(<name> [<option>...]) →
|
||||
# yosys_component("test" <name> [<option>...])
|
||||
#
|
||||
# yosys_frontend(<name> [<option>...]) →
|
||||
# yosys_component("frontend" <name> [<option>...])
|
||||
#
|
||||
# yosys_backend(<name> [<option>...]) →
|
||||
# yosys_component("backend" <name> [<option>...])
|
||||
#
|
||||
# See `yosys_component()` for details.
|
||||
#
|
||||
function(yosys_core)
|
||||
yosys_component("" ${ARGV})
|
||||
endfunction()
|
||||
|
||||
function(yosys_pass)
|
||||
yosys_component("" ${ARGV})
|
||||
endfunction()
|
||||
|
||||
function(yosys_test_pass)
|
||||
yosys_component(test ${ARGV})
|
||||
endfunction()
|
||||
|
||||
function(yosys_frontend)
|
||||
yosys_component(read ${ARGV})
|
||||
endfunction()
|
||||
|
||||
function(yosys_backend)
|
||||
yosys_component(write ${ARGV})
|
||||
endfunction()
|
||||
|
||||
# Syntax:
|
||||
#
|
||||
# yosys_expand_components(<variable> <component>...)
|
||||
#
|
||||
# Populates `<variable>` with the list of components required for linking every `<component>`,
|
||||
# sorted by pre-order traversal.
|
||||
#
|
||||
function(yosys_expand_components arg_OUTPUT)
|
||||
cmake_parse_arguments(PARSE_ARGV 1 arg "QUIET" "" "")
|
||||
set(arg_COMPONENTS ${arg_UNPARSED_ARGUMENTS})
|
||||
|
||||
function(check_components context components)
|
||||
set(error 0)
|
||||
foreach (component ${components})
|
||||
set(target "${namespace}_${component}")
|
||||
if (NOT TARGET ${target})
|
||||
message(SEND_ERROR "${context}Target ${target} does not exist")
|
||||
set(error 1)
|
||||
continue()
|
||||
endif()
|
||||
get_target_property(target_is_component ${target} YOSYS_COMPONENT)
|
||||
if (NOT target_is_component)
|
||||
message(SEND_ERROR "${context}Target ${target} is not a Yosys component")
|
||||
set(error 1)
|
||||
endif()
|
||||
endforeach()
|
||||
return (PROPAGATE error)
|
||||
endfunction()
|
||||
|
||||
function(depth_first_search component visited_components required_components)
|
||||
list(APPEND visited_components ${component})
|
||||
get_target_property(component_requires "${namespace}_${component}" YOSYS_REQUIRES)
|
||||
check_components("In REQUIRES of ${component}: " "${component_requires}")
|
||||
foreach (requirement ${component_requires})
|
||||
if (NOT requirement IN_LIST visited_components)
|
||||
depth_first_search(${requirement} "${visited_components}" "${required_components}")
|
||||
endif()
|
||||
endforeach()
|
||||
list(APPEND required_components ${component})
|
||||
return (PROPAGATE visited_components required_components)
|
||||
endfunction()
|
||||
|
||||
set(visited_components)
|
||||
set(required_components)
|
||||
check_components("" "${arg_COMPONENTS}")
|
||||
foreach (component ${arg_COMPONENTS})
|
||||
if (NOT component IN_LIST visited_components)
|
||||
depth_first_search(${component} "${visited_components}" "${required_components}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# If `everything` is in the component list, ignore disabled dependencies, else fail the build.
|
||||
set(fail_if_disabled TRUE)
|
||||
if (everything IN_LIST arg_COMPONENTS)
|
||||
set(fail_if_disabled FALSE)
|
||||
endif()
|
||||
|
||||
# ${required_components} are now sorted in pre-order (every component is visited before
|
||||
# all of its dependents). Figure out which components are enabled and which components
|
||||
# have disabled dependencies.
|
||||
set(enabled_components)
|
||||
if (NOT arg_QUIET)
|
||||
message(TRACE "Resolving component dependencies:")
|
||||
endif()
|
||||
foreach (component ${required_components})
|
||||
set(why_disabled "")
|
||||
get_target_property(component_enable_if "${namespace}_${component}" YOSYS_ENABLE_IF)
|
||||
if (${component_enable_if})
|
||||
get_target_property(component_requires "${namespace}_${component}" YOSYS_REQUIRES)
|
||||
foreach (requirement ${component_requires})
|
||||
if (NOT requirement IN_LIST enabled_components)
|
||||
set(why_disabled "dependency ${requirement}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
set(why_disabled "condition")
|
||||
endif()
|
||||
if ("${why_disabled}" STREQUAL "")
|
||||
list(APPEND enabled_components ${component})
|
||||
if (NOT arg_QUIET)
|
||||
message(TRACE " Component ${component} enabled")
|
||||
endif()
|
||||
else()
|
||||
if (NOT arg_QUIET)
|
||||
message(TRACE " Component ${component} disabled (cause: ${why_disabled})")
|
||||
endif()
|
||||
if (fail_if_disabled)
|
||||
message(FATAL_ERROR "Required component ${component} is disabled (cause: ${why_disabled})")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(${arg_OUTPUT} ${enabled_components})
|
||||
return(PROPAGATE ${arg_OUTPUT})
|
||||
endfunction()
|
||||
|
||||
# Syntax:
|
||||
#
|
||||
# yosys_link_components(<target> {INTERFACE|PUBLIC|PRIVATE} <component>...)
|
||||
#
|
||||
# Link every `<component>` into `<target>`.
|
||||
#
|
||||
function(yosys_link_components arg_TARGET arg_SCOPE)
|
||||
cmake_parse_arguments(PARSE_ARGV 2 arg "" "" "")
|
||||
set(arg_COMPONENTS ${arg_UNPARSED_ARGUMENTS})
|
||||
|
||||
message(VERBOSE "Components for ${arg_TARGET}: ${arg_COMPONENTS}")
|
||||
list(TRANSFORM arg_COMPONENTS PREPEND ${namespace}_ OUTPUT_VARIABLE linked_targets)
|
||||
target_link_libraries(${arg_TARGET} ${arg_SCOPE} ${linked_targets})
|
||||
endfunction()
|
||||
|
||||
# Syntax:
|
||||
#
|
||||
# yosys_install_component_data(<component>... DESTINATION <directory>)
|
||||
#
|
||||
# Install data files for every `<component>` into `<directory>`.
|
||||
# Equivalent to copying `${CMAKE_BINARY_DIR}/share/.` to `<directory>/.` after a clean rebuild.
|
||||
#
|
||||
function(yosys_install_component_data)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg "" "DESTINATION" "")
|
||||
set(arg_COMPONENTS ${arg_UNPARSED_ARGUMENTS})
|
||||
if (NOT arg_DESTINATION)
|
||||
message(FATAL_ERROR "Missing DESTINATION argument")
|
||||
endif()
|
||||
|
||||
foreach (component ${arg_COMPONENTS})
|
||||
get_target_property(data_files ${namespace}_${component} YOSYS_DATA_FILES)
|
||||
foreach (data_file ${data_files})
|
||||
cmake_path(GET data_file PARENT_PATH data_dir)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/share/${data_file} DESTINATION ${arg_DESTINATION}/${data_dir})
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
70
cmake/YosysConfigScript.cmake
Normal file
70
cmake/YosysConfigScript.cmake
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Syntax:
|
||||
#
|
||||
# yosys_config_script({BUILD|INSTALL})
|
||||
#
|
||||
# Generates a `yosys-config` executable with embedded paths for in-tree builds or after installation.
|
||||
#
|
||||
function(yosys_config_script scope)
|
||||
if (scope STREQUAL BUILD)
|
||||
set(BINDIR ${CMAKE_BINARY_DIR})
|
||||
set(LIBDIR ${CMAKE_BINARY_DIR})
|
||||
set(DATDIR ${CMAKE_BINARY_DIR}/share)
|
||||
set(suffix "")
|
||||
elseif (scope STREQUAL INSTALL)
|
||||
set(BINDIR ${YOSYS_INSTALL_FULL_BINDIR})
|
||||
set(LIBDIR ${YOSYS_INSTALL_FULL_LIBDIR})
|
||||
set(DATDIR ${YOSYS_INSTALL_FULL_DATADIR})
|
||||
set(suffix ".install")
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid scope ${scope}")
|
||||
endif()
|
||||
|
||||
set(link_flags)
|
||||
if (scope STREQUAL BUILD OR YOSYS_INSTALL_LIBRARY)
|
||||
set(link_flags -L${LIBDIR})
|
||||
endif()
|
||||
|
||||
set(platform_link_flags)
|
||||
set(platform_libs)
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(platform_link_flags -undefined dynamic_lookup)
|
||||
endif()
|
||||
if (MINGW)
|
||||
set(platform_libs -l:yosys.exe.a)
|
||||
endif()
|
||||
if (MINGW AND YOSYS_INSTALL_DRIVER)
|
||||
set(platform_link_flags -L${LIBDIR})
|
||||
endif()
|
||||
|
||||
set(CXX ${CMAKE_CXX_COMPILER})
|
||||
string(JOIN " " CXXFLAGS
|
||||
-std=c++${CMAKE_CXX_STANDARD}
|
||||
${CMAKE_CXX_FLAGS}
|
||||
${CMAKE_CXX_COMPILE_OPTIONS_PIC}
|
||||
-D_YOSYS_
|
||||
"-DYOSYS_VER=\"${YOSYS_VERSION}\""
|
||||
"-DYOSYS_MAJOR=${YOSYS_VERSION_MAJOR}"
|
||||
"-DYOSYS_MINOR=${YOSYS_VERSION_MINOR}"
|
||||
"-DYOSYS_COMMIT=${YOSYS_VERSION_COMMIT}"
|
||||
-I${DATDIR}/include
|
||||
)
|
||||
string(JOIN " " LINKFLAGS
|
||||
${CMAKE_SHARED_LIBRARY_CXX_FLAGS}
|
||||
${link_flags}
|
||||
${platform_link_flags}
|
||||
)
|
||||
string(JOIN " " LIBS
|
||||
${platform_libs}
|
||||
)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/misc/yosys-config.in
|
||||
${YOSYS_PROGRAM_PREFIX}yosys-config${suffix}
|
||||
USE_SOURCE_PERMISSIONS
|
||||
@ONLY
|
||||
)
|
||||
if (scope STREQUAL INSTALL)
|
||||
install(PROGRAMS ${CMAKE_BINARY_DIR}/${YOSYS_PROGRAM_PREFIX}yosys-config.install
|
||||
RENAME yosys-config
|
||||
DESTINATION ${YOSYS_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
9
cmake/YosysInstallDirs.cmake
Normal file
9
cmake/YosysInstallDirs.cmake
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
include(GNUInstallDirs)
|
||||
|
||||
# Nothing should be installed outside of the following locations.
|
||||
set(YOSYS_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR})
|
||||
set(YOSYS_INSTALL_FULL_BINDIR ${CMAKE_INSTALL_FULL_BINDIR})
|
||||
set(YOSYS_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}/${YOSYS_PROGRAM_PREFIX}yosys)
|
||||
set(YOSYS_INSTALL_FULL_LIBDIR ${CMAKE_INSTALL_FULL_LIBDIR}/${YOSYS_PROGRAM_PREFIX}yosys)
|
||||
set(YOSYS_INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR}/${YOSYS_PROGRAM_PREFIX}yosys)
|
||||
set(YOSYS_INSTALL_FULL_DATADIR ${CMAKE_INSTALL_FULL_DATADIR}/${YOSYS_PROGRAM_PREFIX}yosys)
|
||||
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