3
0
Fork 0
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:
Mohamed Gaber 2026-06-09 16:22:51 +03:00
commit e58125b605
No known key found for this signature in database
834 changed files with 25281 additions and 8780 deletions

View file

@ -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/).

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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 }}

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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
View 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

View file

@ -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"

View file

@ -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

View file

@ -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 }}

View file

@ -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-*

View file

@ -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)

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
set -e -x
# Build-time dependencies

View file

@ -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
View file

@ -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

View file

@ -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"

View file

@ -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
View 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
)

View file

@ -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).

1480
Makefile

File diff suppressed because it is too large Load diff

112
README.md
View file

@ -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

@ -1 +1 @@
Subproject commit 223d685c5d8e22b90362524bd7189720a6621aeb
Subproject commit 72d015f6567281d84bd4fe6328ce4b7233b596ca

18
backends/CMakeLists.txt Normal file
View 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)

View file

@ -0,0 +1,8 @@
yosys_backend(aiger
aiger.cc
REQUIRES
json11
)
yosys_backend(xaiger
xaiger.cc
)

View file

@ -1,4 +0,0 @@
OBJS += backends/aiger/aiger.o
OBJS += backends/aiger/xaiger.o

View file

@ -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);

View file

@ -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);

View file

@ -0,0 +1,5 @@
yosys_backend(aiger2
aiger.cc
PROVIDES
write_xaiger2
)

View file

@ -1 +0,0 @@
OBJS += backends/aiger2/aiger.o

View file

@ -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");
}

View file

@ -0,0 +1,3 @@
yosys_backend(blif
blif.cc
)

View file

@ -1,3 +0,0 @@
OBJS += backends/blif/blif.o

View file

@ -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> &params)
{
for (auto &param : 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);

View file

@ -0,0 +1,7 @@
yosys_backend(btor
btor.cc
REQUIRES
bmuxmap
demuxmap
bwmuxmap
)

View file

@ -1,3 +0,0 @@
OBJS += backends/btor/btor.o

View file

@ -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);

View 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
)

View file

@ -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))

View file

@ -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 &param_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;

View file

@ -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))

View file

@ -0,0 +1,3 @@
yosys_backend(edif
edif.cc
)

View file

@ -1,3 +0,0 @@
OBJS += backends/edif/edif.o

View file

@ -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");

View file

@ -0,0 +1,8 @@
yosys_backend(firrtl
firrtl.cc
REQUIRES
pmuxtree
bmuxmap
demuxmap
bwmuxmap
)

View file

@ -1,3 +0,0 @@
OBJS += backends/firrtl/firrtl.o

View file

@ -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;

View 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
)

View file

@ -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

View file

@ -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");

View file

@ -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();
}

View file

@ -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();
}

View file

@ -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;

View file

@ -0,0 +1,3 @@
yosys_backend(intersynth
intersynth.cc
)

View file

@ -1,3 +0,0 @@
OBJS += backends/intersynth/intersynth.o

View file

@ -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 &param : 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");

View file

@ -0,0 +1,5 @@
yosys_backend(jny
jny.cc
PROVIDES
jny
)

View file

@ -1,2 +0,0 @@
OBJS += backends/jny/jny.o

View file

@ -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";

View file

@ -0,0 +1,5 @@
yosys_backend(json
json.cc
PROVIDES
json
)

View file

@ -1,3 +0,0 @@
OBJS += backends/json/json.o

View file

@ -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++;
}

View 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
)

View file

@ -1,3 +0,0 @@
OBJS += backends/rtlil/rtlil_backend.o

View file

@ -0,0 +1,3 @@
yosys_backend(simplec
simplec.cc
)

View file

@ -1,3 +0,0 @@
OBJS += backends/simplec/simplec.o

View file

@ -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);

View 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
)

View file

@ -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

View file

@ -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
View 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
View 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

View file

@ -0,0 +1,7 @@
yosys_backend(smv
smv.cc
REQUIRES
bmuxmap
demuxmap
bwmuxmap
)

View file

@ -1,3 +0,0 @@
OBJS += backends/smv/smv.o

View file

@ -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();
}

View file

@ -0,0 +1,3 @@
yosys_backend(spice
spice.cc
)

View file

@ -1,3 +0,0 @@
OBJS += backends/spice/spice.o

View file

@ -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;

View file

@ -0,0 +1,3 @@
yosys_backend(table
table.cc
)

View file

@ -1,3 +0,0 @@
OBJS += backends/table/table.o

View file

@ -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";

View file

@ -0,0 +1,8 @@
yosys_backend(verilog
verilog_backend.cc
verilog_backend.h
REQUIRES
bmuxmap
demuxmap
clean_zerowidth
)

View file

@ -1,3 +0,0 @@
OBJS += backends/verilog/verilog_backend.o

View file

@ -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);

View file

@ -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);

View 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
View 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
View 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
View 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
)

View 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}")

View 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
View 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
View 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
View 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()

View 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
View 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()

View 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()

View 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