mirror of
https://github.com/YosysHQ/yosys
synced 2026-06-29 03:58:50 +00:00
Merge branch 'YosysHQ:main' into master
This commit is contained in:
commit
8ffca44e62
80 changed files with 2635 additions and 1137 deletions
67
.github/actions/setup-build-env/action.yml
vendored
67
.github/actions/setup-build-env/action.yml
vendored
|
|
@ -1,14 +1,65 @@
|
||||||
name: Build environment setup
|
name: Build environment setup
|
||||||
description: Configure build env for Yosys builds
|
description: Configure build env for Yosys builds
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
runs-on:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
get-build-deps:
|
||||||
|
description: 'Install Yosys build dependencies'
|
||||||
|
default: false
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
get-docs-deps:
|
||||||
|
description: 'Install Yosys docs dependencies'
|
||||||
|
default: false
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
get-test-deps:
|
||||||
|
description: 'Install Yosys test dependencies'
|
||||||
|
default: false
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
get-iverilog:
|
||||||
|
description: 'Install iverilog'
|
||||||
|
default: false
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Install Linux Dependencies
|
# if updating common/build/docs dependencies, make sure to update README.md
|
||||||
|
# and docs/source/getting_started/installation.rst to match.
|
||||||
|
- name: Linux common dependencies
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
shell: bash
|
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||||
run: |
|
with:
|
||||||
sudo apt-get update
|
packages: gawk git make python3
|
||||||
sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libgtest-dev
|
version: ${{ inputs.runs-on }}-commonys
|
||||||
|
|
||||||
|
- name: Linux build dependencies
|
||||||
|
if: runner.os == 'Linux' && inputs.get-build-deps == 'true'
|
||||||
|
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||||
|
with:
|
||||||
|
packages: bison clang flex libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev
|
||||||
|
version: ${{ inputs.runs-on }}-buildys
|
||||||
|
|
||||||
|
- name: Linux docs dependencies
|
||||||
|
if: runner.os == 'Linux' && inputs.get-docs-deps == 'true'
|
||||||
|
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||||
|
with:
|
||||||
|
packages: graphviz xdot
|
||||||
|
version: ${{ inputs.runs-on }}-docsys
|
||||||
|
|
||||||
|
# if updating test dependencies, make sure to update
|
||||||
|
# docs/source/yosys_internals/extending_yosys/test_suites.rst to match.
|
||||||
|
- name: Linux test dependencies
|
||||||
|
if: runner.os == 'Linux' && inputs.get-test-deps == 'true'
|
||||||
|
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||||
|
with:
|
||||||
|
packages: libgtest-dev
|
||||||
|
version: ${{ inputs.runs-on }}-testys
|
||||||
|
|
||||||
- name: Install macOS Dependencies
|
- name: Install macOS Dependencies
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
|
|
@ -32,3 +83,9 @@ runs:
|
||||||
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
|
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
|
||||||
echo "$(brew --prefix flex)/bin" >> $GITHUB_PATH
|
echo "$(brew --prefix flex)/bin" >> $GITHUB_PATH
|
||||||
echo "procs=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV
|
echo "procs=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Setup iverilog
|
||||||
|
if: inputs.get-iverilog == 'true'
|
||||||
|
uses: ./.github/actions/setup-iverilog
|
||||||
|
with:
|
||||||
|
runs-on: ${{ inputs.runs-on }}
|
||||||
|
|
|
||||||
70
.github/actions/setup-iverilog/action.yml
vendored
Normal file
70
.github/actions/setup-iverilog/action.yml
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
name: iverilog setup
|
||||||
|
description: Cached build and install of iverilog
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
runs-on:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: iverilog Linux deps
|
||||||
|
if: steps.restore-iverilog.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||||
|
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||||
|
with:
|
||||||
|
packages: autoconf gperf make gcc g++ bison flex libbz2-dev
|
||||||
|
version: ${{ inputs.runs-on }}-iverilog
|
||||||
|
|
||||||
|
- name: iverilog macOS deps
|
||||||
|
if: steps.restore-iverilog.outputs.cache-hit != 'true' && runner.os == 'macOS'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
brew install autoconf
|
||||||
|
|
||||||
|
- name: Get iverilog
|
||||||
|
id: get-iverilog
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/steveicarus/iverilog.git
|
||||||
|
cd iverilog
|
||||||
|
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Get vcd2fst
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/mmicko/libwave.git
|
||||||
|
mkdir -p ${{ github.workspace }}/.local/
|
||||||
|
cd libwave
|
||||||
|
cmake . -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/.local
|
||||||
|
make -j$procs
|
||||||
|
make install
|
||||||
|
|
||||||
|
- uses: actions/cache/restore@v4
|
||||||
|
id: restore-iverilog
|
||||||
|
with:
|
||||||
|
path: .local/
|
||||||
|
key: ${{ inputs.runs-on }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
|
||||||
|
|
||||||
|
- name: Build iverilog
|
||||||
|
if: steps.restore-iverilog.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ github.workspace }}/.local/
|
||||||
|
cd iverilog
|
||||||
|
autoconf
|
||||||
|
CC=gcc CXX=g++ ./configure --prefix=${{ github.workspace }}/.local
|
||||||
|
make -j$procs
|
||||||
|
make install
|
||||||
|
|
||||||
|
- name: Check iverilog
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
iverilog -V
|
||||||
|
|
||||||
|
- uses: actions/cache/save@v4
|
||||||
|
id: save-iverilog
|
||||||
|
if: steps.restore-iverilog.outputs.cache-hit != 'true'
|
||||||
|
with:
|
||||||
|
path: .local/
|
||||||
|
key: ${{ steps.restore-iverilog.outputs.cache-primary-key }}
|
||||||
9
.github/workflows/codeql.yml
vendored
9
.github/workflows/codeql.yml
vendored
|
|
@ -10,15 +10,18 @@ jobs:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install deps
|
|
||||||
run: sudo apt-get install bison flex libfl-dev libreadline-dev tcl-dev libffi-dev
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Setup environment
|
||||||
|
uses: ./.github/actions/setup-build-env
|
||||||
|
with:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
get-build-deps: true
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
4
.github/workflows/extra-builds.yml
vendored
4
.github/workflows/extra-builds.yml
vendored
|
|
@ -73,8 +73,8 @@ jobs:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
WASI_SDK=wasi-sdk-19.0
|
WASI_SDK=wasi-sdk-27.0-x86_64-linux
|
||||||
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
|
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz
|
||||||
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
|
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
|
||||||
|
|
||||||
FLEX_VER=2.6.4
|
FLEX_VER=2.6.4
|
||||||
|
|
|
||||||
53
.github/workflows/test-build.yml
vendored
53
.github/workflows/test-build.yml
vendored
|
|
@ -60,6 +60,9 @@ jobs:
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
with:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
get-build-deps: true
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -105,48 +108,10 @@ jobs:
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
|
||||||
- name: Get iverilog
|
|
||||||
id: get-iverilog
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/steveicarus/iverilog.git
|
|
||||||
cd iverilog
|
|
||||||
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Get vcd2fst
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/mmicko/libwave.git
|
|
||||||
mkdir -p ${{ github.workspace }}/.local/
|
|
||||||
cd libwave
|
|
||||||
cmake . -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/.local
|
|
||||||
make -j$procs
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: Cache iverilog
|
|
||||||
id: cache-iverilog
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
with:
|
||||||
path: .local/
|
runs-on: ${{ matrix.os }}
|
||||||
key: ${{ matrix.os }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
|
get-test-deps: true
|
||||||
|
get-iverilog: true
|
||||||
- name: iverilog macOS deps
|
|
||||||
if: steps.cache-iverilog.outputs.cache-hit != 'true' && runner.os == 'macOS'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
brew install autoconf
|
|
||||||
|
|
||||||
- name: Build iverilog
|
|
||||||
if: steps.cache-iverilog.outputs.cache-hit != 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.local/
|
|
||||||
cd iverilog
|
|
||||||
autoconf
|
|
||||||
CC=gcc CXX=g++ ./configure --prefix=${{ github.workspace }}/.local
|
|
||||||
make -j$procs
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
|
|
@ -191,6 +156,8 @@ jobs:
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
with:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
|
|
@ -229,6 +196,10 @@ jobs:
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
with:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
get-build-deps: true
|
||||||
|
get-docs-deps: true
|
||||||
|
|
||||||
- name: Download build artifact
|
- name: Download build artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
|
|
|
||||||
5
.github/workflows/test-compile.yml
vendored
5
.github/workflows/test-compile.yml
vendored
|
|
@ -45,7 +45,7 @@ jobs:
|
||||||
- 'gcc-14'
|
- 'gcc-14'
|
||||||
include:
|
include:
|
||||||
# macOS x86
|
# macOS x86
|
||||||
- os: macos-13
|
- os: macos-15-intel
|
||||||
compiler: 'clang-19'
|
compiler: 'clang-19'
|
||||||
# macOS arm
|
# macOS arm
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
|
|
@ -60,6 +60,9 @@ jobs:
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
with:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
get-build-deps: true
|
||||||
|
|
||||||
- name: Setup Cpp
|
- name: Setup Cpp
|
||||||
uses: aminya/setup-cpp@v1
|
uses: aminya/setup-cpp@v1
|
||||||
|
|
|
||||||
50
.github/workflows/test-sanitizers.yml
vendored
50
.github/workflows/test-sanitizers.yml
vendored
|
|
@ -44,53 +44,11 @@ jobs:
|
||||||
|
|
||||||
- name: Setup environment
|
- name: Setup environment
|
||||||
uses: ./.github/actions/setup-build-env
|
uses: ./.github/actions/setup-build-env
|
||||||
|
|
||||||
- name: Get iverilog
|
|
||||||
id: get-iverilog
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/steveicarus/iverilog.git
|
|
||||||
cd iverilog
|
|
||||||
echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Get vcd2fst
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
git clone https://github.com/mmicko/libwave.git
|
|
||||||
mkdir -p ${{ github.workspace }}/.local/
|
|
||||||
cd libwave
|
|
||||||
cmake . -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/.local
|
|
||||||
make -j$procs
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: Cache iverilog
|
|
||||||
id: cache-iverilog
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
with:
|
||||||
path: .local/
|
runs-on: ${{ matrix.os }}
|
||||||
key: ${{ matrix.os }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
|
get-build-deps: true
|
||||||
|
get-test-deps: true
|
||||||
- name: iverilog macOS deps
|
get-iverilog: true
|
||||||
if: steps.cache-iverilog.outputs.cache-hit != 'true' && runner.os == 'macOS'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
brew install autoconf
|
|
||||||
|
|
||||||
- name: Build iverilog
|
|
||||||
if: steps.cache-iverilog.outputs.cache-hit != 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.local/
|
|
||||||
cd iverilog
|
|
||||||
autoconf
|
|
||||||
CC=gcc CXX=g++ ./configure --prefix=${{ github.workspace }}/.local
|
|
||||||
make -j$procs
|
|
||||||
make install
|
|
||||||
|
|
||||||
- name: Check iverilog
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
iverilog -V
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
12
.github/workflows/wheels.yml
vendored
12
.github/workflows/wheels.yml
vendored
|
|
@ -25,15 +25,15 @@ jobs:
|
||||||
archs: "aarch64",
|
archs: "aarch64",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "macOS 13",
|
name: "macOS 15 x64",
|
||||||
family: "macos",
|
family: "macos",
|
||||||
runner: "macos-13",
|
runner: "macos-15-intel",
|
||||||
archs: "x86_64",
|
archs: "x86_64",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "macOS 14",
|
name: "macOS 15 arm64",
|
||||||
family: "macos",
|
family: "macos",
|
||||||
runner: "macos-14",
|
runner: "macos-15",
|
||||||
archs: "arm64",
|
archs: "arm64",
|
||||||
},
|
},
|
||||||
## Windows is disabled because of an issue with compiling FFI as
|
## Windows is disabled because of an issue with compiling FFI as
|
||||||
|
|
@ -59,7 +59,7 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ffi
|
mkdir -p ffi
|
||||||
curl -L https://github.com/libffi/libffi/releases/download/v3.4.6/libffi-3.4.6.tar.gz | tar --strip-components=1 -xzC ffi
|
curl -L https://github.com/libffi/libffi/releases/download/v3.4.8/libffi-3.4.8.tar.gz | tar --strip-components=1 -xzC ffi
|
||||||
- if: ${{ matrix.os.family == 'linux' }}
|
- if: ${{ matrix.os.family == 'linux' }}
|
||||||
name: "[Linux] Bison 3.8.2"
|
name: "[Linux] Bison 3.8.2"
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
@ -114,7 +114,7 @@ jobs:
|
||||||
path: ./wheelhouse/*.whl
|
path: ./wheelhouse/*.whl
|
||||||
upload_wheels:
|
upload_wheels:
|
||||||
name: Upload Wheels
|
name: Upload Wheels
|
||||||
if: github.repository == 'YosysHQ/Yosys'
|
if: (github.repository == 'YosysHQ/Yosys') && (github.event_name == 'workflow_dispatch')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Specifying a GitHub environment is optional, but strongly encouraged
|
# Specifying a GitHub environment is optional, but strongly encouraged
|
||||||
environment: pypi
|
environment: pypi
|
||||||
|
|
|
||||||
4
.github/workflows/wheels/_run_cibw_linux.py
vendored
4
.github/workflows/wheels/_run_cibw_linux.py
vendored
|
|
@ -24,10 +24,10 @@ from pathlib import Path
|
||||||
|
|
||||||
__yosys_root__ = Path(__file__).absolute().parents[3]
|
__yosys_root__ = Path(__file__).absolute().parents[3]
|
||||||
|
|
||||||
for source in ["boost", "ffi", "bison"]:
|
for source in ["ffi", "bison"]:
|
||||||
if not (__yosys_root__ / source).is_dir():
|
if not (__yosys_root__ / source).is_dir():
|
||||||
print(
|
print(
|
||||||
"You need to download boost, ffi and bison in a similar manner to wheels.yml first."
|
"You need to download ffi and bison in a similar manner to wheels.yml first."
|
||||||
)
|
)
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -55,7 +55,6 @@
|
||||||
# pyosys
|
# pyosys
|
||||||
/kernel/*.pyh
|
/kernel/*.pyh
|
||||||
/kernel/python_wrappers.cc
|
/kernel/python_wrappers.cc
|
||||||
/boost
|
|
||||||
/ffi
|
/ffi
|
||||||
/bison
|
/bison
|
||||||
/venv
|
/venv
|
||||||
|
|
|
||||||
2
Brewfile
2
Brewfile
|
|
@ -6,9 +6,9 @@ brew "git"
|
||||||
brew "graphviz"
|
brew "graphviz"
|
||||||
brew "pkg-config"
|
brew "pkg-config"
|
||||||
brew "python3"
|
brew "python3"
|
||||||
|
brew "uv"
|
||||||
brew "xdot"
|
brew "xdot"
|
||||||
brew "bash"
|
brew "bash"
|
||||||
brew "boost-python3"
|
|
||||||
brew "llvm@20"
|
brew "llvm@20"
|
||||||
brew "lld"
|
brew "lld"
|
||||||
brew "googletest"
|
brew "googletest"
|
||||||
|
|
|
||||||
20
CHANGELOG
20
CHANGELOG
|
|
@ -2,9 +2,27 @@
|
||||||
List of major changes and improvements between releases
|
List of major changes and improvements between releases
|
||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
Yosys 0.58 .. Yosys 0.59-dev
|
Yosys 0.59 .. Yosys 0.60-dev
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
Yosys 0.58 .. Yosys 0.59
|
||||||
|
--------------------------
|
||||||
|
* Various
|
||||||
|
- Pyosys is rewritten using pybind11.
|
||||||
|
- alumacc: merge independent of sign.
|
||||||
|
- write_btor: Include $assert and $assume cells in -ywmap output.
|
||||||
|
- RTLIL parser rewritten for efficiency.
|
||||||
|
- Wildcards enabled for Liberty file consuming.
|
||||||
|
- timeest: Add top ports launching/sampling.
|
||||||
|
|
||||||
|
* New commands and options
|
||||||
|
- Added "-apply_derived_type" option to "box_derive" pass.
|
||||||
|
- Added "-publish_icells" option to "chtype" pass.
|
||||||
|
- Added "-width" option to "sim" pass.
|
||||||
|
- Added "sort" pass for sorting the design objects.
|
||||||
|
- Merged "synth_ecp5" and "synth_nexus" into "synth_lattice" pass.
|
||||||
|
- Added "-strict-gw5a-dffs" and "-setundef" options to "synth_gowin" pass.
|
||||||
|
|
||||||
Yosys 0.57 .. Yosys 0.58
|
Yosys 0.57 .. Yosys 0.58
|
||||||
--------------------------
|
--------------------------
|
||||||
* Various
|
* Various
|
||||||
|
|
|
||||||
34
Makefile
34
Makefile
|
|
@ -28,6 +28,7 @@ ENABLE_HELP_SOURCE := 0
|
||||||
|
|
||||||
# python wrappers
|
# python wrappers
|
||||||
ENABLE_PYOSYS := 0
|
ENABLE_PYOSYS := 0
|
||||||
|
PYOSYS_USE_UV := 1
|
||||||
|
|
||||||
# other configuration flags
|
# other configuration flags
|
||||||
ENABLE_GCOV := 0
|
ENABLE_GCOV := 0
|
||||||
|
|
@ -94,14 +95,14 @@ TARGETS = $(PROGRAM_PREFIX)yosys$(EXE) $(PROGRAM_PREFIX)yosys-config
|
||||||
PRETTY = 1
|
PRETTY = 1
|
||||||
SMALL = 0
|
SMALL = 0
|
||||||
|
|
||||||
# Unit test
|
|
||||||
UNITESTPATH := tests/unit
|
|
||||||
|
|
||||||
all: top-all
|
all: top-all
|
||||||
|
|
||||||
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
|
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
|
||||||
VPATH := $(YOSYS_SRC)
|
VPATH := $(YOSYS_SRC)
|
||||||
|
|
||||||
|
# Unit test
|
||||||
|
UNITESTPATH := $(YOSYS_SRC)/tests/unit
|
||||||
|
|
||||||
export CXXSTD ?= c++17
|
export CXXSTD ?= c++17
|
||||||
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include
|
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include
|
||||||
LIBS := $(LIBS) -lstdc++ -lm
|
LIBS := $(LIBS) -lstdc++ -lm
|
||||||
|
|
@ -160,7 +161,7 @@ ifeq ($(OS), Haiku)
|
||||||
CXXFLAGS += -D_DEFAULT_SOURCE
|
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
YOSYS_VER := 0.58+89
|
YOSYS_VER := 0.59+0
|
||||||
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
||||||
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
|
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
|
||||||
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
|
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
|
||||||
|
|
@ -183,7 +184,7 @@ endif
|
||||||
OBJS = kernel/version_$(GIT_REV).o
|
OBJS = kernel/version_$(GIT_REV).o
|
||||||
|
|
||||||
bumpversion:
|
bumpversion:
|
||||||
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 157aabb.. | wc -l`/;" Makefile
|
sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 03eb220.. | wc -l`/;" Makefile
|
||||||
|
|
||||||
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
|
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)
|
||||||
|
|
||||||
|
|
@ -282,12 +283,11 @@ ifeq ($(WASI_SDK),)
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
AR = llvm-ar
|
AR = llvm-ar
|
||||||
RANLIB = llvm-ranlib
|
RANLIB = llvm-ranlib
|
||||||
WASIFLAGS := -target wasm32-wasi --sysroot $(WASI_SYSROOT) $(WASIFLAGS)
|
WASIFLAGS := -target wasm32-wasi $(WASIFLAGS)
|
||||||
else
|
else
|
||||||
CXX = $(WASI_SDK)/bin/clang++
|
CXX = $(WASI_SDK)/bin/clang++
|
||||||
AR = $(WASI_SDK)/bin/ar
|
AR = $(WASI_SDK)/bin/ar
|
||||||
RANLIB = $(WASI_SDK)/bin/ranlib
|
RANLIB = $(WASI_SDK)/bin/ranlib
|
||||||
WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS)
|
|
||||||
endif
|
endif
|
||||||
CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS $(filter-out -fPIC,$(CXXFLAGS))
|
CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS $(filter-out -fPIC,$(CXXFLAGS))
|
||||||
LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS))
|
LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS))
|
||||||
|
|
@ -352,16 +352,22 @@ PYTHON_OBJECTS = pyosys/wrappers.o kernel/drivers.o kernel/yosys.o passes/cmds/p
|
||||||
|
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
# python-config --ldflags includes -l and -L, but LINKFLAGS is only -L
|
# python-config --ldflags includes -l and -L, but LINKFLAGS is only -L
|
||||||
|
|
||||||
|
UV_ENV :=
|
||||||
|
ifeq ($(PYOSYS_USE_UV),1)
|
||||||
|
UV_ENV := uv run --no-project --with 'pybind11>3,<4' --with 'cxxheaderparser'
|
||||||
|
endif
|
||||||
|
|
||||||
LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags))
|
LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags))
|
||||||
LIBS += $(shell $(PYTHON_CONFIG) --libs)
|
LIBS += $(shell $(PYTHON_CONFIG) --libs)
|
||||||
EXE_LIBS += $(filter-out $(LIBS),$(shell $(PYTHON_CONFIG_FOR_EXE) --libs))
|
EXE_LIBS += $(filter-out $(LIBS),$(shell $(PYTHON_CONFIG_FOR_EXE) --libs))
|
||||||
PYBIND11_INCLUDE ?= $(shell $(PYTHON_EXECUTABLE) -m pybind11 --includes)
|
PYBIND11_INCLUDE ?= $(shell $(UV_ENV) $(PYTHON_EXECUTABLE) -m pybind11 --includes)
|
||||||
CXXFLAGS += -I$(PYBIND11_INCLUDE) -DYOSYS_ENABLE_PYTHON
|
CXXFLAGS += -I$(PYBIND11_INCLUDE) -DYOSYS_ENABLE_PYTHON
|
||||||
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DYOSYS_ENABLE_PYTHON
|
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DYOSYS_ENABLE_PYTHON
|
||||||
|
|
||||||
OBJS += $(PY_WRAPPER_FILE).o
|
OBJS += $(PY_WRAPPER_FILE).o
|
||||||
PY_GEN_SCRIPT = pyosys/generator.py
|
PY_GEN_SCRIPT = $(YOSYS_SRC)/pyosys/generator.py
|
||||||
PY_WRAP_INCLUDES := $(shell $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) --print-includes)
|
PY_WRAP_INCLUDES := $(shell $(UV_ENV) $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) --print-includes)
|
||||||
endif # ENABLE_PYOSYS
|
endif # ENABLE_PYOSYS
|
||||||
|
|
||||||
ifeq ($(ENABLE_READLINE),1)
|
ifeq ($(ENABLE_READLINE),1)
|
||||||
|
|
@ -777,7 +783,7 @@ endif
|
||||||
ifeq ($(ENABLE_PYOSYS),1)
|
ifeq ($(ENABLE_PYOSYS),1)
|
||||||
$(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT) pyosys/wrappers_tpl.cc $(PY_WRAP_INCLUDES) pyosys/hashlib.h
|
$(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT) pyosys/wrappers_tpl.cc $(PY_WRAP_INCLUDES) pyosys/hashlib.h
|
||||||
$(Q) mkdir -p $(dir $@)
|
$(Q) mkdir -p $(dir $@)
|
||||||
$(P) $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) $(PY_WRAPPER_FILE).cc
|
$(P) $(UV_ENV) $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) $(PY_WRAPPER_FILE).cc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
|
|
@ -1129,7 +1135,7 @@ DOC_TARGET ?= html
|
||||||
docs: docs/prep
|
docs: docs/prep
|
||||||
$(Q) $(MAKE) -C docs $(DOC_TARGET)
|
$(Q) $(MAKE) -C docs $(DOC_TARGET)
|
||||||
|
|
||||||
clean: clean-py
|
clean: clean-py clean-unit-test
|
||||||
rm -rf share
|
rm -rf share
|
||||||
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
|
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
|
||||||
rm -f kernel/version_*.o kernel/version_*.cc
|
rm -f kernel/version_*.o kernel/version_*.cc
|
||||||
|
|
@ -1144,7 +1150,7 @@ clean: clean-py
|
||||||
rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
|
rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
|
||||||
rm -f tests/tools/cmp_tbdata
|
rm -f tests/tools/cmp_tbdata
|
||||||
rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS))
|
rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS))
|
||||||
-$(MAKE) -C docs clean
|
-$(MAKE) -C $(YOSYS_SRC)/docs clean
|
||||||
rm -rf docs/util/__pycache__
|
rm -rf docs/util/__pycache__
|
||||||
rm -f libyosys.so
|
rm -f libyosys.so
|
||||||
|
|
||||||
|
|
@ -1156,7 +1162,7 @@ clean-py:
|
||||||
rm -rf kernel/*.pyh
|
rm -rf kernel/*.pyh
|
||||||
|
|
||||||
clean-abc:
|
clean-abc:
|
||||||
$(MAKE) -C abc DEP= clean
|
$(MAKE) -C $(YOSYS_SRC)/abc DEP= clean
|
||||||
rm -f $(PROGRAM_PREFIX)yosys-abc$(EXE) $(PROGRAM_PREFIX)yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a .git-abc-submodule-hash
|
rm -f $(PROGRAM_PREFIX)yosys-abc$(EXE) $(PROGRAM_PREFIX)yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a .git-abc-submodule-hash
|
||||||
|
|
||||||
mrproper: clean
|
mrproper: clean
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,10 @@ Xdot (graphviz) is used by the ``show`` command in yosys to display schematics.
|
||||||
For example on Ubuntu Linux 22.04 LTS the following commands will install all
|
For example on Ubuntu Linux 22.04 LTS the following commands will install all
|
||||||
prerequisites for building yosys:
|
prerequisites for building yosys:
|
||||||
|
|
||||||
$ sudo apt-get install build-essential clang lld bison flex libfl-dev \
|
$ sudo apt-get install gawk git make python3 lld bison clang flex \
|
||||||
libreadline-dev gawk tcl-dev libffi-dev git \
|
libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev \
|
||||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
graphviz xdot
|
||||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
$ curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
|
||||||
The environment variable `CXX` can be used to control the C++ compiler used, or
|
The environment variable `CXX` can be used to control the C++ compiler used, or
|
||||||
run one of the following to override it:
|
run one of the following to override it:
|
||||||
|
|
|
||||||
2
abc
2
abc
|
|
@ -1 +1 @@
|
||||||
Subproject commit fa186342baefea06e7c2aa13fe51f338ffc84912
|
Subproject commit 1c5ed1ce378cc04beac30bb31abc4c37c8467042
|
||||||
|
|
@ -637,20 +637,6 @@ std::string escape_cxx_string(const std::string &input)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string basename(const std::string &filepath)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
const std::string dir_seps = "\\/";
|
|
||||||
#else
|
|
||||||
const std::string dir_seps = "/";
|
|
||||||
#endif
|
|
||||||
size_t sep_pos = filepath.find_last_of(dir_seps);
|
|
||||||
if (sep_pos != std::string::npos)
|
|
||||||
return filepath.substr(sep_pos + 1);
|
|
||||||
else
|
|
||||||
return filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
std::string get_hdl_name(T *object)
|
std::string get_hdl_name(T *object)
|
||||||
{
|
{
|
||||||
|
|
@ -2858,7 +2844,7 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (split_intf)
|
if (split_intf)
|
||||||
f << "#include \"" << basename(intf_filename) << "\"\n";
|
f << "#include \"" << name_from_file_path(intf_filename) << "\"\n";
|
||||||
else
|
else
|
||||||
f << "#include <cxxrtl/cxxrtl.h>\n";
|
f << "#include <cxxrtl/cxxrtl.h>\n";
|
||||||
f << "\n";
|
f << "\n";
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,8 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
|
||||||
dump_sigchunk(f, sig.as_chunk(), autoint);
|
dump_sigchunk(f, sig.as_chunk(), autoint);
|
||||||
} else {
|
} else {
|
||||||
f << stringf("{ ");
|
f << stringf("{ ");
|
||||||
for (const auto& chunk : reversed(sig.chunks())) {
|
auto chunks = sig.chunks();
|
||||||
|
for (const auto& chunk : reversed(chunks)) {
|
||||||
dump_sigchunk(f, chunk, false);
|
dump_sigchunk(f, chunk, false);
|
||||||
f << stringf(" ");
|
f << stringf(" ");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -382,8 +382,9 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
|
||||||
dump_sigchunk(f, sig.as_chunk());
|
dump_sigchunk(f, sig.as_chunk());
|
||||||
} else {
|
} else {
|
||||||
f << stringf("{ ");
|
f << stringf("{ ");
|
||||||
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
|
auto chunks = sig.chunks();
|
||||||
if (it != sig.chunks().rbegin())
|
for (auto it = chunks.rbegin(); it != chunks.rend(); ++it) {
|
||||||
|
if (it != chunks.rbegin())
|
||||||
f << stringf(", ");
|
f << stringf(", ");
|
||||||
dump_sigchunk(f, *it, true);
|
dump_sigchunk(f, *it, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
ECP5
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. autocmdgroup:: techlibs/ecp5
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
Lattice Nexus
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. autocmdgroup:: techlibs/nexus
|
|
||||||
:members:
|
|
||||||
|
|
@ -6,7 +6,7 @@ import os
|
||||||
project = 'YosysHQ Yosys'
|
project = 'YosysHQ Yosys'
|
||||||
author = 'YosysHQ GmbH'
|
author = 'YosysHQ GmbH'
|
||||||
copyright ='2025 YosysHQ GmbH'
|
copyright ='2025 YosysHQ GmbH'
|
||||||
yosys_ver = "0.58"
|
yosys_ver = "0.59"
|
||||||
|
|
||||||
# select HTML theme
|
# select HTML theme
|
||||||
html_theme = 'furo-ys'
|
html_theme = 'furo-ys'
|
||||||
|
|
@ -50,7 +50,7 @@ rst_prolog = """
|
||||||
:language: yoscrypt
|
:language: yoscrypt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex']
|
extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex', 'sphinx_inline_tabs']
|
||||||
|
|
||||||
if os.getenv("READTHEDOCS"):
|
if os.getenv("READTHEDOCS"):
|
||||||
# Use rtds_action if we are building on read the docs and have a github token env var
|
# Use rtds_action if we are building on read the docs and have a github token env var
|
||||||
|
|
|
||||||
|
|
@ -93,60 +93,66 @@ tools: readline, libffi, Tcl and zlib; are optional but enabled by default (see
|
||||||
:makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the
|
:makevar:`ENABLE_*` settings in Makefile). Graphviz and Xdot are used by the
|
||||||
`show` command to display schematics.
|
`show` command to display schematics.
|
||||||
|
|
||||||
Installing all prerequisites for Ubuntu 22.04:
|
Installing all prerequisites:
|
||||||
|
|
||||||
.. code:: console
|
.. tab:: Ubuntu 22.04
|
||||||
|
|
||||||
sudo apt-get install gperf build-essential clang lld bison flex libfl-dev \
|
|
||||||
libreadline-dev gawk tcl-dev libffi-dev git \
|
|
||||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
|
||||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
|
||||||
|
|
||||||
Installing all prerequisites for macOS 13 (with Homebrew):
|
|
||||||
|
|
||||||
.. code:: console
|
|
||||||
|
|
||||||
brew tap Homebrew/bundle && brew bundle
|
|
||||||
|
|
||||||
or MacPorts:
|
|
||||||
|
|
||||||
.. code:: console
|
|
||||||
|
|
||||||
sudo port install bison flex readline gawk libffi graphviz \
|
|
||||||
pkgconfig python311 boost zlib tcl
|
|
||||||
|
|
||||||
On FreeBSD use the following command to install all prerequisites:
|
|
||||||
|
|
||||||
.. code:: console
|
|
||||||
|
|
||||||
pkg install bison flex readline gawk libffi graphviz \
|
|
||||||
pkgconf python311 tcl-wrapper boost-libs
|
|
||||||
|
|
||||||
.. note:: On FreeBSD system use gmake instead of make. To run tests use:
|
|
||||||
``MAKE=gmake CXX=cxx CC=cc gmake test``
|
|
||||||
|
|
||||||
For Cygwin use the following command to install all prerequisites, or select these additional packages:
|
|
||||||
|
|
||||||
.. code:: console
|
|
||||||
|
|
||||||
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
As of this writing, Cygwin only supports up to Python 3.9.16 while the
|
|
||||||
minimum required version of Python is 3.11. This means that Cygwin is not
|
|
||||||
compatible with many of the Python-based frontends. While this does not
|
|
||||||
currently prevent Yosys itself from working, no guarantees are made for
|
|
||||||
continued support. You may also need to specify `CXXSTD=gnu++17` to resolve
|
|
||||||
missing `strdup` function when using gcc. It is instead recommended to use
|
|
||||||
Windows Subsystem for Linux (WSL) and follow the instructions for Ubuntu.
|
|
||||||
|
|
||||||
..
|
|
||||||
For MSYS2 (MINGW64):
|
|
||||||
|
|
||||||
.. code:: console
|
.. code:: console
|
||||||
|
|
||||||
pacman -S bison flex mingw-w64-x86_64-gcc git libffi-devel libreadline-devel make pkg-config python3 tcl-devel mingw-w64-x86_64-boost zlib-devel
|
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
|
||||||
|
|
||||||
|
.. tab:: macOS 13 (with Homebrew)
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
brew tap Homebrew/bundle && brew bundle
|
||||||
|
|
||||||
|
.. tab:: MacPorts
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
sudo port install bison flex readline gawk libffi graphviz \
|
||||||
|
pkgconfig python311 zlib tcl
|
||||||
|
|
||||||
|
.. tab:: FreeBSD
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
pkg install bison flex readline gawk libffi graphviz \
|
||||||
|
pkgconf python311 tcl-wrapper
|
||||||
|
|
||||||
|
.. note:: On FreeBSD system use gmake instead of make. To run tests use:
|
||||||
|
``MAKE=gmake CXX=cxx CC=cc gmake test``
|
||||||
|
|
||||||
|
.. tab:: Cygwin
|
||||||
|
|
||||||
|
Use the following command to install all prerequisites, or select these
|
||||||
|
additional packages:
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,zlib-devel
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
As of this writing, Cygwin only supports up to Python 3.9.16 while the
|
||||||
|
minimum required version of Python is 3.11. This means that Cygwin is not
|
||||||
|
compatible with many of the Python-based frontends. While this does not
|
||||||
|
currently prevent Yosys itself from working, no guarantees are made for
|
||||||
|
continued support. You may also need to specify ``CXXSTD=gnu++17`` to
|
||||||
|
resolve missing ``strdup`` function when using gcc. It is instead
|
||||||
|
recommended to use Windows Subsystem for Linux (WSL) and follow the
|
||||||
|
instructions for Ubuntu.
|
||||||
|
|
||||||
|
..
|
||||||
|
tab:: MSYS2 (MINGW64)
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
pacman -S bison flex mingw-w64-x86_64-gcc git libffi-devel libreadline-devel make pkg-config python3 tcl-devel zlib-devel
|
||||||
|
|
||||||
Not that I can get this to work; it's failing during ld with what looks like
|
Not that I can get this to work; it's failing during ld with what looks like
|
||||||
math library issues: ``multiple definition of `tanh'`` and
|
math library issues: ``multiple definition of `tanh'`` and
|
||||||
|
|
@ -215,7 +221,7 @@ Running the build system
|
||||||
From the root ``yosys`` directory, call the following commands:
|
From the root ``yosys`` directory, call the following commands:
|
||||||
|
|
||||||
.. code:: console
|
.. code:: console
|
||||||
|
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
||||||
|
|
@ -228,7 +234,7 @@ To use a separate (out-of-tree) build directory, provide a path to the Makefile.
|
||||||
|
|
||||||
Out-of-tree builds require a clean source tree.
|
Out-of-tree builds require a clean source tree.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
Refer to :doc:`/yosys_internals/extending_yosys/test_suites` for details on
|
Refer to :doc:`/yosys_internals/extending_yosys/test_suites` for details on
|
||||||
testing Yosys once compiled.
|
testing Yosys once compiled.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
furo-ys @ git+https://github.com/YosysHQ/furo-ys
|
furo-ys @ git+https://github.com/YosysHQ/furo-ys
|
||||||
sphinxcontrib-bibtex
|
sphinxcontrib-bibtex
|
||||||
rtds-action
|
rtds-action
|
||||||
|
sphinx-inline-tabs
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,14 @@ methods:
|
||||||
|
|
||||||
``yosys -y ./my_pyosys_script.py``
|
``yosys -y ./my_pyosys_script.py``
|
||||||
|
|
||||||
|
Do note this requires some build-time dependencies to be available to Python,
|
||||||
|
namely, ``pybind11`` and ``cxxheaderparser``. By default, the required
|
||||||
|
``uv`` package will be used to create an ephemeral environment with the
|
||||||
|
correct versions of the tools installed.
|
||||||
|
|
||||||
|
You can force use of your current Python environment by passing the Makefile
|
||||||
|
flag ``PYOSYS_USE_UV=0``.
|
||||||
|
|
||||||
2. Installing the Pyosys wheels
|
2. Installing the Pyosys wheels
|
||||||
|
|
||||||
On macOS and GNU/Linux you can install pre-built wheels of Yosys using
|
On macOS and GNU/Linux you can install pre-built wheels of Yosys using
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ Yosys and there are currently no plans to add support
|
||||||
for them:
|
for them:
|
||||||
|
|
||||||
- Non-synthesizable language features as defined in
|
- Non-synthesizable language features as defined in
|
||||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||||
|
|
||||||
- The ``tri``, ``triand`` and ``trior`` net types
|
- The ``tri``, ``triand`` and ``trior`` net types
|
||||||
|
|
||||||
|
|
@ -356,21 +356,29 @@ from SystemVerilog:
|
||||||
files being read into the same design afterwards.
|
files being read into the same design afterwards.
|
||||||
|
|
||||||
- typedefs are supported (including inside packages)
|
- typedefs are supported (including inside packages)
|
||||||
- type casts are currently not supported
|
|
||||||
|
- type casts are currently not supported
|
||||||
|
|
||||||
- enums are supported (including inside packages)
|
- enums are supported (including inside packages)
|
||||||
- but are currently not strongly typed
|
|
||||||
|
- but are currently not strongly typed
|
||||||
|
|
||||||
- packed structs and unions are supported
|
- packed structs and unions are supported
|
||||||
- arrays of packed structs/unions are currently not supported
|
|
||||||
- structure literals are currently not supported
|
- arrays of packed structs/unions are currently not supported
|
||||||
|
- structure literals are currently not supported
|
||||||
|
|
||||||
- multidimensional arrays are supported
|
- multidimensional arrays are supported
|
||||||
- array assignment of unpacked arrays is currently not supported
|
|
||||||
- array literals are currently not supported
|
|
||||||
|
|
||||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
- array assignment of unpacked arrays is currently not supported
|
||||||
ports are inputs or outputs are supported.
|
- array literals are currently not supported
|
||||||
|
|
||||||
|
- SystemVerilog interfaces (SVIs), including modports for specifying whether
|
||||||
|
ports are inputs or outputs, are partially supported.
|
||||||
|
|
||||||
|
- interfaces must be provided as *named* arguments, not positional arguments.
|
||||||
|
i.e. ``foo bar(.intf(intf0), .x(x));`` is supported but ``foo bar(intf0,
|
||||||
|
x);`` is not.
|
||||||
|
|
||||||
- Assignments within expressions are supported.
|
- Assignments within expressions are supported.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,72 @@
|
||||||
Testing Yosys
|
Testing Yosys
|
||||||
=============
|
=============
|
||||||
|
|
||||||
.. TODO:: more about the included test suite and how to add tests
|
.. todo:: adding tests (makefile-tests vs seed-tests)
|
||||||
|
|
||||||
|
Running the included test suite
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The Yosys source comes with a test suite to avoid regressions and keep
|
||||||
|
everything working as expected. Tests can be run by calling ``make test`` from
|
||||||
|
the root Yosys directory.
|
||||||
|
|
||||||
|
Functional tests
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Testing functional backends (see
|
||||||
|
:doc:`/yosys_internals/extending_yosys/functional_ir`) has a few requirements in
|
||||||
|
addition to those listed in :ref:`getting_started/installation:Build
|
||||||
|
prerequisites`:
|
||||||
|
|
||||||
|
.. tab:: Ubuntu
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
sudo apt-get install racket
|
||||||
|
raco pkg install rosette
|
||||||
|
pip install pytest-xdist pytest-xdist-gnumake
|
||||||
|
|
||||||
|
.. tab:: macOS
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
brew install racket
|
||||||
|
raco pkg install rosette
|
||||||
|
pip install pytest-xdist pytest-xdist-gnumake
|
||||||
|
|
||||||
|
If you don't have one of the :ref:`getting_started/installation:CAD suite(s)`
|
||||||
|
installed, you should also install Z3 `following their
|
||||||
|
instructions <https://github.com/Z3Prover/z3>`_.
|
||||||
|
|
||||||
|
Then, set the :makevar:`ENABLE_FUNCTIONAL_TESTS` make variable when calling
|
||||||
|
``make test`` and the functional tests will be run as well.
|
||||||
|
|
||||||
|
Unit tests
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Running the unit tests requires the following additional packages:
|
||||||
|
|
||||||
|
.. tab:: Ubuntu
|
||||||
|
|
||||||
|
.. code:: console
|
||||||
|
|
||||||
|
sudo apt-get install libgtest-dev
|
||||||
|
|
||||||
|
.. tab:: macOS
|
||||||
|
|
||||||
|
No additional requirements.
|
||||||
|
|
||||||
|
Unit tests can be run with ``make unit-test``.
|
||||||
|
|
||||||
|
Docs tests
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
There are some additional tests for checking examples included in the
|
||||||
|
documentation, which can be run by calling ``make test`` from the
|
||||||
|
:file:`yosys/docs` sub-directory (or ``make -C docs test`` from the root). This
|
||||||
|
also includes checking some macro commands to ensure that descriptions of them
|
||||||
|
are kept up to date, and is mostly intended for CI.
|
||||||
|
|
||||||
|
|
||||||
Automatic testing
|
Automatic testing
|
||||||
-----------------
|
-----------------
|
||||||
|
|
@ -14,8 +79,6 @@ compiler versions. For up to date information, including OS versions, refer to
|
||||||
.. _Yosys Git repo: https://github.com/YosysHQ/yosys
|
.. _Yosys Git repo: https://github.com/YosysHQ/yosys
|
||||||
.. _the git actions page: https://github.com/YosysHQ/yosys/actions
|
.. _the git actions page: https://github.com/YosysHQ/yosys/actions
|
||||||
|
|
||||||
.. todo:: are unit tests currently working
|
|
||||||
|
|
||||||
..
|
..
|
||||||
How to add a unit test
|
How to add a unit test
|
||||||
----------------------
|
----------------------
|
||||||
|
|
|
||||||
|
|
@ -194,17 +194,18 @@ RTLIL::SigSpec
|
||||||
|
|
||||||
A "signal" is everything that can be applied to a cell port. I.e.
|
A "signal" is everything that can be applied to a cell port. I.e.
|
||||||
|
|
||||||
- | Any constant value of arbitrary bit-width
|
- | A bit from a wire (``RTLIL::SigBit``)
|
||||||
|
| 1em For example: ``mywire[24]``
|
||||||
|
|
||||||
|
- | A range of bits from a wire (wire variant of ``RTLIL::SigChunk``)
|
||||||
|
| 1em For example: ``mywire, mywire[15:8]``
|
||||||
|
|
||||||
|
- | Any constant value of arbitrary bit-width (``std::vector<RTLIL::State>>`` variant of ``RTLIL::SigChunk``)
|
||||||
| 1em For example: ``1337, 16'b0000010100111001, 1'b1, 1'bx``
|
| 1em For example: ``1337, 16'b0000010100111001, 1'b1, 1'bx``
|
||||||
|
|
||||||
- | All bits of a wire or a selection of bits from a wire
|
The ``RTLIL::SigSpec`` data type is used to represent signals.
|
||||||
| 1em For example: ``mywire, mywire[24], mywire[15:8]``
|
It contains a single ``RTLIL::SigChunk`` or a vector of ``RTLIL::SigBit``.
|
||||||
|
The ``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||||
- | Concatenations of the above
|
|
||||||
| 1em For example: ``{16'd1337, mywire[15:8]}``
|
|
||||||
|
|
||||||
The ``RTLIL::SigSpec`` data type is used to represent signals. The
|
|
||||||
``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
|
||||||
|
|
||||||
In addition, connections between wires are represented using a pair of
|
In addition, connections between wires are represented using a pair of
|
||||||
``RTLIL::SigSpec`` objects. Such pairs are needed in different locations.
|
``RTLIL::SigSpec`` objects. Such pairs are needed in different locations.
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
packages.default = yosys;
|
packages.default = yosys;
|
||||||
defaultPackage = yosys;
|
defaultPackage = yosys;
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [ clang llvmPackages.bintools gcc bison flex libffi tcl readline python3 zlib git gtest abc-verifier verilog boost python3Packages.boost ];
|
buildInputs = with pkgs; [ clang llvmPackages.bintools gcc bison flex libffi tcl readline python3 zlib git gtest abc-verifier verilog ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "libs/sha1/sha1.h"
|
#include "libs/sha1/sha1.h"
|
||||||
#include "frontends/verilog/verilog_frontend.h"
|
#include "frontends/verilog/verilog_frontend.h"
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
|
#include "kernel/io.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
@ -888,6 +889,52 @@ static void check_auto_nosync(AstNode *node)
|
||||||
check_auto_nosync(child.get());
|
check_auto_nosync(child.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PackageImporter {
|
||||||
|
std::set<std::string> import_items;
|
||||||
|
bool is_wildcard;
|
||||||
|
const AstNode* node;
|
||||||
|
public:
|
||||||
|
PackageImporter(const AstNode* n, const AstNode* child) : node(n) {
|
||||||
|
is_wildcard = child->children.empty();
|
||||||
|
// For specific imports, collect the list of items to import
|
||||||
|
if (!is_wildcard) {
|
||||||
|
for (auto& item : child->children) {
|
||||||
|
import_items.insert(item->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void import(std::map<std::string, AstNode*>& scope, AstNode* to_import) const {
|
||||||
|
// Check if this is a specific import and if this item should be imported
|
||||||
|
if (!is_wildcard && import_items.count(to_import->str) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (to_import->type == AST_PARAMETER || to_import->type == AST_LOCALPARAM ||
|
||||||
|
to_import->type == AST_TYPEDEF || to_import->type == AST_FUNCTION ||
|
||||||
|
to_import->type == AST_TASK || to_import->type == AST_ENUM) {
|
||||||
|
// For wildcard imports, check if item already exists (from specific import)
|
||||||
|
if (is_wildcard && scope.count(to_import->str) > 0)
|
||||||
|
return;
|
||||||
|
scope[to_import->str] = to_import;
|
||||||
|
}
|
||||||
|
if (to_import->type == AST_ENUM) {
|
||||||
|
for (auto& enode : to_import->children) {
|
||||||
|
log_assert(enode->type==AST_ENUM_ITEM);
|
||||||
|
// Check if this enum item should be imported
|
||||||
|
if (!is_wildcard && import_items.count(enode->str) == 0)
|
||||||
|
continue;
|
||||||
|
// For wildcard imports, check if item already exists (from specific import)
|
||||||
|
if (is_wildcard && scope.count(enode->str) > 0)
|
||||||
|
continue;
|
||||||
|
if (scope.count(enode->str) == 0)
|
||||||
|
scope[enode->str] = enode.get();
|
||||||
|
else
|
||||||
|
node->input_error("enum item %s already exists in current scope\n", enode->str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// convert the AST into a simpler AST that has all parameters substituted by their
|
// convert the AST into a simpler AST that has all parameters substituted by their
|
||||||
// values, unrolled for-loops, expanded generate blocks, etc. when this function
|
// values, unrolled for-loops, expanded generate blocks, etc. when this function
|
||||||
// is done with an AST it can be converted into RTLIL using genRTLIL().
|
// is done with an AST it can be converted into RTLIL using genRTLIL().
|
||||||
|
|
@ -1122,22 +1169,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin
|
||||||
}
|
}
|
||||||
|
|
||||||
if (package_node) {
|
if (package_node) {
|
||||||
// Import all names from the package into current scope
|
PackageImporter importer(this, child);
|
||||||
|
// Import names from the package into current scope
|
||||||
for (auto& pkg_child : package_node->children) {
|
for (auto& pkg_child : package_node->children) {
|
||||||
if (pkg_child->type == AST_PARAMETER || pkg_child->type == AST_LOCALPARAM ||
|
importer.import(current_scope, pkg_child.get());
|
||||||
pkg_child->type == AST_TYPEDEF || pkg_child->type == AST_FUNCTION ||
|
|
||||||
pkg_child->type == AST_TASK || pkg_child->type == AST_ENUM) {
|
|
||||||
current_scope[pkg_child->str] = pkg_child.get();
|
|
||||||
}
|
|
||||||
if (pkg_child->type == AST_ENUM) {
|
|
||||||
for (auto& enode : pkg_child->children) {
|
|
||||||
log_assert(enode->type==AST_ENUM_ITEM);
|
|
||||||
if (current_scope.count(enode->str) == 0)
|
|
||||||
current_scope[enode->str] = enode.get();
|
|
||||||
else
|
|
||||||
input_error("enum item %s already exists in current scope\n", enode->str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Remove the import node since it's been processed
|
// Remove the import node since it's been processed
|
||||||
children.erase(children.begin() + i);
|
children.erase(children.begin() + i);
|
||||||
|
|
@ -4474,12 +4509,7 @@ std::unique_ptr<AstNode> AstNode::readmem(bool is_readmemh, std::string mem_file
|
||||||
std::ifstream f;
|
std::ifstream f;
|
||||||
f.open(mem_filename.c_str());
|
f.open(mem_filename.c_str());
|
||||||
if (f.fail()) {
|
if (f.fail()) {
|
||||||
#ifdef _WIN32
|
std::string path = parent_from_file_path(*location.begin.filename);
|
||||||
char slash = '\\';
|
|
||||||
#else
|
|
||||||
char slash = '/';
|
|
||||||
#endif
|
|
||||||
std::string path = location.begin.filename->substr(0, location.begin.filename->find_last_of(slash)+1);
|
|
||||||
f.open(path + mem_filename.c_str());
|
f.open(path + mem_filename.c_str());
|
||||||
yosys_input_files.insert(path + mem_filename);
|
yosys_input_files.insert(path + mem_filename);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1576,6 +1576,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
||||||
SetIter si ;
|
SetIter si ;
|
||||||
Port *port ;
|
Port *port ;
|
||||||
FOREACH_PORT_OF_PORTBUS(portbus, si, port) {
|
FOREACH_PORT_OF_PORTBUS(portbus, si, port) {
|
||||||
|
wire->port_id = nl->IndexOf(port) + 1;
|
||||||
import_attributes(wire->attributes, port->GetNet(), nl, portbus->Size());
|
import_attributes(wire->attributes, port->GetNet(), nl, portbus->Size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -895,11 +895,7 @@ frontend_verilog_preproc(std::istream &f,
|
||||||
// if the include file was not found, it is not given with an absolute path, and the
|
// if the include file was not found, it is not given with an absolute path, and the
|
||||||
// currently read file is given with a path, then try again relative to its directory
|
// currently read file is given with a path, then try again relative to its directory
|
||||||
ff.clear();
|
ff.clear();
|
||||||
#ifdef _WIN32
|
fixed_fn = parent_from_file_path(filename) + fn;
|
||||||
fixed_fn = filename.substr(0, filename.find_last_of("/\\")+1) + fn;
|
|
||||||
#else
|
|
||||||
fixed_fn = filename.substr(0, filename.rfind('/')+1) + fn;
|
|
||||||
#endif
|
|
||||||
ff.open(fixed_fn);
|
ff.open(fixed_fn);
|
||||||
}
|
}
|
||||||
if (ff.fail() && fn.size() > 0 && fn_relative) {
|
if (ff.fail() && fn.size() > 0 && fn_relative) {
|
||||||
|
|
|
||||||
|
|
@ -829,11 +829,31 @@ package_body_stmt:
|
||||||
typedef_decl | localparam_decl | param_decl | task_func_decl;
|
typedef_decl | localparam_decl | param_decl | task_func_decl;
|
||||||
|
|
||||||
import_stmt:
|
import_stmt:
|
||||||
TOK_IMPORT hierarchical_id TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL {
|
TOK_IMPORT TOK_ID TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL {
|
||||||
// Create an import node to track package imports
|
// Create an import node to track wildcard package imports
|
||||||
auto import_node = std::make_unique<AstNode>(@$, AST_IMPORT);
|
auto import_node = std::make_unique<AstNode>(@$, AST_IMPORT);
|
||||||
import_node->str = *$2;
|
import_node->str = *$2;
|
||||||
extra->ast_stack.back()->children.push_back(std::move(import_node));
|
extra->ast_stack.back()->children.push_back(std::move(import_node));
|
||||||
|
} |
|
||||||
|
TOK_IMPORT TOK_ID TOK_PACKAGESEP {
|
||||||
|
// Start a specific import: create and push the AST_IMPORT node
|
||||||
|
AstNode* import_node = extra->pushChild(std::make_unique<AstNode>(@$, AST_IMPORT));
|
||||||
|
import_node->str = *$2;
|
||||||
|
} import_item_list TOK_SEMICOL {
|
||||||
|
// Done collecting specific items, pop the AST_IMPORT node
|
||||||
|
extra->ast_stack.pop_back();
|
||||||
|
};
|
||||||
|
|
||||||
|
import_item_list:
|
||||||
|
import_item |
|
||||||
|
import_item_list TOK_COMMA import_item ;
|
||||||
|
|
||||||
|
import_item:
|
||||||
|
TOK_ID {
|
||||||
|
// Append this specific import name under the current AST_IMPORT
|
||||||
|
auto item_node = std::make_unique<AstNode>(@$, AST_NONE);
|
||||||
|
item_node->str = *$1;
|
||||||
|
extra->ast_stack.back()->children.push_back(std::move(item_node));
|
||||||
};
|
};
|
||||||
|
|
||||||
interface:
|
interface:
|
||||||
|
|
|
||||||
|
|
@ -1021,7 +1021,7 @@ protected:
|
||||||
if (hashtable.empty()) {
|
if (hashtable.empty()) {
|
||||||
entries.emplace_back(std::forward<K>(rvalue), -1);
|
entries.emplace_back(std::forward<K>(rvalue), -1);
|
||||||
do_rehash();
|
do_rehash();
|
||||||
hash = do_hash(rvalue);
|
hash = do_hash(entries.back().udata);
|
||||||
} else {
|
} else {
|
||||||
entries.emplace_back(std::forward<K>(rvalue), hashtable[hash]);
|
entries.emplace_back(std::forward<K>(rvalue), hashtable[hash]);
|
||||||
hashtable[hash] = entries.size() - 1;
|
hashtable[hash] = entries.size() - 1;
|
||||||
|
|
|
||||||
19
kernel/io.cc
19
kernel/io.cc
|
|
@ -2,6 +2,7 @@
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
@ -391,6 +392,24 @@ void append_globbed(std::vector<std::string>& paths, std::string pattern)
|
||||||
copy(globbed.begin(), globbed.end(), back_inserter(paths));
|
copy(globbed.begin(), globbed.end(), back_inserter(paths));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string name_from_file_path(std::string path) {
|
||||||
|
return std::filesystem::path(path).filename().string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Includes OS_PATH_SEP at the end if present
|
||||||
|
std::string parent_from_file_path(std::string path) {
|
||||||
|
auto parent = std::filesystem::path(path).parent_path();
|
||||||
|
if (parent.empty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// Add trailing separator to match original behavior
|
||||||
|
std::string result = parent.string();
|
||||||
|
if (!result.empty() && result.back() != std::filesystem::path::preferred_separator) {
|
||||||
|
result += std::filesystem::path::preferred_separator;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void format_emit_unescaped(std::string &result, std::string_view fmt)
|
void format_emit_unescaped(std::string &result, std::string_view fmt)
|
||||||
{
|
{
|
||||||
result.reserve(result.size() + fmt.size());
|
result.reserve(result.size() + fmt.size());
|
||||||
|
|
|
||||||
|
|
@ -470,6 +470,8 @@ void remove_directory(std::string dirname);
|
||||||
bool create_directory(const std::string& dirname);
|
bool create_directory(const std::string& dirname);
|
||||||
std::string escape_filename_spaces(const std::string& filename);
|
std::string escape_filename_spaces(const std::string& filename);
|
||||||
void append_globbed(std::vector<std::string>& paths, std::string pattern);
|
void append_globbed(std::vector<std::string>& paths, std::string pattern);
|
||||||
|
std::string name_from_file_path(std::string path);
|
||||||
|
std::string parent_from_file_path(std::string path);
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
||||||
|
|
|
||||||
1017
kernel/rtlil.cc
1017
kernel/rtlil.cc
File diff suppressed because it is too large
Load diff
265
kernel/rtlil.h
265
kernel/rtlil.h
|
|
@ -569,6 +569,7 @@ template <> struct IDMacroHelper<-1> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef ID
|
||||||
#define ID(_id) \
|
#define ID(_id) \
|
||||||
YOSYS_NAMESPACE_PREFIX IDMacroHelper< \
|
YOSYS_NAMESPACE_PREFIX IDMacroHelper< \
|
||||||
YOSYS_NAMESPACE_PREFIX lookup_well_known_id(#_id) \
|
YOSYS_NAMESPACE_PREFIX lookup_well_known_id(#_id) \
|
||||||
|
|
@ -1222,9 +1223,10 @@ struct RTLIL::SigSpecConstIterator
|
||||||
typedef RTLIL::SigBit& reference;
|
typedef RTLIL::SigBit& reference;
|
||||||
|
|
||||||
const RTLIL::SigSpec *sig_p;
|
const RTLIL::SigSpec *sig_p;
|
||||||
|
RTLIL::SigBit bit;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
inline const RTLIL::SigBit &operator*() const;
|
inline const RTLIL::SigBit &operator*();
|
||||||
inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; }
|
inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; }
|
||||||
inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; }
|
inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; }
|
||||||
inline void operator++() { index++; }
|
inline void operator++() { index++; }
|
||||||
|
|
@ -1233,33 +1235,84 @@ struct RTLIL::SigSpecConstIterator
|
||||||
struct RTLIL::SigSpec
|
struct RTLIL::SigSpec
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int width_;
|
enum Representation : char {
|
||||||
Hasher::hash_t hash_;
|
CHUNK,
|
||||||
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
|
BITS,
|
||||||
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
};
|
||||||
|
// An AtomicHash is either clear or a nonzero integer.
|
||||||
|
struct AtomicHash {
|
||||||
|
// Create an initially clear value.
|
||||||
|
AtomicHash() : atomic_(0) {}
|
||||||
|
AtomicHash(const AtomicHash &rhs) : atomic_(rhs.load()) {}
|
||||||
|
AtomicHash &operator=(const AtomicHash &rhs) { store(rhs.load()); return *this; }
|
||||||
|
// Read the hash. Returns nullopt if the hash is clear.
|
||||||
|
std::optional<Hasher::hash_t> read() const {
|
||||||
|
Hasher::hash_t value = load();
|
||||||
|
if (value == 0)
|
||||||
|
return std::nullopt;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
// Set the hash. If the value is already set, then the new value must
|
||||||
|
// equal the current value.
|
||||||
|
void set(Hasher::hash_t value) const {
|
||||||
|
log_assert(value != 0);
|
||||||
|
Hasher::hash_t old = const_cast<std::atomic<Hasher::hash_t>&>(atomic_)
|
||||||
|
.exchange(value, std::memory_order_relaxed);
|
||||||
|
log_assert(old == 0 || old == value);
|
||||||
|
}
|
||||||
|
void clear() { store(0); }
|
||||||
|
private:
|
||||||
|
int load() const { return atomic_.load(std::memory_order_relaxed); }
|
||||||
|
void store(Hasher::hash_t value) const {
|
||||||
|
const_cast<std::atomic<Hasher::hash_t>&>(atomic_).store(value, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
void pack() const;
|
std::atomic<Hasher::hash_t> atomic_;
|
||||||
void unpack() const;
|
};
|
||||||
void updhash() const;
|
|
||||||
|
|
||||||
inline bool packed() const {
|
Representation rep_;
|
||||||
return bits_.empty();
|
AtomicHash hash_;
|
||||||
|
union {
|
||||||
|
RTLIL::SigChunk chunk_;
|
||||||
|
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
||||||
|
};
|
||||||
|
|
||||||
|
void init_empty_bits() {
|
||||||
|
rep_ = BITS;
|
||||||
|
new (&bits_) std::vector<RTLIL::SigBit>;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void inline_unpack() const {
|
void unpack();
|
||||||
if (!chunks_.empty())
|
inline void inline_unpack() {
|
||||||
|
if (rep_ == CHUNK)
|
||||||
unpack();
|
unpack();
|
||||||
}
|
}
|
||||||
|
void try_repack();
|
||||||
|
|
||||||
// Only used by Module::remove(const pool<Wire*> &wires)
|
Hasher::hash_t updhash() const;
|
||||||
// but cannot be more specific as it isn't yet declared
|
void destroy() {
|
||||||
friend struct RTLIL::Module;
|
if (rep_ == CHUNK)
|
||||||
|
chunk_.~SigChunk();
|
||||||
|
else
|
||||||
|
bits_.~vector();
|
||||||
|
}
|
||||||
|
friend struct Chunks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SigSpec() : width_(0), hash_(0) {}
|
SigSpec() { init_empty_bits(); }
|
||||||
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
|
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
|
||||||
SigSpec(const SigSpec &value) = default;
|
SigSpec(const SigSpec &value) : rep_(value.rep_), hash_(value.hash_) {
|
||||||
SigSpec(SigSpec &&value) = default;
|
if (value.rep_ == CHUNK)
|
||||||
|
new (&chunk_) RTLIL::SigChunk(value.chunk_);
|
||||||
|
else
|
||||||
|
new (&bits_) std::vector<RTLIL::SigBit>(value.bits_);
|
||||||
|
}
|
||||||
|
SigSpec(SigSpec &&value) : rep_(value.rep_), hash_(value.hash_) {
|
||||||
|
if (value.rep_ == CHUNK)
|
||||||
|
new (&chunk_) RTLIL::SigChunk(std::move(value.chunk_));
|
||||||
|
else
|
||||||
|
new (&bits_) std::vector<RTLIL::SigBit>(std::move(value.bits_));
|
||||||
|
}
|
||||||
SigSpec(const RTLIL::Const &value);
|
SigSpec(const RTLIL::Const &value);
|
||||||
SigSpec(RTLIL::Const &&value);
|
SigSpec(RTLIL::Const &&value);
|
||||||
SigSpec(const RTLIL::SigChunk &chunk);
|
SigSpec(const RTLIL::SigChunk &chunk);
|
||||||
|
|
@ -1275,24 +1328,138 @@ public:
|
||||||
SigSpec(const pool<RTLIL::SigBit> &bits);
|
SigSpec(const pool<RTLIL::SigBit> &bits);
|
||||||
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
||||||
explicit SigSpec(bool bit);
|
explicit SigSpec(bool bit);
|
||||||
|
~SigSpec() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
SigSpec &operator=(const SigSpec &rhs) = default;
|
SigSpec &operator=(const SigSpec &rhs) {
|
||||||
SigSpec &operator=(SigSpec &&rhs) = default;
|
destroy();
|
||||||
|
rep_ = rhs.rep_;
|
||||||
|
hash_ = rhs.hash_;
|
||||||
|
if (rep_ == CHUNK)
|
||||||
|
new (&chunk_) RTLIL::SigChunk(rhs.chunk_);
|
||||||
|
else
|
||||||
|
new (&bits_) std::vector<RTLIL::SigBit>(rhs.bits_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SigSpec &operator=(SigSpec &&rhs) {
|
||||||
|
destroy();
|
||||||
|
rep_ = rhs.rep_;
|
||||||
|
hash_ = rhs.hash_;
|
||||||
|
if (rep_ == CHUNK)
|
||||||
|
new (&chunk_) RTLIL::SigChunk(std::move(rhs.chunk_));
|
||||||
|
else
|
||||||
|
new (&bits_) std::vector<RTLIL::SigBit>(std::move(rhs.bits_));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
|
// SigSpec::Chunks holds one reconstructed chunk at a time
|
||||||
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }
|
// to provide the SigSpec::chunks() read-only chunks view
|
||||||
|
// since vector<SigChunk> SigSpec::chunks_ has been removed
|
||||||
|
struct Chunks {
|
||||||
|
Chunks(const SigSpec &spec) : spec(spec) {}
|
||||||
|
struct const_iterator {
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using value_type = const SigChunk &;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const SigChunk *;
|
||||||
|
using reference = const SigChunk &;
|
||||||
|
|
||||||
inline int size() const { return width_; }
|
const SigSpec &spec;
|
||||||
inline bool empty() const { return width_ == 0; }
|
int bit_index;
|
||||||
|
SigChunk chunk;
|
||||||
|
|
||||||
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); }
|
const_iterator(const SigSpec &spec) : spec(spec) {
|
||||||
inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); }
|
bit_index = 0;
|
||||||
|
if (spec.rep_ == BITS)
|
||||||
|
next_chunk_bits();
|
||||||
|
}
|
||||||
|
enum End { END };
|
||||||
|
const_iterator(const SigSpec &spec, End) : spec(spec) {
|
||||||
|
bit_index = spec.size();
|
||||||
|
}
|
||||||
|
void next_chunk_bits();
|
||||||
|
|
||||||
|
const SigChunk &operator*() {
|
||||||
|
if (spec.rep_ == CHUNK)
|
||||||
|
return spec.chunk_;
|
||||||
|
return chunk;
|
||||||
|
};
|
||||||
|
const SigChunk *operator->() { return &**this; }
|
||||||
|
const_iterator &operator++() {
|
||||||
|
bit_index += (**this).width;
|
||||||
|
if (spec.rep_ == BITS)
|
||||||
|
next_chunk_bits();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
bool operator==(const const_iterator &rhs) const { return bit_index == rhs.bit_index; }
|
||||||
|
bool operator!=(const const_iterator &rhs) const { return !(*this == rhs); }
|
||||||
|
};
|
||||||
|
const_iterator begin() const { return const_iterator(spec); }
|
||||||
|
const_iterator end() const {
|
||||||
|
const_iterator it(spec, const_iterator::END);
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
// Later we should deprecate these and remove their in-tree calls,
|
||||||
|
// so we can eventually remove chunk_vector.
|
||||||
|
std::vector<RTLIL::SigChunk>::const_reverse_iterator rbegin() {
|
||||||
|
ensure_chunk_vector();
|
||||||
|
return chunk_vector.rbegin();
|
||||||
|
}
|
||||||
|
std::vector<RTLIL::SigChunk>::const_reverse_iterator rend() {
|
||||||
|
ensure_chunk_vector();
|
||||||
|
return chunk_vector.rend();
|
||||||
|
}
|
||||||
|
int size() {
|
||||||
|
ensure_chunk_vector();
|
||||||
|
return chunk_vector.size();
|
||||||
|
}
|
||||||
|
int size() const {
|
||||||
|
return std::distance(begin(), end());
|
||||||
|
}
|
||||||
|
const SigChunk &at(int index) {
|
||||||
|
ensure_chunk_vector();
|
||||||
|
return chunk_vector.at(index);
|
||||||
|
}
|
||||||
|
operator const std::vector<RTLIL::SigChunk>&() {
|
||||||
|
ensure_chunk_vector();
|
||||||
|
return chunk_vector;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void ensure_chunk_vector() {
|
||||||
|
if (spec.size() > 0 && chunk_vector.empty()) {
|
||||||
|
for (const RTLIL::SigChunk &c : *this)
|
||||||
|
chunk_vector.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const SigSpec &spec;
|
||||||
|
std::vector<RTLIL::SigChunk> chunk_vector;
|
||||||
|
};
|
||||||
|
friend struct Chunks::const_iterator;
|
||||||
|
|
||||||
|
inline Chunks chunks() const { return {*this}; }
|
||||||
|
inline const SigSpec &bits() const { return *this; }
|
||||||
|
|
||||||
|
inline int size() const { return rep_ == CHUNK ? chunk_.width : GetSize(bits_); }
|
||||||
|
inline bool empty() const { return size() == 0; };
|
||||||
|
|
||||||
|
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_.clear(); return bits_.at(index); }
|
||||||
|
inline RTLIL::SigBit operator[](int index) const {
|
||||||
|
if (rep_ == CHUNK) {
|
||||||
|
if (index < 0 || index >= chunk_.width)
|
||||||
|
throw std::out_of_range("SigSpec::operator[]");
|
||||||
|
if (chunk_.wire)
|
||||||
|
return RTLIL::SigBit(chunk_.wire, chunk_.offset + index);
|
||||||
|
return RTLIL::SigBit(chunk_.data[index]);
|
||||||
|
}
|
||||||
|
return bits_.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; }
|
inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; }
|
||||||
inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; }
|
inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = size(); return it; }
|
||||||
|
|
||||||
inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; }
|
inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; }
|
||||||
inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = width_; return it; }
|
inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = size(); return it; }
|
||||||
|
|
||||||
void sort();
|
void sort();
|
||||||
void sort_and_unify();
|
void sort_and_unify();
|
||||||
|
|
@ -1324,10 +1491,14 @@ public:
|
||||||
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
|
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||||
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
|
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
|
||||||
RTLIL::SigSpec extract(int offset, int length = 1) const;
|
RTLIL::SigSpec extract(int offset, int length = 1) const;
|
||||||
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); }
|
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, size() - offset); }
|
||||||
|
|
||||||
RTLIL::SigBit lsb() const { log_assert(width_); return (*this)[0]; };
|
void rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite);
|
||||||
RTLIL::SigBit msb() const { log_assert(width_); return (*this)[width_ - 1]; };
|
|
||||||
|
RTLIL::SigBit lsb() const { log_assert(size()); return (*this)[0]; };
|
||||||
|
RTLIL::SigBit msb() const { log_assert(size()); return (*this)[size() - 1]; };
|
||||||
|
RTLIL::SigBit front() const { return (*this)[0]; }
|
||||||
|
RTLIL::SigBit back() const { return (*this)[size() - 1]; }
|
||||||
|
|
||||||
void append(const RTLIL::SigSpec &signal);
|
void append(const RTLIL::SigSpec &signal);
|
||||||
inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); }
|
inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); }
|
||||||
|
|
@ -1350,7 +1521,7 @@ public:
|
||||||
|
|
||||||
bool is_wire() const;
|
bool is_wire() const;
|
||||||
bool is_chunk() const;
|
bool is_chunk() const;
|
||||||
inline bool is_bit() const { return width_ == 1; }
|
inline bool is_bit() const { return size() == 1; }
|
||||||
|
|
||||||
bool known_driver() const;
|
bool known_driver() const;
|
||||||
|
|
||||||
|
|
@ -1387,6 +1558,9 @@ public:
|
||||||
int as_int_saturating(bool is_signed = false) const;
|
int as_int_saturating(bool is_signed = false) const;
|
||||||
|
|
||||||
std::string as_string() const;
|
std::string as_string() const;
|
||||||
|
// Returns std::nullopt if there are any non-constant bits. Returns an empty
|
||||||
|
// Const if this has zero width.
|
||||||
|
std::optional<RTLIL::Const> try_as_const() const;
|
||||||
RTLIL::Const as_const() const;
|
RTLIL::Const as_const() const;
|
||||||
RTLIL::Wire *as_wire() const;
|
RTLIL::Wire *as_wire() const;
|
||||||
RTLIL::SigChunk as_chunk() const;
|
RTLIL::SigChunk as_chunk() const;
|
||||||
|
|
@ -1404,11 +1578,19 @@ public:
|
||||||
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str);
|
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str);
|
||||||
static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
|
static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
|
||||||
|
|
||||||
operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
|
operator std::vector<RTLIL::SigChunk>() const;
|
||||||
operator std::vector<RTLIL::SigBit>() const { return bits(); }
|
operator std::vector<RTLIL::SigBit>() const { return to_sigbit_vector(); }
|
||||||
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
|
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < size() ? (*this)[offset] : defval; }
|
||||||
|
|
||||||
[[nodiscard]] Hasher hash_into(Hasher h) const { if (!hash_) updhash(); h.eat(hash_); return h; }
|
[[nodiscard]] Hasher hash_into(Hasher h) const {
|
||||||
|
Hasher::hash_t val;
|
||||||
|
if (std::optional<Hasher::hash_t> current = hash_.read())
|
||||||
|
val = *current;
|
||||||
|
else
|
||||||
|
val = updhash();
|
||||||
|
h.eat(val);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void check(Module *mod = nullptr) const;
|
void check(Module *mod = nullptr) const;
|
||||||
|
|
@ -1827,6 +2009,7 @@ public:
|
||||||
RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type);
|
RTLIL::Cell *addCell(RTLIL::IdString name, RTLIL::IdString type);
|
||||||
RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other);
|
RTLIL::Cell *addCell(RTLIL::IdString name, const RTLIL::Cell *other);
|
||||||
|
|
||||||
|
RTLIL::Memory *addMemory(RTLIL::IdString name);
|
||||||
RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other);
|
RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other);
|
||||||
|
|
||||||
RTLIL::Process *addProcess(RTLIL::IdString name);
|
RTLIL::Process *addProcess(RTLIL::IdString name);
|
||||||
|
|
@ -2312,13 +2495,15 @@ inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
|
||||||
return (*sig_p)[index];
|
return (*sig_p)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const {
|
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() {
|
||||||
return (*sig_p)[index];
|
bit = (*sig_p)[index];
|
||||||
|
return bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
|
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
|
||||||
log_assert(sig.size() == 1 && sig.chunks().size() == 1);
|
log_assert(sig.size() == 1);
|
||||||
*this = SigBit(sig.chunks().front());
|
auto it = sig.chunks().begin();
|
||||||
|
*this = SigBit(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
||||||
|
|
@ -277,14 +277,26 @@ inline int ceil_log2(int x)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto reversed(T& container) {
|
||||||
|
struct reverse_view {
|
||||||
|
reverse_view(T& container) : container(container) {}
|
||||||
|
auto begin() const { return container.rbegin(); }
|
||||||
|
auto end() const { return container.rend(); }
|
||||||
|
T& container;
|
||||||
|
};
|
||||||
|
return reverse_view{container};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto reversed(const T& container) {
|
auto reversed(const T& container) {
|
||||||
struct reverse_view {
|
struct reverse_view {
|
||||||
const T& cont;
|
reverse_view(const T& container) : container(container) {}
|
||||||
auto begin() const { return cont.rbegin(); }
|
auto begin() const { return container.rbegin(); }
|
||||||
auto end() const { return cont.rend(); }
|
auto end() const { return container.rend(); }
|
||||||
};
|
const T& container;
|
||||||
return reverse_view{container};
|
};
|
||||||
|
return reverse_view{container};
|
||||||
}
|
}
|
||||||
|
|
||||||
YOSYS_NAMESPACE_END
|
YOSYS_NAMESPACE_END
|
||||||
|
|
|
||||||
|
|
@ -278,11 +278,12 @@ struct ShowWorker
|
||||||
std::vector<std::string> label_pieces;
|
std::vector<std::string> label_pieces;
|
||||||
int bitpos = sig.size()-1;
|
int bitpos = sig.size()-1;
|
||||||
|
|
||||||
for (int rep, chunk_idx = ((int) sig.chunks().size()) - 1; chunk_idx >= 0; chunk_idx -= rep) {
|
RTLIL::SigSpec::Chunks sig_chunks = sig.chunks();
|
||||||
const RTLIL::SigChunk &c = sig.chunks().at(chunk_idx);
|
for (int rep, chunk_idx = ((int) sig_chunks.size()) - 1; chunk_idx >= 0; chunk_idx -= rep) {
|
||||||
|
const RTLIL::SigChunk &c = sig_chunks.at(chunk_idx);
|
||||||
|
|
||||||
// Find the number of times this chunk is repeating
|
// Find the number of times this chunk is repeating
|
||||||
for (rep = 1; chunk_idx - rep >= 0 && c == sig.chunks().at(chunk_idx - rep); rep++);
|
for (rep = 1; chunk_idx - rep >= 0 && c == sig_chunks.at(chunk_idx - rep); rep++);
|
||||||
|
|
||||||
int cl, cr;
|
int cl, cr;
|
||||||
cl = c.offset + c.width - 1;
|
cl = c.offset + c.width - 1;
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ const arrivalint INF_PAST = std::numeric_limits<arrivalint>::min();
|
||||||
struct EstimateSta {
|
struct EstimateSta {
|
||||||
SigMap sigmap;
|
SigMap sigmap;
|
||||||
Module *m;
|
Module *m;
|
||||||
SigBit clk;
|
std::optional<SigBit> clk;
|
||||||
|
bool top_port_endpoints = false;
|
||||||
|
|
||||||
dict<std::pair<RTLIL::IdString, dict<RTLIL::IdString, RTLIL::Const>>, Aig> aigs;
|
dict<std::pair<RTLIL::IdString, dict<RTLIL::IdString, RTLIL::Const>>, Aig> aigs;
|
||||||
dict<Cell *, Aig *> cell_aigs;
|
dict<Cell *, Aig *> cell_aigs;
|
||||||
|
|
@ -73,15 +74,18 @@ struct EstimateSta {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ignores clock polarity
|
// TODO: ignores clock polarity
|
||||||
EstimateSta(Module *m, SigBit clk)
|
EstimateSta(Module *m, std::optional<SigBit> clk, bool top_port_endpoints)
|
||||||
: sigmap(m), m(m), clk(clk)
|
: sigmap(m), m(m), clk(clk), top_port_endpoints(top_port_endpoints)
|
||||||
{
|
{
|
||||||
sigmap.apply(clk);
|
if (clk.has_value())
|
||||||
|
sigmap.apply(*clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
log("Domain %s\n", log_signal(clk));
|
log("\nModule %s\n", log_id(m));
|
||||||
|
if (clk.has_value())
|
||||||
|
log("Domain %s\n", log_signal(*clk));
|
||||||
|
|
||||||
// first, we collect launch and sample points and convert the combinational logic to AIG
|
// first, we collect launch and sample points and convert the combinational logic to AIG
|
||||||
std::vector<Cell *> combinational;
|
std::vector<Cell *> combinational;
|
||||||
|
|
@ -151,6 +155,22 @@ struct EstimateSta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add top module port launching/sampling, if requested
|
||||||
|
if (top_port_endpoints) {
|
||||||
|
SigSpec all_inputs, all_outputs;
|
||||||
|
for (auto port_id : m->ports) {
|
||||||
|
Wire *port = m->wire(port_id);
|
||||||
|
if (port->port_input && !port->port_output) {
|
||||||
|
all_inputs.append(port);
|
||||||
|
} else if (port->port_output && !port->port_input) {
|
||||||
|
all_outputs.append(port);
|
||||||
|
} else if (port->port_output && port->port_input) {
|
||||||
|
log_warning("Ignoring bi-directional port %s\n", log_id(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_seq(nullptr, all_inputs, all_outputs);
|
||||||
|
}
|
||||||
|
|
||||||
// now we toposort the combinational logic
|
// now we toposort the combinational logic
|
||||||
|
|
||||||
// each toposort node is either a SigBit or a pair of Cell * / AigNode *
|
// each toposort node is either a SigBit or a pair of Cell * / AigNode *
|
||||||
|
|
@ -360,7 +380,7 @@ struct TimeestPass : Pass {
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" timeest [-clk <clk_signal>] [options] [selection]\n");
|
log(" timeest [-clk <clk_signal>] [options] [selection]\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log("Estimate the critical path in clock domain <clk_signal> by counting AIG nodes.\n");
|
log("Estimate the critical path by counting AIG nodes.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -all_paths\n");
|
log(" -all_paths\n");
|
||||||
log(" Print or select nodes from all critical paths instead of focusing on\n");
|
log(" Print or select nodes from all critical paths instead of focusing on\n");
|
||||||
|
|
@ -374,7 +394,8 @@ struct TimeestPass : Pass {
|
||||||
{
|
{
|
||||||
log_header(d, "Executing TIMEEST pass. (estimate timing)\n");
|
log_header(d, "Executing TIMEEST pass. (estimate timing)\n");
|
||||||
|
|
||||||
std::string clk;
|
std::string clk_name;
|
||||||
|
bool clk_domain_specified = false;
|
||||||
bool all_paths = false;
|
bool all_paths = false;
|
||||||
bool select = false;
|
bool select = false;
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
|
|
@ -388,26 +409,30 @@ struct TimeestPass : Pass {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (args[argidx] == "-clk" && argidx + 1 < args.size()) {
|
if (args[argidx] == "-clk" && argidx + 1 < args.size()) {
|
||||||
clk = args[++argidx];
|
clk_domain_specified = true;
|
||||||
|
clk_name = args[++argidx];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, d);
|
extra_args(args, argidx, d);
|
||||||
|
|
||||||
if (clk.empty())
|
|
||||||
log_cmd_error("No -clk argument provided\n");
|
|
||||||
|
|
||||||
if (select && d->selected_modules().size() > 1)
|
if (select && d->selected_modules().size() > 1)
|
||||||
log_cmd_error("The -select option operates on a single selected module\n");
|
log_cmd_error("The -select option operates on a single selected module\n");
|
||||||
|
|
||||||
for (auto m : d->selected_modules()) {
|
for (auto m : d->selected_modules()) {
|
||||||
if (!m->wire(RTLIL::escape_id(clk))) {
|
std::optional<SigBit> clk;
|
||||||
log_warning("No domain '%s' in module %s\n", clk, log_id(m));
|
|
||||||
continue;
|
if (clk_domain_specified) {
|
||||||
|
if (!m->wire(RTLIL::escape_id(clk_name))) {
|
||||||
|
log_warning("No domain '%s' in module %s\n", clk_name.c_str(), log_id(m));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk = SigBit(m->wire(RTLIL::escape_id(clk_name)), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
EstimateSta sta(m, SigBit(m->wire(RTLIL::escape_id(clk)), 0));
|
EstimateSta sta(m, clk, /*top_port_endpoints=*/ !clk_domain_specified);
|
||||||
sta.all_paths = all_paths;
|
sta.all_paths = all_paths;
|
||||||
sta.select = select;
|
sta.select = select;
|
||||||
sta.run();
|
sta.run();
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,21 @@ std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
|
||||||
return basicType;
|
return basicType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to read an IdString as a numbered connection name ("$123" or similar),
|
||||||
|
// writing the result to dst. If the string isn't of the right format, ignore
|
||||||
|
// dst and return false.
|
||||||
|
bool read_id_num(RTLIL::IdString str, int *dst)
|
||||||
|
{
|
||||||
|
log_assert(dst);
|
||||||
|
|
||||||
|
const char *c_str = str.c_str();
|
||||||
|
if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*dst = atoi(c_str + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// A helper struct for expanding a module's interface connections in expand_module
|
// A helper struct for expanding a module's interface connections in expand_module
|
||||||
struct IFExpander
|
struct IFExpander
|
||||||
{
|
{
|
||||||
|
|
@ -283,15 +298,42 @@ struct IFExpander
|
||||||
RTLIL::IdString conn_name,
|
RTLIL::IdString conn_name,
|
||||||
const RTLIL::SigSpec &conn_signals)
|
const RTLIL::SigSpec &conn_signals)
|
||||||
{
|
{
|
||||||
// Check if the connection is present as an interface in the sub-module's port list
|
// Does the connection look like an interface
|
||||||
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
if (
|
||||||
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
conn_signals.size() != 1 ||
|
||||||
|
conn_signals[0].wire == nullptr ||
|
||||||
|
conn_signals[0].wire->get_bool_attribute(ID::is_interface) == false ||
|
||||||
|
conn_signals[0].wire->name.str().find("$dummywireforinterface") != 0
|
||||||
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Check if the connection is present as an interface in the sub-module's port list
|
||||||
|
int id;
|
||||||
|
if (read_id_num(conn_name, &id)) {
|
||||||
|
/* Interface expansion is incompatible with positional arguments
|
||||||
|
* during expansion, the port list gets each interface signal
|
||||||
|
* inserted after the interface itself which means that the argument
|
||||||
|
* positions in the parent module no longer match.
|
||||||
|
*
|
||||||
|
* Supporting this would require expanding the interfaces in the
|
||||||
|
* parent module, renumbering the arguments to match, and then
|
||||||
|
* iterating over the ports list to find the matching interface
|
||||||
|
* (refactoring on_interface to accept different conn_names on the
|
||||||
|
* parent and child).
|
||||||
|
*/
|
||||||
|
log_error("Unable to connect `%s' to submodule `%s' with positional interface argument `%s'!\n",
|
||||||
|
module.name,
|
||||||
|
submodule.name,
|
||||||
|
conn_signals[0].wire->name.str().substr(23)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Lookup connection by name
|
||||||
|
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
||||||
|
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If the connection looks like an interface, handle it.
|
// If the connection looks like an interface, handle it.
|
||||||
const auto &bits = conn_signals;
|
on_interface(submodule, conn_name, conn_signals);
|
||||||
if (bits.size() == 1 && bits[0].wire->get_bool_attribute(ID::is_interface))
|
|
||||||
on_interface(submodule, conn_name, conn_signals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the connections in a cell, tracking any interface
|
// Iterate over the connections in a cell, tracking any interface
|
||||||
|
|
@ -376,21 +418,6 @@ RTLIL::Module *get_module(RTLIL::Design &design,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to read an IdString as a numbered connection name ("$123" or similar),
|
|
||||||
// writing the result to dst. If the string isn't of the right format, ignore
|
|
||||||
// dst and return false.
|
|
||||||
bool read_id_num(RTLIL::IdString str, int *dst)
|
|
||||||
{
|
|
||||||
log_assert(dst);
|
|
||||||
|
|
||||||
const char *c_str = str.c_str();
|
|
||||||
if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*dst = atoi(c_str + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the connections on the cell match those that are defined
|
// Check that the connections on the cell match those that are defined
|
||||||
// on the type: each named connection should match the name of a port
|
// on the type: each named connection should match the name of a port
|
||||||
// and each positional connection should have an index smaller than
|
// and each positional connection should have an index smaller than
|
||||||
|
|
|
||||||
|
|
@ -117,15 +117,6 @@ struct gate_t
|
||||||
std::string bit_str;
|
std::string bit_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool map_mux4;
|
|
||||||
bool map_mux8;
|
|
||||||
bool map_mux16;
|
|
||||||
|
|
||||||
bool markgroups;
|
|
||||||
|
|
||||||
pool<std::string> enabled_gates;
|
|
||||||
bool cmos_cost;
|
|
||||||
|
|
||||||
struct AbcConfig
|
struct AbcConfig
|
||||||
{
|
{
|
||||||
std::string global_tempdir_name;
|
std::string global_tempdir_name;
|
||||||
|
|
@ -146,6 +137,12 @@ struct AbcConfig
|
||||||
bool show_tempdir = false;
|
bool show_tempdir = false;
|
||||||
bool sop_mode = false;
|
bool sop_mode = false;
|
||||||
bool abc_dress = false;
|
bool abc_dress = false;
|
||||||
|
bool map_mux4 = false;
|
||||||
|
bool map_mux8 = false;
|
||||||
|
bool map_mux16 = false;
|
||||||
|
bool markgroups = false;
|
||||||
|
pool<std::string> enabled_gates;
|
||||||
|
bool cmos_cost = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AbcSigVal {
|
struct AbcSigVal {
|
||||||
|
|
@ -1382,7 +1379,7 @@ void emit_global_input_files(const AbcConfig &config)
|
||||||
fprintf(f, "%d %d.00 1.00\n", i+1, config.lut_costs.at(i));
|
fprintf(f, "%d %d.00 1.00\n", i+1, config.lut_costs.at(i));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
} else {
|
} else {
|
||||||
auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
|
auto &cell_cost = config.cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost();
|
||||||
|
|
||||||
std::string buffer = stringf("%s/stdcells.genlib", config.global_tempdir_name.c_str());
|
std::string buffer = stringf("%s/stdcells.genlib", config.global_tempdir_name.c_str());
|
||||||
FILE *f = fopen(buffer.c_str(), "wt");
|
FILE *f = fopen(buffer.c_str(), "wt");
|
||||||
|
|
@ -1392,39 +1389,39 @@ void emit_global_input_files(const AbcConfig &config)
|
||||||
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
|
fprintf(f, "GATE ONE 1 Y=CONST1;\n");
|
||||||
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_BUF_)));
|
fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_BUF_)));
|
||||||
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOT_)));
|
fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOT_)));
|
||||||
if (enabled_gates.count("AND"))
|
if (config.enabled_gates.count("AND"))
|
||||||
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_AND_)));
|
fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_AND_)));
|
||||||
if (enabled_gates.count("NAND"))
|
if (config.enabled_gates.count("NAND"))
|
||||||
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NAND_)));
|
fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NAND_)));
|
||||||
if (enabled_gates.count("OR"))
|
if (config.enabled_gates.count("OR"))
|
||||||
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_OR_)));
|
fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at(ID($_OR_)));
|
||||||
if (enabled_gates.count("NOR"))
|
if (config.enabled_gates.count("NOR"))
|
||||||
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOR_)));
|
fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_NOR_)));
|
||||||
if (enabled_gates.count("XOR"))
|
if (config.enabled_gates.count("XOR"))
|
||||||
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XOR_)));
|
fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XOR_)));
|
||||||
if (enabled_gates.count("XNOR"))
|
if (config.enabled_gates.count("XNOR"))
|
||||||
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XNOR_)));
|
fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_XNOR_)));
|
||||||
if (enabled_gates.count("ANDNOT"))
|
if (config.enabled_gates.count("ANDNOT"))
|
||||||
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ANDNOT_)));
|
fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ANDNOT_)));
|
||||||
if (enabled_gates.count("ORNOT"))
|
if (config.enabled_gates.count("ORNOT"))
|
||||||
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ORNOT_)));
|
fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_ORNOT_)));
|
||||||
if (enabled_gates.count("AOI3"))
|
if (config.enabled_gates.count("AOI3"))
|
||||||
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI3_)));
|
fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI3_)));
|
||||||
if (enabled_gates.count("OAI3"))
|
if (config.enabled_gates.count("OAI3"))
|
||||||
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI3_)));
|
fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI3_)));
|
||||||
if (enabled_gates.count("AOI4"))
|
if (config.enabled_gates.count("AOI4"))
|
||||||
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI4_)));
|
fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_AOI4_)));
|
||||||
if (enabled_gates.count("OAI4"))
|
if (config.enabled_gates.count("OAI4"))
|
||||||
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI4_)));
|
fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at(ID($_OAI4_)));
|
||||||
if (enabled_gates.count("MUX"))
|
if (config.enabled_gates.count("MUX"))
|
||||||
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_MUX_)));
|
fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_MUX_)));
|
||||||
if (enabled_gates.count("NMUX"))
|
if (config.enabled_gates.count("NMUX"))
|
||||||
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_NMUX_)));
|
fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at(ID($_NMUX_)));
|
||||||
if (map_mux4)
|
if (config.map_mux4)
|
||||||
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at(ID($_MUX_)));
|
fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at(ID($_MUX_)));
|
||||||
if (map_mux8)
|
if (config.map_mux8)
|
||||||
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at(ID($_MUX_)));
|
fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at(ID($_MUX_)));
|
||||||
if (map_mux16)
|
if (config.map_mux16)
|
||||||
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at(ID($_MUX_)));
|
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at(ID($_MUX_)));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
@ -1456,6 +1453,7 @@ void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL
|
||||||
RTLIL::Module *mapped_mod = mapped_design->module(ID(netlist));
|
RTLIL::Module *mapped_mod = mapped_design->module(ID(netlist));
|
||||||
if (mapped_mod == nullptr)
|
if (mapped_mod == nullptr)
|
||||||
log_error("ABC output file does not contain a module `netlist'.\n");
|
log_error("ABC output file does not contain a module `netlist'.\n");
|
||||||
|
bool markgroups = run_abc.config.markgroups;
|
||||||
for (auto w : mapped_mod->wires()) {
|
for (auto w : mapped_mod->wires()) {
|
||||||
RTLIL::Wire *orig_wire = nullptr;
|
RTLIL::Wire *orig_wire = nullptr;
|
||||||
RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire));
|
RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire));
|
||||||
|
|
@ -1998,9 +1996,9 @@ struct AbcPass : public Pass {
|
||||||
lut_arg = design->scratchpad_get_string("abc.lut", lut_arg);
|
lut_arg = design->scratchpad_get_string("abc.lut", lut_arg);
|
||||||
luts_arg = design->scratchpad_get_string("abc.luts", luts_arg);
|
luts_arg = design->scratchpad_get_string("abc.luts", luts_arg);
|
||||||
config.sop_mode = design->scratchpad_get_bool("abc.sop", false);
|
config.sop_mode = design->scratchpad_get_bool("abc.sop", false);
|
||||||
map_mux4 = design->scratchpad_get_bool("abc.mux4", map_mux4);
|
config.map_mux4 = design->scratchpad_get_bool("abc.mux4", false);
|
||||||
map_mux8 = design->scratchpad_get_bool("abc.mux8", map_mux8);
|
config.map_mux8 = design->scratchpad_get_bool("abc.mux8", false);
|
||||||
map_mux16 = design->scratchpad_get_bool("abc.mux16", map_mux16);
|
config.map_mux16 = design->scratchpad_get_bool("abc.mux16", false);
|
||||||
config.abc_dress = design->scratchpad_get_bool("abc.dress", false);
|
config.abc_dress = design->scratchpad_get_bool("abc.dress", false);
|
||||||
g_arg = design->scratchpad_get_string("abc.g", g_arg);
|
g_arg = design->scratchpad_get_string("abc.g", g_arg);
|
||||||
|
|
||||||
|
|
@ -2014,7 +2012,7 @@ struct AbcPass : public Pass {
|
||||||
config.keepff = design->scratchpad_get_bool("abc.keepff", false);
|
config.keepff = design->scratchpad_get_bool("abc.keepff", false);
|
||||||
config.cleanup = !design->scratchpad_get_bool("abc.nocleanup", false);
|
config.cleanup = !design->scratchpad_get_bool("abc.nocleanup", false);
|
||||||
config.show_tempdir = design->scratchpad_get_bool("abc.showtmp", false);
|
config.show_tempdir = design->scratchpad_get_bool("abc.showtmp", false);
|
||||||
markgroups = design->scratchpad_get_bool("abc.markgroups", markgroups);
|
config.markgroups = design->scratchpad_get_bool("abc.markgroups", false);
|
||||||
|
|
||||||
if (config.cleanup)
|
if (config.cleanup)
|
||||||
config.global_tempdir_name = get_base_tmpdir() + "/";
|
config.global_tempdir_name = get_base_tmpdir() + "/";
|
||||||
|
|
@ -2094,15 +2092,15 @@ struct AbcPass : public Pass {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-mux4") {
|
if (arg == "-mux4") {
|
||||||
map_mux4 = true;
|
config.map_mux4 = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-mux8") {
|
if (arg == "-mux8") {
|
||||||
map_mux8 = true;
|
config.map_mux8 = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-mux16") {
|
if (arg == "-mux16") {
|
||||||
map_mux16 = true;
|
config.map_mux16 = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-dress") {
|
if (arg == "-dress") {
|
||||||
|
|
@ -2143,7 +2141,7 @@ struct AbcPass : public Pass {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-markgroups") {
|
if (arg == "-markgroups") {
|
||||||
markgroups = true;
|
config.markgroups = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -2236,14 +2234,14 @@ struct AbcPass : public Pass {
|
||||||
}
|
}
|
||||||
if (g == "cmos2") {
|
if (g == "cmos2") {
|
||||||
if (!remove_gates)
|
if (!remove_gates)
|
||||||
cmos_cost = true;
|
config.cmos_cost = true;
|
||||||
gate_list.push_back("NAND");
|
gate_list.push_back("NAND");
|
||||||
gate_list.push_back("NOR");
|
gate_list.push_back("NOR");
|
||||||
goto ok_alias;
|
goto ok_alias;
|
||||||
}
|
}
|
||||||
if (g == "cmos3") {
|
if (g == "cmos3") {
|
||||||
if (!remove_gates)
|
if (!remove_gates)
|
||||||
cmos_cost = true;
|
config.cmos_cost = true;
|
||||||
gate_list.push_back("NAND");
|
gate_list.push_back("NAND");
|
||||||
gate_list.push_back("NOR");
|
gate_list.push_back("NOR");
|
||||||
gate_list.push_back("AOI3");
|
gate_list.push_back("AOI3");
|
||||||
|
|
@ -2252,7 +2250,7 @@ struct AbcPass : public Pass {
|
||||||
}
|
}
|
||||||
if (g == "cmos4") {
|
if (g == "cmos4") {
|
||||||
if (!remove_gates)
|
if (!remove_gates)
|
||||||
cmos_cost = true;
|
config.cmos_cost = true;
|
||||||
gate_list.push_back("NAND");
|
gate_list.push_back("NAND");
|
||||||
gate_list.push_back("NOR");
|
gate_list.push_back("NOR");
|
||||||
gate_list.push_back("AOI3");
|
gate_list.push_back("AOI3");
|
||||||
|
|
@ -2263,7 +2261,7 @@ struct AbcPass : public Pass {
|
||||||
}
|
}
|
||||||
if (g == "cmos") {
|
if (g == "cmos") {
|
||||||
if (!remove_gates)
|
if (!remove_gates)
|
||||||
cmos_cost = true;
|
config.cmos_cost = true;
|
||||||
gate_list.push_back("NAND");
|
gate_list.push_back("NAND");
|
||||||
gate_list.push_back("NOR");
|
gate_list.push_back("NOR");
|
||||||
gate_list.push_back("AOI3");
|
gate_list.push_back("AOI3");
|
||||||
|
|
@ -2322,9 +2320,9 @@ struct AbcPass : public Pass {
|
||||||
ok_alias:
|
ok_alias:
|
||||||
for (auto gate : gate_list) {
|
for (auto gate : gate_list) {
|
||||||
if (remove_gates)
|
if (remove_gates)
|
||||||
enabled_gates.erase(gate);
|
config.enabled_gates.erase(gate);
|
||||||
else
|
else
|
||||||
enabled_gates.insert(gate);
|
config.enabled_gates.insert(gate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2334,21 +2332,21 @@ struct AbcPass : public Pass {
|
||||||
if (!config.constr_file.empty() && (config.liberty_files.empty() && config.genlib_files.empty()))
|
if (!config.constr_file.empty() && (config.liberty_files.empty() && config.genlib_files.empty()))
|
||||||
log_cmd_error("Got -constr but no -liberty/-genlib!\n");
|
log_cmd_error("Got -constr but no -liberty/-genlib!\n");
|
||||||
|
|
||||||
if (enabled_gates.empty()) {
|
if (config.enabled_gates.empty()) {
|
||||||
enabled_gates.insert("AND");
|
config.enabled_gates.insert("AND");
|
||||||
enabled_gates.insert("NAND");
|
config.enabled_gates.insert("NAND");
|
||||||
enabled_gates.insert("OR");
|
config.enabled_gates.insert("OR");
|
||||||
enabled_gates.insert("NOR");
|
config.enabled_gates.insert("NOR");
|
||||||
enabled_gates.insert("XOR");
|
config.enabled_gates.insert("XOR");
|
||||||
enabled_gates.insert("XNOR");
|
config.enabled_gates.insert("XNOR");
|
||||||
enabled_gates.insert("ANDNOT");
|
config.enabled_gates.insert("ANDNOT");
|
||||||
enabled_gates.insert("ORNOT");
|
config.enabled_gates.insert("ORNOT");
|
||||||
// enabled_gates.insert("AOI3");
|
// config.enabled_gates.insert("AOI3");
|
||||||
// enabled_gates.insert("OAI3");
|
// config.enabled_gates.insert("OAI3");
|
||||||
// enabled_gates.insert("AOI4");
|
// config.enabled_gates.insert("AOI4");
|
||||||
// enabled_gates.insert("OAI4");
|
// config.enabled_gates.insert("OAI4");
|
||||||
enabled_gates.insert("MUX");
|
config.enabled_gates.insert("MUX");
|
||||||
// enabled_gates.insert("NMUX");
|
// config.enabled_gates.insert("NMUX");
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_global_input_files(config);
|
emit_global_input_files(config);
|
||||||
|
|
|
||||||
|
|
@ -1428,13 +1428,13 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
|
||||||
// Copy connections (and rename) from mapped_mod to module
|
// Copy connections (and rename) from mapped_mod to module
|
||||||
for (auto conn : mapped_mod->connections()) {
|
for (auto conn : mapped_mod->connections()) {
|
||||||
if (!conn.first.is_fully_const()) {
|
if (!conn.first.is_fully_const()) {
|
||||||
auto chunks = conn.first.chunks();
|
std::vector<RTLIL::SigChunk> chunks = conn.first.chunks();
|
||||||
for (auto &c : chunks)
|
for (auto &c : chunks)
|
||||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
c.wire = module->wires_.at(remap_name(c.wire->name));
|
||||||
conn.first = std::move(chunks);
|
conn.first = std::move(chunks);
|
||||||
}
|
}
|
||||||
if (!conn.second.is_fully_const()) {
|
if (!conn.second.is_fully_const()) {
|
||||||
auto chunks = conn.second.chunks();
|
std::vector<RTLIL::SigChunk> chunks = conn.second.chunks();
|
||||||
for (auto &c : chunks)
|
for (auto &c : chunks)
|
||||||
if (c.wire)
|
if (c.wire)
|
||||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
c.wire = module->wires_.at(remap_name(c.wire->name));
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pin_names = pool<std::string>{};
|
auto pin_names = std::unordered_set<std::string>{};
|
||||||
tree.get_pin_names(pin_names);
|
tree.get_pin_names(pin_names);
|
||||||
|
|
||||||
// from the `ff` block, we know the flop output signal name for loopback.
|
// from the `ff` block, we know the flop output signal name for loopback.
|
||||||
|
|
@ -156,7 +156,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std
|
||||||
auto pins = std::vector<std::string>(pin_names.begin(), pin_names.end());
|
auto pins = std::vector<std::string>(pin_names.begin(), pin_names.end());
|
||||||
int lut = 0;
|
int lut = 0;
|
||||||
for (int n = 0; n < 8; n++) {
|
for (int n = 0; n < 8; n++) {
|
||||||
auto values = dict<std::string, bool>{};
|
auto values = std::unordered_map<std::string, bool>{};
|
||||||
values.insert(std::make_pair(pins[0], (n & 1) == 1));
|
values.insert(std::make_pair(pins[0], (n & 1) == 1));
|
||||||
values.insert(std::make_pair(pins[1], (n & 2) == 2));
|
values.insert(std::make_pair(pins[1], (n & 2) == 2));
|
||||||
values.insert(std::make_pair(ff_output, (n & 4) == 4));
|
values.insert(std::make_pair(ff_output, (n & 4) == 4));
|
||||||
|
|
@ -271,6 +271,13 @@ static void find_cell(std::vector<const LibertyAst *> cells, IdString cell_type,
|
||||||
continue;
|
continue;
|
||||||
if (!parse_next_state(cell, ff->find("next_state"), cell_next_pin, cell_next_pol, cell_enable_pin, cell_enable_pol) || (has_enable && (cell_enable_pin.empty() || cell_enable_pol != enapol)))
|
if (!parse_next_state(cell, ff->find("next_state"), cell_next_pin, cell_next_pol, cell_enable_pin, cell_enable_pol) || (has_enable && (cell_enable_pin.empty() || cell_enable_pol != enapol)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (has_reset && !cell_next_pol) {
|
||||||
|
// next_state is negated
|
||||||
|
// we later propagate this inversion to the output,
|
||||||
|
// which requires the negation of the reset value
|
||||||
|
rstval = !rstval;
|
||||||
|
}
|
||||||
if (has_reset && rstval == false) {
|
if (has_reset && rstval == false) {
|
||||||
if (!parse_pin(cell, ff->find("clear"), cell_rst_pin, cell_rst_pol) || cell_rst_pol != rstpol)
|
if (!parse_pin(cell, ff->find("clear"), cell_rst_pin, cell_rst_pol) || cell_rst_pol != rstpol)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,22 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifndef FILTERLIB
|
#ifdef FILTERLIB
|
||||||
|
#undef log_assert
|
||||||
|
void log_assert(bool cond) {
|
||||||
|
if (!cond)
|
||||||
|
fprintf(stderr, "Unspecified assertion failed\n");
|
||||||
|
}
|
||||||
|
void warn(std::string str) {
|
||||||
|
std::cerr << str;
|
||||||
|
}
|
||||||
|
#else
|
||||||
#include "kernel/log.h"
|
#include "kernel/log.h"
|
||||||
|
void warn(std::string str) {
|
||||||
|
Yosys::log_formatted_warning("", str);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Yosys;
|
using namespace Yosys;
|
||||||
|
|
@ -110,7 +123,9 @@ int LibertyInputStream::peek_cold(size_t offset)
|
||||||
if (!extend_buffer_at_least(offset + 1))
|
if (!extend_buffer_at_least(offset + 1))
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
#ifdef log_assert
|
||||||
|
log_assert(buf_pos + offset < buffer.size());
|
||||||
|
#endif
|
||||||
return buffer[buf_pos + offset];
|
return buffer[buf_pos + offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,13 +177,15 @@ void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string i
|
||||||
fprintf(f, " ;\n");
|
fprintf(f, " ;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FILTERLIB
|
|
||||||
|
|
||||||
// binary operators excluding ' '
|
// binary operators excluding ' '
|
||||||
bool LibertyExpression::is_nice_binop(char c) {
|
bool LibertyExpression::char_is_nice_binop(char c) {
|
||||||
return c == '*' || c == '&' || c == '^' || c == '+' || c == '|';
|
return c == '*' || c == '&' || c == '^' || c == '+' || c == '|';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LibertyExpression::is_binop() {
|
||||||
|
return kind == AND || kind == OR || kind == XOR;
|
||||||
|
}
|
||||||
|
|
||||||
// https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
|
// https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html
|
||||||
LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
|
|
@ -177,7 +194,7 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||||
char c = s.peek();
|
char c = s.peek();
|
||||||
auto lhs = LibertyExpression{};
|
auto lhs = LibertyExpression{};
|
||||||
|
|
||||||
while (isspace(c)) {
|
while (isspace(c) || c == '"') {
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
return lhs;
|
return lhs;
|
||||||
s.next();
|
s.next();
|
||||||
|
|
@ -191,7 +208,9 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||||
s.next();
|
s.next();
|
||||||
lhs = parse(s);
|
lhs = parse(s);
|
||||||
if (s.peek() != ')') {
|
if (s.peek() != ')') {
|
||||||
log_warning("expected ')' instead of '%c' while parsing Liberty expression '%s'\n", s.peek(), s.full_expr());
|
std::stringstream ss;
|
||||||
|
ss << "expected ')' instead of " << s.peek() << " while parsing Liberty expression '" << s.full_expr() << "'\n";
|
||||||
|
warn(ss.str());
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
s.next();
|
s.next();
|
||||||
|
|
@ -200,10 +219,11 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||||
lhs.kind = Kind::NOT;
|
lhs.kind = Kind::NOT;
|
||||||
lhs.children.push_back(parse(s, 7));
|
lhs.children.push_back(parse(s, 7));
|
||||||
} else {
|
} else {
|
||||||
log_warning("unrecognised character '%c' while parsing Liberty expression '%s'\n", c, s.full_expr());
|
std::stringstream ss;
|
||||||
|
ss << "unrecognised character " << c << " while parsing Liberty expression " << s.full_expr() << "\n";
|
||||||
|
warn(ss.str());
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
break;
|
break;
|
||||||
|
|
@ -246,9 +266,10 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||||
s.next();
|
s.next();
|
||||||
c = s.peek();
|
c = s.peek();
|
||||||
}
|
}
|
||||||
if (is_nice_binop(c)) {
|
if (char_is_nice_binop(c) || c == ')' || c == '\'' || c == '\"') {
|
||||||
// We found a real binop, so this space wasn't an AND
|
// We found a real binop, so this space wasn't an AND
|
||||||
// and we just discard it as meaningless whitespace
|
// and we just discard it as meaningless whitespace
|
||||||
|
// Tail operators also imply this isn't an AND
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -286,7 +307,7 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibertyExpression::get_pin_names(pool<std::string>& names) {
|
void LibertyExpression::get_pin_names(std::unordered_set<std::string>& names) {
|
||||||
if (kind == Kind::PIN) {
|
if (kind == Kind::PIN) {
|
||||||
names.insert(name);
|
names.insert(name);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -295,7 +316,7 @@ void LibertyExpression::get_pin_names(pool<std::string>& names) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibertyExpression::eval(dict<std::string, bool>& values) {
|
bool LibertyExpression::eval(std::unordered_map<std::string, bool>& values) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind::AND:
|
case Kind::AND:
|
||||||
|
|
@ -324,7 +345,7 @@ bool LibertyExpression::eval(dict<std::string, bool>& values) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LibertyExpression::str(int indent)
|
std::string LibertyExpression::sexpr_str(int indent)
|
||||||
{
|
{
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|
@ -355,16 +376,55 @@ std::string LibertyExpression::str(int indent)
|
||||||
if (!first) {
|
if (!first) {
|
||||||
prefix += "\n" + std::string(indent + add_indent, ' ');
|
prefix += "\n" + std::string(indent + add_indent, ' ');
|
||||||
}
|
}
|
||||||
prefix += child.str(indent + add_indent);
|
prefix += child.sexpr_str(indent + add_indent);
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
prefix += ")";
|
prefix += ")";
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
std::string LibertyExpression::vlog_str()
|
||||||
|
{
|
||||||
|
std::string prefix;
|
||||||
|
if (kind != PIN)
|
||||||
|
prefix += "(";
|
||||||
|
if (is_binop()) {
|
||||||
|
log_assert(children.size() == 2);
|
||||||
|
prefix += children[0].vlog_str();
|
||||||
|
switch (kind) {
|
||||||
|
case AND:
|
||||||
|
prefix += "&";
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
prefix += "|";
|
||||||
|
break;
|
||||||
|
case XOR:
|
||||||
|
prefix += "^";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_assert(false);
|
||||||
|
}
|
||||||
|
prefix += children[1].vlog_str();
|
||||||
|
} else {
|
||||||
|
switch (kind) {
|
||||||
|
case NOT:
|
||||||
|
log_assert(children.size() == 1);
|
||||||
|
prefix += "~";
|
||||||
|
prefix += children[0].vlog_str();
|
||||||
|
break;
|
||||||
|
case PIN:
|
||||||
|
prefix += name;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log_assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kind != PIN)
|
||||||
|
prefix += ")";
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
int LibertyParser::lexer(std::string &str)
|
int LibertyParser::lexer_inner(std::string &str)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
|
@ -390,11 +450,9 @@ int LibertyParser::lexer(std::string &str)
|
||||||
|
|
||||||
if (str == "+" || str == "-") {
|
if (str == "+" || str == "-") {
|
||||||
/* Single operator is not an identifier */
|
/* Single operator is not an identifier */
|
||||||
// fprintf(stderr, "LEX: char >>%s<<\n", str.c_str());
|
|
||||||
return str[0];
|
return str[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// fprintf(stderr, "LEX: identifier >>%s<<\n", str.c_str());
|
|
||||||
return 'v';
|
return 'v';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -406,20 +464,19 @@ int LibertyParser::lexer(std::string &str)
|
||||||
while (true) {
|
while (true) {
|
||||||
c = f.peek(i);
|
c = f.peek(i);
|
||||||
line += (c == '\n');
|
line += (c == '\n');
|
||||||
if (c != '"')
|
if (c != '"' && c != EOF)
|
||||||
i += 1;
|
i += 1;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
str.clear();
|
str.clear();
|
||||||
#ifdef FILTERLIB
|
|
||||||
f.unget();
|
|
||||||
str.append(f.buffered_data(), f.buffered_data() + i + 2);
|
|
||||||
f.consume(i + 2);
|
|
||||||
#else
|
|
||||||
str.append(f.buffered_data(), f.buffered_data() + i);
|
str.append(f.buffered_data(), f.buffered_data() + i);
|
||||||
f.consume(i + 1);
|
// Usage in filterlib is expected to retain quotes
|
||||||
|
// but yosys expects to get unquoted
|
||||||
|
#ifdef FILTERLIB
|
||||||
|
str = "\"" + str + "\"";
|
||||||
#endif
|
#endif
|
||||||
|
f.consume(i + 1);
|
||||||
return 'v';
|
return 'v';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -442,13 +499,12 @@ int LibertyParser::lexer(std::string &str)
|
||||||
return lexer(str);
|
return lexer(str);
|
||||||
}
|
}
|
||||||
f.unget();
|
f.unget();
|
||||||
// fprintf(stderr, "LEX: char >>/<<\n");
|
|
||||||
return '/'; // a single '/' charater.
|
return '/'; // a single '/' charater.
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for a backslash
|
// check for a backslash
|
||||||
if (c == '\\') {
|
if (c == '\\') {
|
||||||
c = f.get();
|
c = f.get();
|
||||||
if (c == '\r')
|
if (c == '\r')
|
||||||
c = f.get();
|
c = f.get();
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
|
|
@ -467,14 +523,22 @@ int LibertyParser::lexer(std::string &str)
|
||||||
|
|
||||||
// anything else, such as ';' will get passed
|
// anything else, such as ';' will get passed
|
||||||
// through as literal items.
|
// through as literal items.
|
||||||
|
|
||||||
// if (c >= 32 && c < 255)
|
|
||||||
// fprintf(stderr, "LEX: char >>%c<<\n", c);
|
|
||||||
// else
|
|
||||||
// fprintf(stderr, "LEX: char %d\n", c);
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LibertyParser::lexer(std::string &str)
|
||||||
|
{
|
||||||
|
int ret = lexer_inner(str);
|
||||||
|
// if (ret >= 32 && ret < 255) {
|
||||||
|
// fprintf(stdout, "LEX: ret >>%c<<\n", ret);
|
||||||
|
// } else if (ret == 'v') {
|
||||||
|
// fprintf(stdout, "LEX: ret v str %s\n", str.c_str());
|
||||||
|
// } else {
|
||||||
|
// fprintf(stdout, "LEX: ret %d\n", ret);
|
||||||
|
// }
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void LibertyParser::report_unexpected_token(int tok)
|
void LibertyParser::report_unexpected_token(int tok)
|
||||||
{
|
{
|
||||||
std::string eReport;
|
std::string eReport;
|
||||||
|
|
@ -545,6 +609,25 @@ void LibertyParser::parse_vector_range(int tok)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Consume into out_str any string-ish tokens, seperated with spaces
|
||||||
|
// to cope with abuse of the underdefined spec by real world PDKs
|
||||||
|
// enabled by proprietary implementations.
|
||||||
|
// Sorry.
|
||||||
|
int LibertyParser::consume_wrecked_str(int tok, std::string& out_str) {
|
||||||
|
std::string str = "";
|
||||||
|
while (tok != ';' && tok != EOF && tok != 'n') {
|
||||||
|
out_str += " ";
|
||||||
|
if (tok == 'v')
|
||||||
|
out_str += str;
|
||||||
|
else
|
||||||
|
out_str += tok;
|
||||||
|
tok = lexer(str);
|
||||||
|
}
|
||||||
|
if (tok == EOF)
|
||||||
|
error("wrecked string EOF");
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
LibertyAst *LibertyParser::parse(bool top_level)
|
LibertyAst *LibertyParser::parse(bool top_level)
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
@ -591,7 +674,14 @@ LibertyAst *LibertyParser::parse(bool top_level)
|
||||||
if (tok == '[') {
|
if (tok == '[') {
|
||||||
parse_vector_range(tok);
|
parse_vector_range(tok);
|
||||||
tok = lexer(str);
|
tok = lexer(str);
|
||||||
|
} else {
|
||||||
|
// Hack for when an expression string is unquoted
|
||||||
|
tok = consume_wrecked_str(tok, ast->value);
|
||||||
}
|
}
|
||||||
|
} else if (tok == '(') {
|
||||||
|
// Hack for when an expression string is unquoted and starts with
|
||||||
|
// parentheses
|
||||||
|
tok = consume_wrecked_str(tok, ast->value);
|
||||||
}
|
}
|
||||||
while (tok == '+' || tok == '-' || tok == '*' || tok == '/' || tok == '!') {
|
while (tok == '+' || tok == '-' || tok == '*' || tok == '/' || tok == '!') {
|
||||||
ast->value += tok;
|
ast->value += tok;
|
||||||
|
|
@ -601,7 +691,7 @@ LibertyAst *LibertyParser::parse(bool top_level)
|
||||||
ast->value += str;
|
ast->value += str;
|
||||||
tok = lexer(str);
|
tok = lexer(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In a liberty file, all key : value pairs should end in ';'
|
// In a liberty file, all key : value pairs should end in ';'
|
||||||
// However, there are some liberty files in the wild that
|
// However, there are some liberty files in the wild that
|
||||||
// just have a newline. We'll be kind and accept a newline
|
// just have a newline. We'll be kind and accept a newline
|
||||||
|
|
@ -621,11 +711,11 @@ LibertyAst *LibertyParser::parse(bool top_level)
|
||||||
continue;
|
continue;
|
||||||
if (tok == ')')
|
if (tok == ')')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (tok == '[')
|
if (tok == '[')
|
||||||
{
|
{
|
||||||
parse_vector_range(tok);
|
parse_vector_range(tok);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (tok == 'n')
|
if (tok == 'n')
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -727,42 +817,13 @@ const LibertyAst *find_non_null(const LibertyAst *node, const char *name)
|
||||||
|
|
||||||
std::string func2vl(std::string str)
|
std::string func2vl(std::string str)
|
||||||
{
|
{
|
||||||
for (size_t pos = str.find_first_of("\" \t"); pos != std::string::npos; pos = str.find_first_of("\" \t")) {
|
auto helper = LibertyExpression::Lexer(str);
|
||||||
char c_left = pos > 0 ? str[pos-1] : ' ';
|
return LibertyExpression::parse(helper).vlog_str();
|
||||||
char c_right = pos+1 < str.size() ? str[pos+1] : ' ';
|
}
|
||||||
if (std::string("\" \t*+").find(c_left) != std::string::npos)
|
|
||||||
str.erase(pos, 1);
|
|
||||||
else if (std::string("\" \t*+").find(c_right) != std::string::npos)
|
|
||||||
str.erase(pos, 1);
|
|
||||||
else
|
|
||||||
str[pos] = '*';
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<size_t> group_start;
|
|
||||||
for (size_t pos = 0; pos < str.size(); pos++) {
|
|
||||||
if (str[pos] == '(')
|
|
||||||
group_start.push_back(pos);
|
|
||||||
if (str[pos] == ')' && group_start.size() > 0) {
|
|
||||||
if (pos+1 < str.size() && str[pos+1] == '\'') {
|
|
||||||
std::string group = str.substr(group_start.back(), pos-group_start.back()+1);
|
|
||||||
str[group_start.back()] = '~';
|
|
||||||
str.replace(group_start.back()+1, group.size(), group);
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
group_start.pop_back();
|
|
||||||
}
|
|
||||||
if (str[pos] == '\'' && pos > 0) {
|
|
||||||
size_t start = str.find_last_of("()'*+^&| ", pos-1)+1;
|
|
||||||
std::string group = str.substr(start, pos-start);
|
|
||||||
str[start] = '~';
|
|
||||||
str.replace(start+1, group.size(), group);
|
|
||||||
}
|
|
||||||
if (str[pos] == '*')
|
|
||||||
str[pos] = '&';
|
|
||||||
if (str[pos] == '+')
|
|
||||||
str[pos] = '|';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string vlog_identifier(std::string str)
|
||||||
|
{
|
||||||
|
str.erase(std::remove(str.begin(), str.end(), '\"'), str.end());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -772,11 +833,13 @@ void event2vl(const LibertyAst *ast, std::string &edge, std::string &expr)
|
||||||
expr.clear();
|
expr.clear();
|
||||||
|
|
||||||
if (ast != NULL) {
|
if (ast != NULL) {
|
||||||
expr = func2vl(ast->value);
|
auto helper = LibertyExpression::Lexer(ast->value);
|
||||||
if (expr.size() > 0 && expr[0] == '~')
|
auto parsed = LibertyExpression::parse(helper);
|
||||||
edge = "negedge " + expr.substr(1);
|
expr = parsed.vlog_str();
|
||||||
|
if (parsed.kind == LibertyExpression::Kind::NOT)
|
||||||
|
edge = "negedge " + parsed.children[0].vlog_str();
|
||||||
else
|
else
|
||||||
edge = "posedge " + expr;
|
edge = "posedge " + parsed.vlog_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -806,13 +869,13 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CHECK_NV(ast->args.size(), == 1);
|
CHECK_NV(ast->args.size(), == 1);
|
||||||
printf("module %s (", ast->args[0].c_str());
|
printf("module %s (", vlog_identifier(ast->args[0]).c_str());
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto child : ast->children) {
|
for (auto child : ast->children) {
|
||||||
if (child->id != "pin")
|
if (child->id != "pin")
|
||||||
continue;
|
continue;
|
||||||
CHECK_NV(child->args.size(), == 1);
|
CHECK_NV(child->args.size(), == 1);
|
||||||
printf("%s%s", first ? "" : ", ", child->args[0].c_str());
|
printf("%s%s", first ? "" : ", ", vlog_identifier(child->args[0]).c_str());
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
printf(");\n");
|
printf(");\n");
|
||||||
|
|
@ -823,7 +886,7 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
||||||
printf(" reg ");
|
printf(" reg ");
|
||||||
first = true;
|
first = true;
|
||||||
for (auto arg : child->args) {
|
for (auto arg : child->args) {
|
||||||
printf("%s%s", first ? "" : ", ", arg.c_str());
|
printf("%s%s", first ? "" : ", ", vlog_identifier(arg).c_str());
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
printf(";\n");
|
printf(";\n");
|
||||||
|
|
@ -835,9 +898,10 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
||||||
CHECK_NV(child->args.size(), == 1);
|
CHECK_NV(child->args.size(), == 1);
|
||||||
const LibertyAst *dir = find_non_null(child, "direction");
|
const LibertyAst *dir = find_non_null(child, "direction");
|
||||||
const LibertyAst *func = child->find("function");
|
const LibertyAst *func = child->find("function");
|
||||||
printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str());
|
std::string var = vlog_identifier(child->args[0]);
|
||||||
|
printf(" %s %s;\n", dir->value.c_str(), var.c_str());
|
||||||
if (func != NULL)
|
if (func != NULL)
|
||||||
printf(" assign %s = %s; // %s\n", child->args[0].c_str(), func2vl(func->value).c_str(), func->value.c_str());
|
printf(" assign %s = %s; // %s\n", var.c_str(), func2vl(func->value).c_str(), func->value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto child : ast->children)
|
for (auto child : ast->children)
|
||||||
|
|
@ -845,8 +909,8 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
||||||
if (child->id != "ff" || child->args.size() != 2)
|
if (child->id != "ff" || child->args.size() != 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string iq_var = child->args[0];
|
std::string iq_var = vlog_identifier(child->args[0]);
|
||||||
std::string iqn_var = child->args[1];
|
std::string iqn_var = vlog_identifier(child->args[1]);
|
||||||
|
|
||||||
std::string clock_edge, clock_expr;
|
std::string clock_edge, clock_expr;
|
||||||
event2vl(child->find("clocked_on"), clock_edge, clock_expr);
|
event2vl(child->find("clocked_on"), clock_edge, clock_expr);
|
||||||
|
|
@ -909,8 +973,8 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
||||||
if (child->id != "latch" || child->args.size() != 2)
|
if (child->id != "latch" || child->args.size() != 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string iq_var = child->args[0];
|
std::string iq_var = vlog_identifier(child->args[0]);
|
||||||
std::string iqn_var = child->args[1];
|
std::string iqn_var = vlog_identifier(child->args[1]);
|
||||||
|
|
||||||
std::string enable_edge, enable_expr;
|
std::string enable_edge, enable_expr;
|
||||||
event2vl(child->find("enable"), enable_edge, enable_expr);
|
event2vl(child->find("enable"), enable_edge, enable_expr);
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ namespace Yosys
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pin() {
|
std::string pin() {
|
||||||
auto length = s.find_first_of("\t()'!^*& +|");
|
auto length = s.find_first_of("\t()'!^*& +|\"");
|
||||||
if (length == std::string::npos) {
|
if (length == std::string::npos) {
|
||||||
// nothing found so use size of s
|
// nothing found so use size of s
|
||||||
length = s.size();
|
length = s.size();
|
||||||
|
|
@ -91,11 +91,13 @@ namespace Yosys
|
||||||
LibertyExpression() : kind(Kind::EMPTY) {}
|
LibertyExpression() : kind(Kind::EMPTY) {}
|
||||||
|
|
||||||
static LibertyExpression parse(Lexer &s, int min_prio = 0);
|
static LibertyExpression parse(Lexer &s, int min_prio = 0);
|
||||||
void get_pin_names(pool<std::string>& names);
|
void get_pin_names(std::unordered_set<std::string>& names);
|
||||||
bool eval(dict<std::string, bool>& values);
|
bool eval(std::unordered_map<std::string, bool>& values);
|
||||||
std::string str(int indent = 0);
|
std::string sexpr_str(int indent = 0);
|
||||||
|
std::string vlog_str();
|
||||||
private:
|
private:
|
||||||
static bool is_nice_binop(char c);
|
static bool char_is_nice_binop(char c);
|
||||||
|
bool is_binop();
|
||||||
};
|
};
|
||||||
|
|
||||||
class LibertyInputStream {
|
class LibertyInputStream {
|
||||||
|
|
@ -170,10 +172,12 @@ namespace Yosys
|
||||||
'n': newline
|
'n': newline
|
||||||
anything else is a single character.
|
anything else is a single character.
|
||||||
*/
|
*/
|
||||||
|
int lexer_inner(std::string &str);
|
||||||
int lexer(std::string &str);
|
int lexer(std::string &str);
|
||||||
|
|
||||||
void report_unexpected_token(int tok);
|
void report_unexpected_token(int tok);
|
||||||
void parse_vector_range(int tok);
|
void parse_vector_range(int tok);
|
||||||
|
int consume_wrecked_str(int tok, std::string& out_str);
|
||||||
LibertyAst *parse(bool top_level);
|
LibertyAst *parse(bool top_level);
|
||||||
void error() const;
|
void error() const;
|
||||||
void error(const std::string &str) const;
|
void error(const std::string &str) const;
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ from cxxheaderparser.types import (
|
||||||
Variable,
|
Variable,
|
||||||
Array,
|
Array,
|
||||||
FundamentalSpecifier,
|
FundamentalSpecifier,
|
||||||
|
FunctionType,
|
||||||
)
|
)
|
||||||
|
|
||||||
__file_dir__ = Path(__file__).absolute().parent
|
__file_dir__ = Path(__file__).absolute().parent
|
||||||
|
|
@ -177,11 +178,11 @@ pyosys_headers = [
|
||||||
denylist=frozenset({"bits", "bitvectorize"}),
|
denylist=frozenset({"bits", "bitvectorize"}),
|
||||||
),
|
),
|
||||||
PyosysClass("AttrObject", denylist=frozenset({"get_blackbox_attribute"})),
|
PyosysClass("AttrObject", denylist=frozenset({"get_blackbox_attribute"})),
|
||||||
PyosysClass("NamedObject", denylist=frozenset({"get_blackbox_attribute"})),
|
PyosysClass("NamedObject"),
|
||||||
PyosysClass("Selection"),
|
PyosysClass("Selection"),
|
||||||
# PyosysClass("Monitor"), # Virtual methods, manually bridged
|
# PyosysClass("Monitor"), # Virtual methods, manually bridged
|
||||||
PyosysClass("CaseRule", denylist=frozenset({"get_blackbox_attribute"})),
|
PyosysClass("CaseRule"),
|
||||||
PyosysClass("SwitchRule", denylist=frozenset({"get_blackbox_attribute"})),
|
PyosysClass("SwitchRule"),
|
||||||
PyosysClass("SyncRule"),
|
PyosysClass("SyncRule"),
|
||||||
PyosysClass(
|
PyosysClass(
|
||||||
"Process",
|
"Process",
|
||||||
|
|
@ -191,7 +192,7 @@ pyosys_headers = [
|
||||||
),
|
),
|
||||||
PyosysClass("SigChunk"),
|
PyosysClass("SigChunk"),
|
||||||
PyosysClass("SigBit", hash_expr="s"),
|
PyosysClass("SigBit", hash_expr="s"),
|
||||||
PyosysClass("SigSpec", hash_expr="s"),
|
PyosysClass("SigSpec", hash_expr="s", denylist={"chunks"}),
|
||||||
PyosysClass(
|
PyosysClass(
|
||||||
"Cell",
|
"Cell",
|
||||||
ref_only=True,
|
ref_only=True,
|
||||||
|
|
@ -219,7 +220,7 @@ pyosys_headers = [
|
||||||
),
|
),
|
||||||
PyosysClass(
|
PyosysClass(
|
||||||
"Design",
|
"Design",
|
||||||
string_expr="s.hashidx_",
|
string_expr="std::to_string(s.hashidx_)",
|
||||||
hash_expr="s",
|
hash_expr="s",
|
||||||
denylist=frozenset({"selected_whole_modules"}), # deprecated
|
denylist=frozenset({"selected_whole_modules"}), # deprecated
|
||||||
),
|
),
|
||||||
|
|
@ -241,13 +242,17 @@ class PyosysType:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_type(Self, type_obj, drop_const=False) -> "PyosysType":
|
def from_type(Self, type_obj, drop_const=False) -> "PyosysType":
|
||||||
const = type_obj.const and not drop_const
|
const = hasattr(type_obj, "const") and type_obj.const and not drop_const
|
||||||
if isinstance(type_obj, Pointer):
|
if isinstance(type_obj, Pointer):
|
||||||
ptr_to = Self.from_type(type_obj.ptr_to)
|
ptr_to = Self.from_type(type_obj.ptr_to)
|
||||||
return Self("ptr", (ptr_to,), const)
|
return Self("ptr", (ptr_to,), const)
|
||||||
elif isinstance(type_obj, Reference):
|
elif isinstance(type_obj, Reference):
|
||||||
ref_to = Self.from_type(type_obj.ref_to)
|
ref_to = Self.from_type(type_obj.ref_to)
|
||||||
return Self("ref", (ref_to,), const)
|
return Self("ref", (ref_to,), const)
|
||||||
|
elif isinstance(type_obj, FunctionType):
|
||||||
|
ret_type = Self.from_type(type_obj.return_type)
|
||||||
|
param_types = (Self.from_type(p.type) for p in type_obj.parameters)
|
||||||
|
return Self("fn", (ret_type, *param_types), False)
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
type_obj, Type
|
type_obj, Type
|
||||||
), f"unexpected c++ type object of type {type(type_obj)}"
|
), f"unexpected c++ type object of type {type(type_obj)}"
|
||||||
|
|
@ -270,6 +275,16 @@ class PyosysType:
|
||||||
if title == "Dict":
|
if title == "Dict":
|
||||||
key, value = self.specialization
|
key, value = self.specialization
|
||||||
return f"{key.generate_identifier()}To{value.generate_identifier()}{title}"
|
return f"{key.generate_identifier()}To{value.generate_identifier()}{title}"
|
||||||
|
elif title == "Fn":
|
||||||
|
identifier = self.specialization[0].generate_identifier()
|
||||||
|
if identifier == "Void":
|
||||||
|
identifier = ""
|
||||||
|
else:
|
||||||
|
identifier += "From"
|
||||||
|
identifier += "And".join(
|
||||||
|
p.generate_identifier() for p in self.specialization[1:]
|
||||||
|
)
|
||||||
|
return identifier
|
||||||
|
|
||||||
return (
|
return (
|
||||||
"".join(spec.generate_identifier() for spec in self.specialization) + title
|
"".join(spec.generate_identifier() for spec in self.specialization) + title
|
||||||
|
|
@ -283,6 +298,9 @@ class PyosysType:
|
||||||
return const_prefix + f"{self.specialization[0].generate_cpp_name()} *"
|
return const_prefix + f"{self.specialization[0].generate_cpp_name()} *"
|
||||||
elif self.base == "ref":
|
elif self.base == "ref":
|
||||||
return const_prefix + f"{self.specialization[0].generate_cpp_name()} &"
|
return const_prefix + f"{self.specialization[0].generate_cpp_name()} &"
|
||||||
|
elif self.base == "fn":
|
||||||
|
param_cpp_names = (s.generate_cpp_name() for s in self.specialization[1:])
|
||||||
|
return f"{self.specialization[0].generate_cpp_name()}({','.join(param_cpp_names)})"
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
const_prefix
|
const_prefix
|
||||||
|
|
@ -301,7 +319,7 @@ class PyosysWrapperGenerator(object):
|
||||||
self.f = wrapper_stream
|
self.f = wrapper_stream
|
||||||
self.f_inc = header_stream
|
self.f_inc = header_stream
|
||||||
self.found_containers: Dict[PyosysType, Any] = {}
|
self.found_containers: Dict[PyosysType, Any] = {}
|
||||||
self.class_registry: Dict[str, ClassScope] = {}
|
self.class_registry: Dict[str, Tuple[ClassScope, PyosysClass]] = {}
|
||||||
|
|
||||||
# entry point
|
# entry point
|
||||||
def generate(self):
|
def generate(self):
|
||||||
|
|
@ -380,7 +398,7 @@ class PyosysWrapperGenerator(object):
|
||||||
if isinstance(type_info, Reference):
|
if isinstance(type_info, Reference):
|
||||||
return PyosysWrapperGenerator.find_containers(containers, type_info.ref_to)
|
return PyosysWrapperGenerator.find_containers(containers, type_info.ref_to)
|
||||||
if not isinstance(type_info, Type):
|
if not isinstance(type_info, Type):
|
||||||
return ()
|
return {}
|
||||||
segments = type_info.typename.segments
|
segments = type_info.typename.segments
|
||||||
containers_found = {}
|
containers_found = {}
|
||||||
for segment in segments:
|
for segment in segments:
|
||||||
|
|
@ -411,19 +429,23 @@ class PyosysWrapperGenerator(object):
|
||||||
def get_parameter_types(function: Function) -> str:
|
def get_parameter_types(function: Function) -> str:
|
||||||
return ", ".join(p.type.format() for p in function.parameters)
|
return ", ".join(p.type.format() for p in function.parameters)
|
||||||
|
|
||||||
def register_containers(self, target: Union[Function, Field, Variable]):
|
def register_containers(self, target: Union[Function, Field, Variable]) -> bool:
|
||||||
supported = ("dict", "idict", "pool", "set", "vector")
|
supported = ("dict", "idict", "pool", "set", "vector")
|
||||||
|
found = False
|
||||||
if isinstance(target, Function):
|
if isinstance(target, Function):
|
||||||
self.found_containers.update(
|
return_type_containers = self.find_containers(supported, target.return_type)
|
||||||
self.find_containers(supported, target.return_type)
|
found = found or len(return_type_containers)
|
||||||
)
|
self.found_containers.update(return_type_containers)
|
||||||
|
|
||||||
for parameter in target.parameters:
|
for parameter in target.parameters:
|
||||||
self.found_containers.update(
|
parameter_containers = self.find_containers(supported, parameter.type)
|
||||||
self.find_containers(supported, parameter.type)
|
found = found or len(parameter_containers)
|
||||||
)
|
self.found_containers.update(parameter_containers)
|
||||||
else:
|
else:
|
||||||
self.found_containers.update(self.find_containers(supported, target.type))
|
variable_containers = self.find_containers(supported, target.type)
|
||||||
|
found = found or len(variable_containers)
|
||||||
|
self.found_containers.update(variable_containers)
|
||||||
|
return found
|
||||||
|
|
||||||
# processors
|
# processors
|
||||||
def get_overload_cast(
|
def get_overload_cast(
|
||||||
|
|
@ -470,9 +492,9 @@ class PyosysWrapperGenerator(object):
|
||||||
|
|
||||||
def_args = [f'"{python_function_basename}"']
|
def_args = [f'"{python_function_basename}"']
|
||||||
def_args.append(self.get_overload_cast(function, class_basename))
|
def_args.append(self.get_overload_cast(function, class_basename))
|
||||||
for parameter in function.parameters:
|
for i, parameter in enumerate(function.parameters):
|
||||||
# ASSUMPTION: there are no unnamed parameters in the yosys codebase
|
name = parameter.name or f"arg{i}"
|
||||||
parameter_arg = f'py::arg("{parameter.name}")'
|
parameter_arg = f'py::arg("{name}")'
|
||||||
if parameter.default is not None:
|
if parameter.default is not None:
|
||||||
parameter_arg += f" = {parameter.default.format()}"
|
parameter_arg += f" = {parameter.default.format()}"
|
||||||
def_args.append(parameter_arg)
|
def_args.append(parameter_arg)
|
||||||
|
|
@ -525,8 +547,12 @@ class PyosysWrapperGenerator(object):
|
||||||
if function.static:
|
if function.static:
|
||||||
definition_fn = "def_static"
|
definition_fn = "def_static"
|
||||||
|
|
||||||
|
definition_args = self.get_definition_args(
|
||||||
|
function, metadata.name, python_name_override
|
||||||
|
)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"\t\t\t.{definition_fn}({', '.join(self.get_definition_args(function, metadata.name, python_name_override))})",
|
f"\t\t\t.{definition_fn}({', '.join(definition_args)})",
|
||||||
file=self.f,
|
file=self.f,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -565,7 +591,7 @@ class PyosysWrapperGenerator(object):
|
||||||
# care
|
# care
|
||||||
return
|
return
|
||||||
|
|
||||||
self.register_containers(field)
|
has_containers = self.register_containers(field)
|
||||||
|
|
||||||
definition_fn = f"def_{'readonly' if field.type.const else 'readwrite'}"
|
definition_fn = f"def_{'readonly' if field.type.const else 'readwrite'}"
|
||||||
if field.static:
|
if field.static:
|
||||||
|
|
@ -573,8 +599,13 @@ class PyosysWrapperGenerator(object):
|
||||||
|
|
||||||
field_python_basename = keyword_aliases.get(field.name, field.name)
|
field_python_basename = keyword_aliases.get(field.name, field.name)
|
||||||
|
|
||||||
|
def_args = [
|
||||||
|
f'"{field_python_basename}"',
|
||||||
|
f"&{metadata.name}::{field.name}",
|
||||||
|
]
|
||||||
|
def_args.append("py::return_value_policy::copy")
|
||||||
print(
|
print(
|
||||||
f'\t\t\t.{definition_fn}("{field_python_basename}", &{metadata.name}::{field.name})',
|
f"\t\t\t.{definition_fn}({', '.join(def_args)})",
|
||||||
file=self.f,
|
file=self.f,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -603,16 +634,20 @@ class PyosysWrapperGenerator(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
def process_class_members(
|
def process_class_members(
|
||||||
self, metadata: PyosysClass, cls: ClassScope, basename: str
|
self,
|
||||||
|
metadata: PyosysClass,
|
||||||
|
base_metadata: PyosysClass,
|
||||||
|
cls: ClassScope,
|
||||||
|
basename: str,
|
||||||
):
|
):
|
||||||
for method in cls.methods:
|
for method in cls.methods:
|
||||||
if method.name.segments[-1].name in metadata.denylist:
|
if method.name.segments[-1].name in base_metadata.denylist:
|
||||||
continue
|
continue
|
||||||
self.process_method(metadata, method)
|
self.process_method(metadata, method)
|
||||||
|
|
||||||
visited_anonymous_unions = set()
|
visited_anonymous_unions = set()
|
||||||
for field_ in cls.fields:
|
for field_ in cls.fields:
|
||||||
if field_.name in metadata.denylist:
|
if field_.name in base_metadata.denylist:
|
||||||
continue
|
continue
|
||||||
self.process_field(metadata, field_)
|
self.process_field(metadata, field_)
|
||||||
|
|
||||||
|
|
@ -627,6 +662,16 @@ class PyosysWrapperGenerator(object):
|
||||||
for subfield in subclass.fields:
|
for subfield in subclass.fields:
|
||||||
self.process_field(metadata, subfield)
|
self.process_field(metadata, subfield)
|
||||||
|
|
||||||
|
for base in cls.class_decl.bases:
|
||||||
|
if base.access != "public":
|
||||||
|
continue
|
||||||
|
name = base.typename.segments[-1].format()
|
||||||
|
if processed := self.class_registry.get(name):
|
||||||
|
base_scope, base_metadata = processed
|
||||||
|
self.process_class_members(
|
||||||
|
metadata, base_metadata, base_scope, basename
|
||||||
|
)
|
||||||
|
|
||||||
def process_class(
|
def process_class(
|
||||||
self,
|
self,
|
||||||
metadata: PyosysClass,
|
metadata: PyosysClass,
|
||||||
|
|
@ -638,7 +683,7 @@ class PyosysWrapperGenerator(object):
|
||||||
segment.format() for segment in pqname.segments
|
segment.format() for segment in pqname.segments
|
||||||
]
|
]
|
||||||
basename = full_path.pop()
|
basename = full_path.pop()
|
||||||
self.class_registry[basename] = cls
|
self.class_registry[basename] = (cls, metadata)
|
||||||
|
|
||||||
declaration_namespace = "::".join(full_path)
|
declaration_namespace = "::".join(full_path)
|
||||||
tpl_args = [basename]
|
tpl_args = [basename]
|
||||||
|
|
@ -649,19 +694,17 @@ class PyosysWrapperGenerator(object):
|
||||||
file=self.f,
|
file=self.f,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.process_class_members(metadata, cls, basename)
|
self.process_class_members(metadata, metadata, cls, basename)
|
||||||
for base in cls.class_decl.bases:
|
|
||||||
if base.access != "public":
|
|
||||||
continue
|
|
||||||
name = base.typename.segments[-1].format()
|
|
||||||
if base_scope := self.class_registry.get(name):
|
|
||||||
self.process_class_members(metadata, base_scope, basename)
|
|
||||||
|
|
||||||
if expr := metadata.string_expr:
|
if expr := metadata.string_expr:
|
||||||
print(
|
print(
|
||||||
f'\t\t.def("__str__", [](const {basename} &s) {{ return {expr}; }})',
|
f'\t\t.def("__str__", [](const {basename} &s) {{ return {expr}; }})',
|
||||||
file=self.f,
|
file=self.f,
|
||||||
)
|
)
|
||||||
|
print(
|
||||||
|
f'\t\t.def("__repr__", [](const {basename} &s) {{ std::stringstream ss; ss << "<{basename} " << {expr} << ">"; return ss.str(); }})',
|
||||||
|
file=self.f,
|
||||||
|
)
|
||||||
|
|
||||||
if expr := metadata.hash_expr:
|
if expr := metadata.hash_expr:
|
||||||
print(
|
print(
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,12 @@
|
||||||
// <!-- generated includes -->
|
// <!-- generated includes -->
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
#include <pybind11/native_enum.h>
|
#include <pybind11/native_enum.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
// duplicates for LSPs
|
||||||
|
#include "kernel/register.h"
|
||||||
|
#include "kernel/yosys_common.h"
|
||||||
|
|
||||||
#include "pyosys/hashlib.h"
|
#include "pyosys/hashlib.h"
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
@ -28,7 +34,7 @@ namespace py = pybind11;
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
|
|
||||||
using std::set;
|
using std::set;
|
||||||
using std::regex;
|
using std::function;
|
||||||
using std::ostream;
|
using std::ostream;
|
||||||
using namespace RTLIL;
|
using namespace RTLIL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
requires = [
|
requires = [
|
||||||
"setuptools>=42",
|
"setuptools>=42",
|
||||||
"pybind11>=3,<4",
|
"pybind11>=3,<4",
|
||||||
"cxxheaderparser",
|
"cxxheaderparser"
|
||||||
]
|
]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
|
|
||||||
1
setup.py
1
setup.py
|
|
@ -51,6 +51,7 @@ class libyosys_so_ext(Extension):
|
||||||
"ENABLE_TCL=0",
|
"ENABLE_TCL=0",
|
||||||
"ENABLE_READLINE=0",
|
"ENABLE_READLINE=0",
|
||||||
"ENABLE_EDITLINE=0",
|
"ENABLE_EDITLINE=0",
|
||||||
|
"PYOSYS_USE_UV=0", # + install requires takes its role when building wheels
|
||||||
# Always compile and include ABC in wheel
|
# Always compile and include ABC in wheel
|
||||||
"ABCEXTERNAL=",
|
"ABCEXTERNAL=",
|
||||||
# Show compile commands
|
# Show compile commands
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
OBJS += techlibs/gatemate/synth_gatemate.o
|
OBJS += techlibs/gatemate/synth_gatemate.o
|
||||||
OBJS += techlibs/gatemate/gatemate_foldinv.o
|
OBJS += techlibs/gatemate/gatemate_foldinv.o
|
||||||
|
|
||||||
|
GENFILES += techlibs/gatemate/lut_tree_cells.genlib
|
||||||
|
GENFILES += techlibs/gatemate/lut_tree_map.v
|
||||||
|
|
||||||
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/reg_map.v))
|
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/reg_map.v))
|
||||||
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mux_map.v))
|
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mux_map.v))
|
||||||
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/lut_map.v))
|
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/lut_map.v))
|
||||||
|
|
@ -28,3 +31,4 @@ techlibs/gatemate/lut_tree_map.v: techlibs/gatemate/lut_tree_lib.mk
|
||||||
|
|
||||||
$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_cells.genlib))
|
$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_cells.genlib))
|
||||||
$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_map.v))
|
$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_map.v))
|
||||||
|
|
||||||
|
|
|
||||||
260
techlibs/gowin/adc.v
Normal file
260
techlibs/gowin/adc.v
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
/********ADC***********/
|
||||||
|
//ADC for LRC,GW5AT-138K
|
||||||
|
module ADCLRC (
|
||||||
|
//Voltage signal source, /mV
|
||||||
|
input ADCINBK2A, //input from bank2 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK2B, //input from bank2 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK3A, //input from bank3 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK3B, //input from bank3 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK4A, //input from bank4 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK4B, //input from bank4 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK5A, //input from bank5 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK5B, //input from bank5 IO, adc_in_b is the reference
|
||||||
|
|
||||||
|
//control signal
|
||||||
|
input [2:0] VSENCTL, //Input source selection (ciu), from 0 to 7: adcv, adct, vdd09_0, vdd09_1, vdd18_0, vdd18_1, vdd33_0, vdd33_1
|
||||||
|
|
||||||
|
input [9:0] FSCAL_VALUE, // temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
input [11:0] OFFSET_VALUE, //signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
input ADCEN, //Enable signal, active high
|
||||||
|
input CLK, //clk input,1/2 shared
|
||||||
|
input DRSTN, //0/1 shared, Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal, valid rising edge, asynchronous signal
|
||||||
|
|
||||||
|
//output
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE //The measurement result output, signed number. In voltage mode,/2048 is the actual measured value; In temperature mode,/4 is the actual measured value
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter DYN_BKEN = "FALSE";//"FALSE","TRUE"."TRUE",BUF_BK2_EN[0]&BUF_BK3_EN[0]=1
|
||||||
|
//Input source selection,1/2 shared
|
||||||
|
parameter BUF_SERDES_Q1_EN = 3'b000; //[1:0] does not support "11"
|
||||||
|
parameter BUF_BK2_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK3_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK4_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK5_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK10_EN = 5'b00000; //[3:1] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK11_EN = 5'b00000; //[3:1] Only one bit can be 1 at the same time
|
||||||
|
//Analog terminal option
|
||||||
|
parameter CLK_SEL = 1'b0; //Clock source selection. 0,PIOCLK_SEL,1,ciu_clk
|
||||||
|
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared,0,mck_adc_clk_osc,1,io_clk
|
||||||
|
parameter VSEN_CTL = 3'b000; //Input source selection
|
||||||
|
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection,0,VSEN_CTL,1,ciu_vsen_ctl
|
||||||
|
parameter ADC_MODE = 1'b0; //Mode selection
|
||||||
|
parameter DIV_CTL = 2'd0; //clock division,0:/1,1:/2,2:/4,3:/8,Clock after frequency division, 500kHz~8MHz
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter SAMPLE_CNT_SEL = 3'd4; //total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter RATE_CHANGE_CTRL = 3'd4; //Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
//ADCULC,GW5AT-138K
|
||||||
|
module ADCULC (
|
||||||
|
|
||||||
|
//Voltage signal source, /mV
|
||||||
|
input ADCINBK6A, //input from bank6 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK6B, //input from bank6 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK7A, //input from bank7 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK7B, //input from bank7 IO, adc_in_b is the reference
|
||||||
|
|
||||||
|
//control signal
|
||||||
|
input [2:0] VSENCTL, //Input source selection(cib),0~7: vtest, vdd09_0, vdd09_1, vdd09_2, vdd18_0, vdd18_1, reserved, vdd33
|
||||||
|
|
||||||
|
input [9:0] FSCAL_VALUE, // temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
input [11:0] OFFSET_VALUE, //signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
input ADCEN, //Enable signal, active high
|
||||||
|
input CLK, //clk input
|
||||||
|
input DRSTN, //0/1 shared, Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal, valid rising edge, asynchronous signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE //The measurement result output, signed number. In voltage mode,/2048 is the actual measured value; In temperature mode,/4 is the actual measured value
|
||||||
|
|
||||||
|
);
|
||||||
|
parameter DYN_BKEN = "FALSE";//"FALSE","TRUE"."TRUE",BUF_BK6_EN[0]&BUF_BK7_EN[0]=1
|
||||||
|
|
||||||
|
//Input source selection
|
||||||
|
parameter BUF_VCC_EN = 1'b0; //ulc
|
||||||
|
parameter BUF_VCCM_EN = 1'b0; //ulc
|
||||||
|
parameter BUF_MIPI_M0_EN = 3'b000; //ulc,[1:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_MIPI_M1_EN = 3'b000; //ulc,[1:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_SERDES_Q0_EN = 3'b000; //ulc,[1:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK6_EN = 6'b000000; //bk6,[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK7_EN = 6'b000000; //bk7,[3:0] Only one bit can be 1 at the same time
|
||||||
|
//Analog terminal option
|
||||||
|
parameter CLK_SEL = 1'b0; //Clock source selection. 0,PIOCLK_SEL,1,ciu_clk
|
||||||
|
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared,0,mck_adc_clk_osc,1,io_clk
|
||||||
|
parameter VSEN_CTL = 3'b000; //Input source selection
|
||||||
|
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection,0,VSEN_CTL,1,ciu_vsen_ctl
|
||||||
|
parameter ADC_MODE = 1'b0; //Mode selection
|
||||||
|
parameter DIV_CTL = 2'd0; //clock division,0:/1,1:/2,2:/4,3:/8,Clock after frequency division, 500kHz~8MHz
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter SAMPLE_CNT_SEL = 3'd4; //total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter RATE_CHANGE_CTRL = 3'd4; //Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
//ADC,GW5A-25
|
||||||
|
module ADC (
|
||||||
|
|
||||||
|
//control signal
|
||||||
|
input CLK, //clk input
|
||||||
|
input [2:0] VSENCTL, //Input source selection (ciu), from 0 to 7: glo_left,glo_right,loc_left,vtest,vcc_rt,vccc_rt,vccm_rt,vccx_buf
|
||||||
|
input ADCMODE, //Mode selection,0:temperature mode,1:voltage mode
|
||||||
|
input DRSTN, //Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal, valid rising edge, asynchronous signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE, //The measurement result output, signed number. In voltage mode,/2048 is the actual measured value; In temperature mode,/4 is the actual measured value
|
||||||
|
//mdrp
|
||||||
|
input MDRP_CLK, //mdrp clock
|
||||||
|
input [7:0] MDRP_WDATA, //mdrp write data
|
||||||
|
input MDRP_A_INC, //mdrp self-increased address
|
||||||
|
input [1:0] MDRP_OPCODE, //mdrp opcode
|
||||||
|
output [7:0] MDRP_RDATA, //mdrp read data
|
||||||
|
input ADCEN //Enable signal, active high
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
//Analog terminal option
|
||||||
|
parameter CLK_SEL = 1'b0; //时钟源选择,0:osc(2.5MHz),1:CLK
|
||||||
|
parameter DIV_CTL = 2'd0; //clock division,0:/1,1:/2,2:/4,3:/8,Clock after frequency division, 500kHz~8MHz
|
||||||
|
|
||||||
|
//Input source selection
|
||||||
|
parameter BUF_EN = 12'b000000000000; //
|
||||||
|
parameter BUF_BK0_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK1_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK2_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK3_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK4_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK5_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK6_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK7_VREF_EN = 1'b0; //
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter CSR_ADC_MODE = 1'b1; // Mode selection
|
||||||
|
parameter CSR_VSEN_CTRL = 3'd0; // signal source:vccx/vccio_*/vcc_reg -> 7, signal source:vcc_ext -> 4, others -> 0
|
||||||
|
parameter CSR_SAMPLE_CNT_SEL = 3'd4; // total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter CSR_RATE_CHANGE_CTRL = 3'd4; // Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
parameter CSR_FSCAL = 10'd730; // Parameter 1: temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
parameter CSR_OFFSET = -12'd1180; // Parameter 2, signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
//ADC_SAR,integrated saradc and adc functions.
|
||||||
|
module ADC_SAR (
|
||||||
|
//`ifdef ADC
|
||||||
|
input ADCMODE, //Mode selection
|
||||||
|
input [2:0] VSENCTL, //Input source selection
|
||||||
|
input CLK, //clk input
|
||||||
|
//Digital
|
||||||
|
output ADCENO, //Enable signal, active high
|
||||||
|
input DRSTN, //Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE, //The measurement result output
|
||||||
|
input MDRP_CLK, //mdrp clock
|
||||||
|
input [7:0] MDRP_WDATA, //mdrp write data
|
||||||
|
input MDRP_A_INC, //mdrp self-increased address
|
||||||
|
input [1:0] MDRP_OPCODE,//mdrp opcode
|
||||||
|
output [7:0] MDRP_RDATA, //mdrp read data
|
||||||
|
//Analog
|
||||||
|
output ADC1BIT, //Analog data output
|
||||||
|
output ADCCLKO, //Analog clock output
|
||||||
|
input ADCENI, //fabric adc enable input
|
||||||
|
//`endif
|
||||||
|
// SAR
|
||||||
|
//`ifdef SARADC
|
||||||
|
output [12:0] ADCBIT, //Measurement result output
|
||||||
|
output CLKO, //output clk
|
||||||
|
output EOC, //The measurement completion signal
|
||||||
|
input CLKI, //fabric input clk
|
||||||
|
input [6:0] CHEN, //channel select
|
||||||
|
input RSTN, //resetn,active low
|
||||||
|
input SOC //Measurement request signal
|
||||||
|
//`endif
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter BUF_EN = 29'b0; // signal source selecor switch
|
||||||
|
// Δ-Σ
|
||||||
|
//`ifdef ADC
|
||||||
|
parameter CLK_SEL = 1'b1; // clk source select
|
||||||
|
parameter DIV_CTL = 2'd0; // clock division.0:/1,1:/2,2:/4,3:/8
|
||||||
|
parameter ADC_EN_SEL = 1'b0; // adc_en source select
|
||||||
|
parameter PHASE_SEL = 1'b0; // adc internal data phase select
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter CSR_ADC_MODE = 1'b1; // Mode selection
|
||||||
|
parameter CSR_VSEN_CTRL = 3'd0; // signal source:vccx/vccio_*/vcc_reg -> 7, signal source:vcc_ext -> 4, others -> 0
|
||||||
|
parameter CSR_SAMPLE_CNT_SEL = 3'd4; // total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter CSR_RATE_CHANGE_CTRL = 3'd4; // Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
parameter CSR_FSCAL = 10'd730; // Parameter 1: temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
parameter CSR_OFFSET = -12'd1180; // Parameter 2, signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
//`endif
|
||||||
|
// SAR
|
||||||
|
//`ifdef SARADC
|
||||||
|
parameter ADC_CLK_DIV = 2'b00; // clock division.00:/1,01:/2,10:/4,11:/8
|
||||||
|
parameter ADC_CLKDIV_EN = 1'b0; // clock division enable
|
||||||
|
parameter CLK_SRC_SEL = 1'b1; // source clock sel
|
||||||
|
parameter VREF_BUF_EN = 1'b1; // BGR vref buffer enable
|
||||||
|
parameter COUNT_LEN = 5'b10100; // ADC counter length
|
||||||
|
parameter DAC_SAMPLE_END = 5'b10010; // DAC sample end point
|
||||||
|
parameter DAC_SAMPLE_START = 5'b01101; // DAC sample start point
|
||||||
|
parameter SH_SAMPLE_END = 5'b01011; // SH sample start point
|
||||||
|
parameter SH_SAMPLE_START = 5'b00001; // SH sample end point
|
||||||
|
parameter AUTO_CHOP_EN = 1'b0; // auto chop
|
||||||
|
parameter CHOP_CLK_DIV = 4'b0; // chop clock divider
|
||||||
|
|
||||||
|
//`endif
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
//ADCA,15k
|
||||||
|
module ADCA (
|
||||||
|
// analog
|
||||||
|
input ADCMODE, //Mode selection
|
||||||
|
input [2:0] VSENCTL, //Input source selection 0-7: vglo_left, vglo_right, vcc2, vccc3, vccb4, vcc5, vccm6, vccc7
|
||||||
|
input CLK, //clk input
|
||||||
|
input ADCENI, //fabric adc enable input
|
||||||
|
input PWRON_DYN, //power enable. 1:on 0:off
|
||||||
|
// digital
|
||||||
|
input DRSTN, //Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE, //The measurement result output
|
||||||
|
input MDRP_CLK, //mdrp clock
|
||||||
|
input [7:0] MDRP_WDATA, //mdrp write data
|
||||||
|
input MDRP_A_INC, //mdrp self-increased address
|
||||||
|
input [1:0] MDRP_OPCODE,//mdrp opcode
|
||||||
|
output [7:0] MDRP_RDATA //mdrp read data
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter BUF_EN = 20'b0; // signal source selecor switch //[8:0] one-hot; [19:15] one-hot. BUF_EN[6] must be 0
|
||||||
|
parameter CLK_SEL = 1'b1; // clk source select
|
||||||
|
parameter DIV_CTL = 2'd0; // clock division
|
||||||
|
parameter ADC_EN_SEL = 1'b0; // adc_en source select
|
||||||
|
parameter PHASE_SEL = 1'b0; // adc internal data phase select
|
||||||
|
|
||||||
|
parameter PWRON_SEL = 1'b0; // power enbale source select. 0:PWRON 1:PWRON_DYN
|
||||||
|
parameter PWRON = 1'b1; // as PWRON_DYN
|
||||||
|
parameter LDO_MODE = 1'b0; // LDO mode 0:on(2.5/3.3V) 1:off(1.8V)
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter CSR_ADC_MODE = 1'b1; // Mode selection
|
||||||
|
parameter CSR_VSEN_CTRL = 3'd0; // signal source:vccx/vccio_*/vcc_reg -> 7, signal source:vcc_ext -> 4, others -> 0
|
||||||
|
parameter CSR_SAMPLE_CNT_SEL = 3'd4; // total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter CSR_RATE_CHANGE_CTRL = 3'd4; // Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
parameter CSR_FSCAL = 10'd730; // Parameter 1: temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
parameter CSR_OFFSET = -12'd1180; // Parameter 2, signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
@ -32,6 +32,8 @@ _skip = { # These are already described, no need to extract them from the vendor
|
||||||
'DLNC', 'DLNCE', 'DLNP', 'DLNPE', 'rSDP', 'rSDPX9', 'rROM', 'rROMX9',
|
'DLNC', 'DLNCE', 'DLNP', 'DLNPE', 'rSDP', 'rSDPX9', 'rROM', 'rROMX9',
|
||||||
'TLVDS_OEN_BK', 'DLL', 'DCC', 'I3C', 'IODELAYA', 'IODELAYC', 'IODELAYB',
|
'TLVDS_OEN_BK', 'DLL', 'DCC', 'I3C', 'IODELAYA', 'IODELAYC', 'IODELAYB',
|
||||||
'SPMI', 'PLLO', 'DCCG', 'MIPI_DPHY_RX', 'CLKDIVG', 'PWRGRD', 'FLASH96KA',
|
'SPMI', 'PLLO', 'DCCG', 'MIPI_DPHY_RX', 'CLKDIVG', 'PWRGRD', 'FLASH96KA',
|
||||||
|
# ADCs are in a separate file
|
||||||
|
'ADCLRC', 'ADCULC', 'ADC', 'ADC_SAR', 'ADCA',
|
||||||
}
|
}
|
||||||
def xtract_cells_decl(dir, fout):
|
def xtract_cells_decl(dir, fout):
|
||||||
fname = os.path.join(dir, 'prim_sim.v')
|
fname = os.path.join(dir, 'prim_sim.v')
|
||||||
|
|
@ -94,3 +96,11 @@ if __name__ == '__main__':
|
||||||
fout.write('// Created by cells_xtra.py\n')
|
fout.write('// Created by cells_xtra.py\n')
|
||||||
fout.write('\n')
|
fout.write('\n')
|
||||||
xtract_cells_decl(dir, fout)
|
xtract_cells_decl(dir, fout)
|
||||||
|
if family == 'gw5a':
|
||||||
|
fout.write('\n')
|
||||||
|
fout.write('// Added from adc.v\n')
|
||||||
|
fout.write('\n')
|
||||||
|
with open(f'adc.v', 'r') as fin:
|
||||||
|
for l in fin:
|
||||||
|
fout.write(l);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1720,89 +1720,6 @@ input SPIAD;
|
||||||
input LOAD;
|
input LOAD;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module ADCLRC (...);
|
|
||||||
parameter DYN_BKEN = "FALSE";
|
|
||||||
parameter BUF_SERDES_Q1_EN = 3'b000;
|
|
||||||
parameter BUF_BK2_EN = 6'b000000;
|
|
||||||
parameter BUF_BK3_EN = 6'b000000;
|
|
||||||
parameter BUF_BK4_EN = 6'b000000;
|
|
||||||
parameter BUF_BK5_EN = 6'b000000;
|
|
||||||
parameter BUF_BK10_EN = 5'b00000;
|
|
||||||
parameter BUF_BK11_EN = 5'b00000;
|
|
||||||
parameter CLK_SEL = 1'b0;
|
|
||||||
parameter PIOCLK_SEL = 1'b0;
|
|
||||||
parameter VSEN_CTL = 3'b000;
|
|
||||||
parameter VSEN_CTL_SEL = 1'b0;
|
|
||||||
parameter ADC_MODE = 1'b0;
|
|
||||||
parameter DIV_CTL = 2'd0;
|
|
||||||
parameter SAMPLE_CNT_SEL = 3'd4;
|
|
||||||
parameter RATE_CHANGE_CTRL = 3'd4;
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module ADCULC (...);
|
|
||||||
parameter DYN_BKEN = "FALSE";
|
|
||||||
parameter BUF_VCC_EN = 1'b0;
|
|
||||||
parameter BUF_VCCM_EN = 1'b0;
|
|
||||||
parameter BUF_MIPI_M0_EN = 3'b000;
|
|
||||||
parameter BUF_MIPI_M1_EN = 3'b000;
|
|
||||||
parameter BUF_SERDES_Q0_EN = 3'b000;
|
|
||||||
parameter BUF_BK6_EN = 6'b000000;
|
|
||||||
parameter BUF_BK7_EN = 6'b000000;
|
|
||||||
parameter CLK_SEL = 1'b0;
|
|
||||||
parameter PIOCLK_SEL = 1'b0;
|
|
||||||
parameter VSEN_CTL = 3'b000;
|
|
||||||
parameter VSEN_CTL_SEL = 1'b0;
|
|
||||||
parameter ADC_MODE = 1'b0;
|
|
||||||
parameter DIV_CTL = 2'd0;
|
|
||||||
parameter SAMPLE_CNT_SEL = 3'd4;
|
|
||||||
parameter RATE_CHANGE_CTRL = 3'd4;
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module ADC (...);
|
|
||||||
parameter CLK_SEL = 1'b0;
|
|
||||||
parameter DIV_CTL = 2'd0;
|
|
||||||
parameter BUF_EN = 12'b000000000000;
|
|
||||||
parameter BUF_BK0_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK1_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK2_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK3_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK4_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK5_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK6_VREF_EN = 1'b0;
|
|
||||||
parameter BUF_BK7_VREF_EN = 1'b0;
|
|
||||||
parameter CSR_ADC_MODE = 1'b1;
|
|
||||||
parameter CSR_VSEN_CTRL = 3'd0;
|
|
||||||
parameter CSR_SAMPLE_CNT_SEL = 3'd4;
|
|
||||||
parameter CSR_RATE_CHANGE_CTRL = 3'd4;
|
|
||||||
parameter CSR_FSCAL = 10'd730;
|
|
||||||
parameter CSR_OFFSET = -12'd1180;
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module ADC_SAR (...);
|
|
||||||
parameter BUF_EN = 29'b0;
|
|
||||||
parameter CLK_SEL = 1'b1;
|
|
||||||
parameter DIV_CTL = 2'd2;
|
|
||||||
parameter ADC_EN_SEL = 1'b0;
|
|
||||||
parameter PHASE_SEL = 1'b0;
|
|
||||||
parameter CSR_ADC_MODE = 1'b1;
|
|
||||||
parameter CSR_VSEN_CTRL = 3'd0;
|
|
||||||
parameter CSR_SAMPLE_CNT_SEL = 3'd4;
|
|
||||||
parameter CSR_RATE_CHANGE_CTRL = 3'd4;
|
|
||||||
parameter CSR_FSCAL = 10'd730;
|
|
||||||
parameter CSR_OFFSET = -12'd1180;
|
|
||||||
parameter ADC_CLK_DIV = 2'b00;
|
|
||||||
parameter ADC_CLKDIV_EN = 1'b0;
|
|
||||||
parameter CLK_SRC_SEL = 1'b1;
|
|
||||||
parameter VREF_BUF_EN = 1'b1;
|
|
||||||
parameter COUNT_LEN = 5'b10100;
|
|
||||||
parameter DAC_SAMPLE_END = 5'b10010;
|
|
||||||
parameter DAC_SAMPLE_START = 5'b01101;
|
|
||||||
parameter SH_SAMPLE_END = 5'b01011;
|
|
||||||
parameter SH_SAMPLE_START = 5'b00001;
|
|
||||||
parameter AUTO_CHOP_EN = 1'b0;
|
|
||||||
parameter CHOP_CLK_DIV = 4'b0;
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module LICD (...);
|
module LICD (...);
|
||||||
parameter STAGE_NUM = 2'b00;
|
parameter STAGE_NUM = 2'b00;
|
||||||
parameter ENCDEC_NUM = 2'b00;
|
parameter ENCDEC_NUM = 2'b00;
|
||||||
|
|
@ -2575,3 +2492,266 @@ parameter RD_PNTR = 3'b000;
|
||||||
parameter DQS_MODE = "X1";
|
parameter DQS_MODE = "X1";
|
||||||
parameter HWL = "false";
|
parameter HWL = "false";
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// Added form adc.v
|
||||||
|
|
||||||
|
/********ADC***********/
|
||||||
|
//ADC for LRC,GW5AT-138K
|
||||||
|
module ADCLRC (
|
||||||
|
//Voltage signal source, /mV
|
||||||
|
input ADCINBK2A, //input from bank2 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK2B, //input from bank2 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK3A, //input from bank3 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK3B, //input from bank3 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK4A, //input from bank4 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK4B, //input from bank4 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK5A, //input from bank5 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK5B, //input from bank5 IO, adc_in_b is the reference
|
||||||
|
|
||||||
|
//control signal
|
||||||
|
input [2:0] VSENCTL, //Input source selection (ciu), from 0 to 7: adcv, adct, vdd09_0, vdd09_1, vdd18_0, vdd18_1, vdd33_0, vdd33_1
|
||||||
|
|
||||||
|
input [9:0] FSCAL_VALUE, // temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
input [11:0] OFFSET_VALUE, //signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
input ADCEN, //Enable signal, active high
|
||||||
|
input CLK, //clk input,1/2 shared
|
||||||
|
input DRSTN, //0/1 shared, Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal, valid rising edge, asynchronous signal
|
||||||
|
|
||||||
|
//output
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE //The measurement result output, signed number. In voltage mode,/2048 is the actual measured value; In temperature mode,/4 is the actual measured value
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter DYN_BKEN = "FALSE";//"FALSE","TRUE"."TRUE",BUF_BK2_EN[0]&BUF_BK3_EN[0]=1
|
||||||
|
//Input source selection,1/2 shared
|
||||||
|
parameter BUF_SERDES_Q1_EN = 3'b000; //[1:0] does not support "11"
|
||||||
|
parameter BUF_BK2_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK3_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK4_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK5_EN = 6'b000000; //[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK10_EN = 5'b00000; //[3:1] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK11_EN = 5'b00000; //[3:1] Only one bit can be 1 at the same time
|
||||||
|
//Analog terminal option
|
||||||
|
parameter CLK_SEL = 1'b0; //Clock source selection. 0,PIOCLK_SEL,1,ciu_clk
|
||||||
|
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared,0,mck_adc_clk_osc,1,io_clk
|
||||||
|
parameter VSEN_CTL = 3'b000; //Input source selection
|
||||||
|
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection,0,VSEN_CTL,1,ciu_vsen_ctl
|
||||||
|
parameter ADC_MODE = 1'b0; //Mode selection
|
||||||
|
parameter DIV_CTL = 2'd0; //clock division,0:/1,1:/2,2:/4,3:/8,Clock after frequency division, 500kHz~8MHz
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter SAMPLE_CNT_SEL = 3'd4; //total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter RATE_CHANGE_CTRL = 3'd4; //Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
//ADCULC,GW5AT-138K
|
||||||
|
module ADCULC (
|
||||||
|
|
||||||
|
//Voltage signal source, /mV
|
||||||
|
input ADCINBK6A, //input from bank6 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK6B, //input from bank6 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK7A, //input from bank7 IO, adc_in_b is the reference
|
||||||
|
input ADCINBK7B, //input from bank7 IO, adc_in_b is the reference
|
||||||
|
|
||||||
|
//control signal
|
||||||
|
input [2:0] VSENCTL, //Input source selection(cib),0~7: vtest, vdd09_0, vdd09_1, vdd09_2, vdd18_0, vdd18_1, reserved, vdd33
|
||||||
|
|
||||||
|
input [9:0] FSCAL_VALUE, // temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
input [11:0] OFFSET_VALUE, //signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
input ADCEN, //Enable signal, active high
|
||||||
|
input CLK, //clk input
|
||||||
|
input DRSTN, //0/1 shared, Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal, valid rising edge, asynchronous signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE //The measurement result output, signed number. In voltage mode,/2048 is the actual measured value; In temperature mode,/4 is the actual measured value
|
||||||
|
|
||||||
|
);
|
||||||
|
parameter DYN_BKEN = "FALSE";//"FALSE","TRUE"."TRUE",BUF_BK6_EN[0]&BUF_BK7_EN[0]=1
|
||||||
|
|
||||||
|
//Input source selection
|
||||||
|
parameter BUF_VCC_EN = 1'b0; //ulc
|
||||||
|
parameter BUF_VCCM_EN = 1'b0; //ulc
|
||||||
|
parameter BUF_MIPI_M0_EN = 3'b000; //ulc,[1:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_MIPI_M1_EN = 3'b000; //ulc,[1:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_SERDES_Q0_EN = 3'b000; //ulc,[1:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK6_EN = 6'b000000; //bk6,[3:0] Only one bit can be 1 at the same time
|
||||||
|
parameter BUF_BK7_EN = 6'b000000; //bk7,[3:0] Only one bit can be 1 at the same time
|
||||||
|
//Analog terminal option
|
||||||
|
parameter CLK_SEL = 1'b0; //Clock source selection. 0,PIOCLK_SEL,1,ciu_clk
|
||||||
|
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared,0,mck_adc_clk_osc,1,io_clk
|
||||||
|
parameter VSEN_CTL = 3'b000; //Input source selection
|
||||||
|
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection,0,VSEN_CTL,1,ciu_vsen_ctl
|
||||||
|
parameter ADC_MODE = 1'b0; //Mode selection
|
||||||
|
parameter DIV_CTL = 2'd0; //clock division,0:/1,1:/2,2:/4,3:/8,Clock after frequency division, 500kHz~8MHz
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter SAMPLE_CNT_SEL = 3'd4; //total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter RATE_CHANGE_CTRL = 3'd4; //Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
//ADC,GW5A-25
|
||||||
|
module ADC (
|
||||||
|
|
||||||
|
//control signal
|
||||||
|
input CLK, //clk input
|
||||||
|
input [2:0] VSENCTL, //Input source selection (ciu), from 0 to 7: glo_left,glo_right,loc_left,vtest,vcc_rt,vccc_rt,vccm_rt,vccx_buf
|
||||||
|
input ADCMODE, //Mode selection,0:temperature mode,1:voltage mode
|
||||||
|
input DRSTN, //Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal, valid rising edge, asynchronous signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE, //The measurement result output, signed number. In voltage mode,/2048 is the actual measured value; In temperature mode,/4 is the actual measured value
|
||||||
|
//mdrp
|
||||||
|
input MDRP_CLK, //mdrp clock
|
||||||
|
input [7:0] MDRP_WDATA, //mdrp write data
|
||||||
|
input MDRP_A_INC, //mdrp self-increased address
|
||||||
|
input [1:0] MDRP_OPCODE, //mdrp opcode
|
||||||
|
output [7:0] MDRP_RDATA, //mdrp read data
|
||||||
|
input ADCEN //Enable signal, active high
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
//Analog terminal option
|
||||||
|
parameter CLK_SEL = 1'b0; //时钟源选择,0:osc(2.5MHz),1:CLK
|
||||||
|
parameter DIV_CTL = 2'd0; //clock division,0:/1,1:/2,2:/4,3:/8,Clock after frequency division, 500kHz~8MHz
|
||||||
|
|
||||||
|
//Input source selection
|
||||||
|
parameter BUF_EN = 12'b000000000000; //
|
||||||
|
parameter BUF_BK0_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK1_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK2_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK3_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK4_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK5_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK6_VREF_EN = 1'b0; //
|
||||||
|
parameter BUF_BK7_VREF_EN = 1'b0; //
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter CSR_ADC_MODE = 1'b1; // Mode selection
|
||||||
|
parameter CSR_VSEN_CTRL = 3'd0; // signal source:vccx/vccio_*/vcc_reg -> 7, signal source:vcc_ext -> 4, others -> 0
|
||||||
|
parameter CSR_SAMPLE_CNT_SEL = 3'd4; // total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter CSR_RATE_CHANGE_CTRL = 3'd4; // Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
parameter CSR_FSCAL = 10'd730; // Parameter 1: temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
parameter CSR_OFFSET = -12'd1180; // Parameter 2, signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
//ADC_SAR,integrated saradc and adc functions.
|
||||||
|
module ADC_SAR (
|
||||||
|
//`ifdef ADC
|
||||||
|
input ADCMODE, //Mode selection
|
||||||
|
input [2:0] VSENCTL, //Input source selection
|
||||||
|
input CLK, //clk input
|
||||||
|
//Digital
|
||||||
|
output ADCENO, //Enable signal, active high
|
||||||
|
input DRSTN, //Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE, //The measurement result output
|
||||||
|
input MDRP_CLK, //mdrp clock
|
||||||
|
input [7:0] MDRP_WDATA, //mdrp write data
|
||||||
|
input MDRP_A_INC, //mdrp self-increased address
|
||||||
|
input [1:0] MDRP_OPCODE,//mdrp opcode
|
||||||
|
output [7:0] MDRP_RDATA, //mdrp read data
|
||||||
|
//Analog
|
||||||
|
output ADC1BIT, //Analog data output
|
||||||
|
output ADCCLKO, //Analog clock output
|
||||||
|
input ADCENI, //fabric adc enable input
|
||||||
|
//`endif
|
||||||
|
// SAR
|
||||||
|
//`ifdef SARADC
|
||||||
|
output [12:0] ADCBIT, //Measurement result output
|
||||||
|
output CLKO, //output clk
|
||||||
|
output EOC, //The measurement completion signal
|
||||||
|
input CLKI, //fabric input clk
|
||||||
|
input [6:0] CHEN, //channel select
|
||||||
|
input RSTN, //resetn,active low
|
||||||
|
input SOC //Measurement request signal
|
||||||
|
//`endif
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter BUF_EN = 29'b0; // signal source selecor switch
|
||||||
|
// Δ-Σ
|
||||||
|
//`ifdef ADC
|
||||||
|
parameter CLK_SEL = 1'b1; // clk source select
|
||||||
|
parameter DIV_CTL = 2'd0; // clock division.0:/1,1:/2,2:/4,3:/8
|
||||||
|
parameter ADC_EN_SEL = 1'b0; // adc_en source select
|
||||||
|
parameter PHASE_SEL = 1'b0; // adc internal data phase select
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter CSR_ADC_MODE = 1'b1; // Mode selection
|
||||||
|
parameter CSR_VSEN_CTRL = 3'd0; // signal source:vccx/vccio_*/vcc_reg -> 7, signal source:vcc_ext -> 4, others -> 0
|
||||||
|
parameter CSR_SAMPLE_CNT_SEL = 3'd4; // total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter CSR_RATE_CHANGE_CTRL = 3'd4; // Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
parameter CSR_FSCAL = 10'd730; // Parameter 1: temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
parameter CSR_OFFSET = -12'd1180; // Parameter 2, signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
//`endif
|
||||||
|
// SAR
|
||||||
|
//`ifdef SARADC
|
||||||
|
parameter ADC_CLK_DIV = 2'b00; // clock division.00:/1,01:/2,10:/4,11:/8
|
||||||
|
parameter ADC_CLKDIV_EN = 1'b0; // clock division enable
|
||||||
|
parameter CLK_SRC_SEL = 1'b1; // source clock sel
|
||||||
|
parameter VREF_BUF_EN = 1'b1; // BGR vref buffer enable
|
||||||
|
parameter COUNT_LEN = 5'b10100; // ADC counter length
|
||||||
|
parameter DAC_SAMPLE_END = 5'b10010; // DAC sample end point
|
||||||
|
parameter DAC_SAMPLE_START = 5'b01101; // DAC sample start point
|
||||||
|
parameter SH_SAMPLE_END = 5'b01011; // SH sample start point
|
||||||
|
parameter SH_SAMPLE_START = 5'b00001; // SH sample end point
|
||||||
|
parameter AUTO_CHOP_EN = 1'b0; // auto chop
|
||||||
|
parameter CHOP_CLK_DIV = 4'b0; // chop clock divider
|
||||||
|
|
||||||
|
//`endif
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
//ADCA,15k
|
||||||
|
module ADCA (
|
||||||
|
// analog
|
||||||
|
input ADCMODE, //Mode selection
|
||||||
|
input [2:0] VSENCTL, //Input source selection 0-7: vglo_left, vglo_right, vcc2, vccc3, vccb4, vcc5, vccm6, vccc7
|
||||||
|
input CLK, //clk input
|
||||||
|
input ADCENI, //fabric adc enable input
|
||||||
|
input PWRON_DYN, //power enable. 1:on 0:off
|
||||||
|
// digital
|
||||||
|
input DRSTN, //Digital part reset signal, active low
|
||||||
|
input ADCREQI, //Measurement request signal
|
||||||
|
output ADCRDY, //The measurement completion signal, active high
|
||||||
|
output [13:0] ADCVALUE, //The measurement result output
|
||||||
|
input MDRP_CLK, //mdrp clock
|
||||||
|
input [7:0] MDRP_WDATA, //mdrp write data
|
||||||
|
input MDRP_A_INC, //mdrp self-increased address
|
||||||
|
input [1:0] MDRP_OPCODE,//mdrp opcode
|
||||||
|
output [7:0] MDRP_RDATA //mdrp read data
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter BUF_EN = 20'b0; // signal source selecor switch //[8:0] one-hot; [19:15] one-hot. BUF_EN[6] must be 0
|
||||||
|
parameter CLK_SEL = 1'b1; // clk source select
|
||||||
|
parameter DIV_CTL = 2'd0; // clock division
|
||||||
|
parameter ADC_EN_SEL = 1'b0; // adc_en source select
|
||||||
|
parameter PHASE_SEL = 1'b0; // adc internal data phase select
|
||||||
|
|
||||||
|
parameter PWRON_SEL = 1'b0; // power enbale source select. 0:PWRON 1:PWRON_DYN
|
||||||
|
parameter PWRON = 1'b1; // as PWRON_DYN
|
||||||
|
parameter LDO_MODE = 1'b0; // LDO mode 0:on(2.5/3.3V) 1:off(1.8V)
|
||||||
|
|
||||||
|
//Digital terminal options
|
||||||
|
parameter CSR_ADC_MODE = 1'b1; // Mode selection
|
||||||
|
parameter CSR_VSEN_CTRL = 3'd0; // signal source:vccx/vccio_*/vcc_reg -> 7, signal source:vcc_ext -> 4, others -> 0
|
||||||
|
parameter CSR_SAMPLE_CNT_SEL = 3'd4; // total samples configuration, 0~4:64, 128, 256, 512, 1024 sampling points, and the other values are 2048 sampling points.The total number of samples shall be greater than 7 * sampling period, i.e. SAMPLR_CNT_SEL >= RATE_CHANGE_CTRL-1
|
||||||
|
parameter CSR_RATE_CHANGE_CTRL = 3'd4; // Sampling period configuration, 0~4:4、8、16、32、64,other values are 128
|
||||||
|
parameter CSR_FSCAL = 10'd730; // Parameter 1: temperature mode 510~948, typical value 730; Voltage mode 452~840, typical value 653
|
||||||
|
parameter CSR_OFFSET = -12'd1180; // Parameter 2, signed number, temperature mode - 1560~- 760, typical value - 1180; Voltage mode - 410~410, typical value 0
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@ module XNOR2X1 (B, A, Y);
|
||||||
input B;
|
input B;
|
||||||
input A;
|
input A;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = !(B&!A|!B&A); // "!(B&!A|!B&A)"
|
assign Y = (~((B&(~A))|((~B)&A))); // "!(B&!A|!B&A)"
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ library(dff) {
|
||||||
area : 1;
|
area : 1;
|
||||||
ff("IQ", "IQN") {
|
ff("IQ", "IQN") {
|
||||||
next_state : "(D)";
|
next_state : "(D)";
|
||||||
clocked_on : "CLK";
|
clocked_on : (CLK);
|
||||||
}
|
}
|
||||||
pin(D) {
|
pin(D) {
|
||||||
direction : input;
|
direction : input;
|
||||||
|
|
@ -15,7 +15,7 @@ library(dff) {
|
||||||
}
|
}
|
||||||
pin(Q) {
|
pin(Q) {
|
||||||
direction: output;
|
direction: output;
|
||||||
function : "IQ";
|
function : IQ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ library(dff) {
|
||||||
area : 1 ;
|
area : 1 ;
|
||||||
ff("IQ", "IQN") {
|
ff("IQ", "IQN") {
|
||||||
next_state : "(D)" ;
|
next_state : "(D)" ;
|
||||||
clocked_on : "CLK" ;
|
clocked_on : ( CLK ) ;
|
||||||
}
|
}
|
||||||
pin(D) {
|
pin(D) {
|
||||||
direction : input ;
|
direction : input ;
|
||||||
|
|
@ -13,7 +13,7 @@ library(dff) {
|
||||||
}
|
}
|
||||||
pin(Q) {
|
pin(Q) {
|
||||||
direction : output ;
|
direction : output ;
|
||||||
function : "IQ" ;
|
function : IQ ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
module dff (D, CLK, Q);
|
module dff (D, CLK, Q);
|
||||||
reg "IQ", "IQN";
|
reg IQ, IQN;
|
||||||
input D;
|
input D;
|
||||||
input CLK;
|
input CLK;
|
||||||
output Q;
|
output Q;
|
||||||
assign Q = IQ; // "IQ"
|
assign Q = IQ; // IQ
|
||||||
always @(posedge CLK) begin
|
always @(posedge CLK) begin
|
||||||
// "(D)"
|
// "(D)"
|
||||||
"IQ" <= (D);
|
IQ <= D;
|
||||||
"IQN" <= ~((D));
|
IQN <= ~(D);
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
module inv (A, Y);
|
module inv (A, Y);
|
||||||
input A;
|
input A;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = ~A; // "A'"
|
assign Y = (~A); // "A'"
|
||||||
endmodule
|
endmodule
|
||||||
module tri_inv (A, S, Z);
|
module tri_inv (A, S, Z);
|
||||||
input A;
|
input A;
|
||||||
input S;
|
input S;
|
||||||
output Z;
|
output Z;
|
||||||
assign Z = ~A; // "A'"
|
assign Z = (~A); // "A'"
|
||||||
endmodule
|
endmodule
|
||||||
module buffer (A, Y);
|
module buffer (A, Y);
|
||||||
input A;
|
input A;
|
||||||
|
|
@ -18,29 +18,29 @@ module nand2 (A, B, Y);
|
||||||
input A;
|
input A;
|
||||||
input B;
|
input B;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = ~(A&B); // "(A * B)'"
|
assign Y = (~(A&B)); // "(A * B)'"
|
||||||
endmodule
|
endmodule
|
||||||
module nor2 (A, B, Y);
|
module nor2 (A, B, Y);
|
||||||
input A;
|
input A;
|
||||||
input B;
|
input B;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = ~(A|B); // "(A + B)'"
|
assign Y = (~(A|B)); // "(A + B)'"
|
||||||
endmodule
|
endmodule
|
||||||
module xor2 (A, B, Y);
|
module xor2 (A, B, Y);
|
||||||
input A;
|
input A;
|
||||||
input B;
|
input B;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = (A&~B)|(~A&B); // "(A *B') + (A' * B)"
|
assign Y = ((A&(~B))|((~A)&B)); // "(A *B') + (A' * B)"
|
||||||
endmodule
|
endmodule
|
||||||
module imux2 (A, B, S, Y);
|
module imux2 (A, B, S, Y);
|
||||||
input A;
|
input A;
|
||||||
input B;
|
input B;
|
||||||
input S;
|
input S;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = ~(&(A&S)|(B&~S)&); // "( (A * S) + (B * S') )'"
|
assign Y = (~((A&S)|(B&(~S)))); // "( (A * S) + (B * S') )'"
|
||||||
endmodule
|
endmodule
|
||||||
module dff (D, CLK, RESET, PRESET, Q, QN);
|
module dff (D, CLK, RESET, PRESET, Q, QN);
|
||||||
reg "IQ", "IQN";
|
reg IQ, IQN;
|
||||||
input D;
|
input D;
|
||||||
input CLK;
|
input CLK;
|
||||||
input RESET;
|
input RESET;
|
||||||
|
|
@ -51,26 +51,26 @@ module dff (D, CLK, RESET, PRESET, Q, QN);
|
||||||
assign QN = IQN; // "IQN"
|
assign QN = IQN; // "IQN"
|
||||||
always @(posedge CLK, posedge RESET, posedge PRESET) begin
|
always @(posedge CLK, posedge RESET, posedge PRESET) begin
|
||||||
if ((RESET) && (PRESET)) begin
|
if ((RESET) && (PRESET)) begin
|
||||||
"IQ" <= 0;
|
IQ <= 0;
|
||||||
"IQN" <= 0;
|
IQN <= 0;
|
||||||
end
|
end
|
||||||
else if (RESET) begin
|
else if (RESET) begin
|
||||||
"IQ" <= 0;
|
IQ <= 0;
|
||||||
"IQN" <= 1;
|
IQN <= 1;
|
||||||
end
|
end
|
||||||
else if (PRESET) begin
|
else if (PRESET) begin
|
||||||
"IQ" <= 1;
|
IQ <= 1;
|
||||||
"IQN" <= 0;
|
IQN <= 0;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
// "D"
|
// "D"
|
||||||
"IQ" <= D;
|
IQ <= D;
|
||||||
"IQN" <= ~(D);
|
IQN <= ~(D);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
module latch (D, G, Q, QN);
|
module latch (D, G, Q, QN);
|
||||||
reg "IQ", "IQN";
|
reg IQ, IQN;
|
||||||
input D;
|
input D;
|
||||||
input G;
|
input G;
|
||||||
output Q;
|
output Q;
|
||||||
|
|
@ -79,8 +79,8 @@ module latch (D, G, Q, QN);
|
||||||
assign QN = IQN; // "IQN"
|
assign QN = IQN; // "IQN"
|
||||||
always @* begin
|
always @* begin
|
||||||
if (G) begin
|
if (G) begin
|
||||||
"IQ" <= D;
|
IQ <= D;
|
||||||
"IQN" <= ~(D);
|
IQN <= ~(D);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
@ -89,14 +89,14 @@ module aoi211 (A, B, C, Y);
|
||||||
input B;
|
input B;
|
||||||
input C;
|
input C;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = ~((A&B)|C); // "((A * B) + C)'"
|
assign Y = (~((A&B)|C)); // "((A * B) + C)'"
|
||||||
endmodule
|
endmodule
|
||||||
module oai211 (A, B, C, Y);
|
module oai211 (A, B, C, Y);
|
||||||
input A;
|
input A;
|
||||||
input B;
|
input B;
|
||||||
input C;
|
input C;
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = ~((A|B)&C); // "((A + B) * C)'"
|
assign Y = (~((A|B)&C)); // "((A + B) * C)'"
|
||||||
endmodule
|
endmodule
|
||||||
module halfadder (A, B, C, Y);
|
module halfadder (A, B, C, Y);
|
||||||
input A;
|
input A;
|
||||||
|
|
@ -104,7 +104,7 @@ module halfadder (A, B, C, Y);
|
||||||
output C;
|
output C;
|
||||||
assign C = (A&B); // "(A * B)"
|
assign C = (A&B); // "(A * B)"
|
||||||
output Y;
|
output Y;
|
||||||
assign Y = (A&~B)|(~A&B); // "(A *B') + (A' * B)"
|
assign Y = ((A&(~B))|((~A)&B)); // "(A *B') + (A' * B)"
|
||||||
endmodule
|
endmodule
|
||||||
module fulladder (A, B, CI, CO, Y);
|
module fulladder (A, B, CI, CO, Y);
|
||||||
input A;
|
input A;
|
||||||
|
|
|
||||||
60
tests/liberty/unquoted.lib
Normal file
60
tests/liberty/unquoted.lib
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
library(dff_unquoted) {
|
||||||
|
cell (dff1) {
|
||||||
|
area : 1;
|
||||||
|
ff("IQ", "IQN") {
|
||||||
|
next_state : !D;
|
||||||
|
clocked_on : (CLK);
|
||||||
|
}
|
||||||
|
pin(D) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(CLK) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(Q) {
|
||||||
|
direction: output;
|
||||||
|
function : IQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell (dff2) {
|
||||||
|
area : 1;
|
||||||
|
ff(IQ, IQN) {
|
||||||
|
next_state : D';
|
||||||
|
clocked_on : CLK;
|
||||||
|
}
|
||||||
|
pin(D) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(CLK) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(Q) {
|
||||||
|
direction: output;
|
||||||
|
function : "IQ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell (dffe) {
|
||||||
|
area : 6;
|
||||||
|
ff("IQ", "IQN") {
|
||||||
|
next_state : (D&EN) | (IQ&!EN);
|
||||||
|
clocked_on : !CLK;
|
||||||
|
}
|
||||||
|
pin(D) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(EN) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(CLK) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin(Q) {
|
||||||
|
direction: output;
|
||||||
|
function : "IQ";
|
||||||
|
}
|
||||||
|
pin(QN) {
|
||||||
|
direction: output;
|
||||||
|
function : "IQN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
tests/liberty/unquoted.lib.filtered.ok
Normal file
60
tests/liberty/unquoted.lib.filtered.ok
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
library(dff_unquoted) {
|
||||||
|
cell(dff1) {
|
||||||
|
area : 1 ;
|
||||||
|
ff("IQ", "IQN") {
|
||||||
|
next_state : !D ;
|
||||||
|
clocked_on : ( CLK ) ;
|
||||||
|
}
|
||||||
|
pin(D) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(CLK) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(Q) {
|
||||||
|
direction : output ;
|
||||||
|
function : IQ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell(dff2) {
|
||||||
|
area : 1 ;
|
||||||
|
ff(IQ, IQN) {
|
||||||
|
next_state : D ' ;
|
||||||
|
clocked_on : CLK ;
|
||||||
|
}
|
||||||
|
pin(D) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(CLK) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(Q) {
|
||||||
|
direction : output ;
|
||||||
|
function : "IQ" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cell(dffe) {
|
||||||
|
area : 6 ;
|
||||||
|
ff("IQ", "IQN") {
|
||||||
|
next_state : ( D & EN ) | ( IQ & ! EN ) ;
|
||||||
|
clocked_on : !CLK ;
|
||||||
|
}
|
||||||
|
pin(D) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(EN) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(CLK) {
|
||||||
|
direction : input ;
|
||||||
|
}
|
||||||
|
pin(Q) {
|
||||||
|
direction : output ;
|
||||||
|
function : "IQ" ;
|
||||||
|
}
|
||||||
|
pin(QN) {
|
||||||
|
direction : output ;
|
||||||
|
function : "IQN" ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
tests/liberty/unquoted.lib.verilogsim.ok
Normal file
39
tests/liberty/unquoted.lib.verilogsim.ok
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
module dff1 (D, CLK, Q);
|
||||||
|
reg IQ, IQN;
|
||||||
|
input D;
|
||||||
|
input CLK;
|
||||||
|
output Q;
|
||||||
|
assign Q = IQ; // IQ
|
||||||
|
always @(posedge CLK) begin
|
||||||
|
// !D
|
||||||
|
IQ <= (~D);
|
||||||
|
IQN <= ~((~D));
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
module dff2 (D, CLK, Q);
|
||||||
|
reg IQ, IQN;
|
||||||
|
input D;
|
||||||
|
input CLK;
|
||||||
|
output Q;
|
||||||
|
assign Q = IQ; // "IQ"
|
||||||
|
always @(posedge CLK) begin
|
||||||
|
// D '
|
||||||
|
IQ <= (~D);
|
||||||
|
IQN <= ~((~D));
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
module dffe (D, EN, CLK, Q, QN);
|
||||||
|
reg IQ, IQN;
|
||||||
|
input D;
|
||||||
|
input EN;
|
||||||
|
input CLK;
|
||||||
|
output Q;
|
||||||
|
assign Q = IQ; // "IQ"
|
||||||
|
output QN;
|
||||||
|
assign QN = IQN; // "IQN"
|
||||||
|
always @(negedge CLK) begin
|
||||||
|
// ( D & EN ) | ( IQ & ! EN )
|
||||||
|
IQ <= ((D&EN)|(IQ&(~EN)));
|
||||||
|
IQN <= ~(((D&EN)|(IQ&(~EN))));
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
28
tests/pyosys/test_idstring_lifetime.py
Normal file
28
tests/pyosys/test_idstring_lifetime.py
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
from pyosys import libyosys as ys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
__file_dir__ = Path(__file__).absolute().parent
|
||||||
|
|
||||||
|
d = ys.Design()
|
||||||
|
ys.run_pass(f"read_verilog {__file_dir__ / 'spm.cut.v.gz'}", d)
|
||||||
|
ys.run_pass("hierarchy -top spm", d)
|
||||||
|
|
||||||
|
external_idstring_holder_0 = None
|
||||||
|
external_idstring_holder_1 = None
|
||||||
|
|
||||||
|
def get_top_module_idstring():
|
||||||
|
global external_idstring_holder_0, external_idstring_holder_1
|
||||||
|
d = ys.Design()
|
||||||
|
ys.run_pass(f"read_verilog {__file_dir__ / 'spm.cut.v.gz'}", d)
|
||||||
|
ys.run_pass("hierarchy -top spm", d)
|
||||||
|
external_idstring_holder_0 = d.top_module().name
|
||||||
|
for cell in d.top_module().cells_:
|
||||||
|
print(f"TARGETED: {cell}", flush=True)
|
||||||
|
external_idstring_holder_1 = cell
|
||||||
|
break
|
||||||
|
# d deallocates
|
||||||
|
|
||||||
|
get_top_module_idstring()
|
||||||
|
print(external_idstring_holder_0, flush=True)
|
||||||
|
print(external_idstring_holder_1, flush=True)
|
||||||
15
tests/pyosys/test_indirect_inheritance.py
Normal file
15
tests/pyosys/test_indirect_inheritance.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
from pyosys import libyosys as ys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
__file_dir__ = Path(__file__).absolute().parent
|
||||||
|
|
||||||
|
|
||||||
|
d = ys.Design()
|
||||||
|
ys.run_pass(f"read_verilog {__file_dir__ / 'spm.cut.v.gz'}", d)
|
||||||
|
ys.run_pass("hierarchy -top spm", d)
|
||||||
|
|
||||||
|
for idstr, cell in d.top_module().cells_.items():
|
||||||
|
cell.set_bool_attribute("\\set")
|
||||||
|
print(cell.attributes)
|
||||||
|
break
|
||||||
|
|
@ -14,7 +14,7 @@ class Monitor(ys.Monitor):
|
||||||
self.mods.append(mod.name.str())
|
self.mods.append(mod.name.str())
|
||||||
|
|
||||||
m = Monitor()
|
m = Monitor()
|
||||||
d.monitors.add(m)
|
d.monitors = [m]
|
||||||
|
|
||||||
ys.run_pass(f"read_verilog {__file_dir__ / 'spm.cut.v.gz'}", d)
|
ys.run_pass(f"read_verilog {__file_dir__ / 'spm.cut.v.gz'}", d)
|
||||||
ys.run_pass("hierarchy -top spm", d)
|
ys.run_pass("hierarchy -top spm", d)
|
||||||
|
|
|
||||||
33
tests/svinterfaces/positional_args.ys
Normal file
33
tests/svinterfaces/positional_args.ys
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
read_verilog -sv << EOF
|
||||||
|
interface simple_if;
|
||||||
|
logic receiver;
|
||||||
|
logic driver;
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
module driver_mod(simple_if intf, input in);
|
||||||
|
assign intf.driver = in;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module receiver_mod(simple_if intf);
|
||||||
|
assign intf.receiver = intf.driver;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module top(
|
||||||
|
input logic [1:0] inputs,
|
||||||
|
output logic [1:0] outputs
|
||||||
|
);
|
||||||
|
simple_if intf0();
|
||||||
|
simple_if intf1();
|
||||||
|
|
||||||
|
driver_mod d0(intf0, inputs[0]);
|
||||||
|
driver_mod d1(intf1, inputs[1]);
|
||||||
|
|
||||||
|
receiver_mod r0(intf0);
|
||||||
|
receiver_mod r1(intf1);
|
||||||
|
|
||||||
|
assign outputs = {intf0.receiver, intf1.receiver};
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
|
||||||
|
logger -expect error "Unable to connect.* with positional interface" 1
|
||||||
|
hierarchy -top top
|
||||||
|
|
@ -5,3 +5,4 @@
|
||||||
|
|
||||||
./run_simple.sh load_and_derive
|
./run_simple.sh load_and_derive
|
||||||
./run_simple.sh resolve_types
|
./run_simple.sh resolve_types
|
||||||
|
./run_simple.sh positional_args
|
||||||
|
|
|
||||||
26
tests/techmap/abc_state.ys
Normal file
26
tests/techmap/abc_state.ys
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
read_verilog <<EOT
|
||||||
|
module simple(I1, I2, O);
|
||||||
|
input wire I1;
|
||||||
|
input wire I2;
|
||||||
|
output wire O;
|
||||||
|
|
||||||
|
assign O = I1 | I2;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
abc -g all
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog <<EOT
|
||||||
|
module simple(I1, I2, O);
|
||||||
|
input wire I1;
|
||||||
|
input wire I2;
|
||||||
|
output wire O;
|
||||||
|
|
||||||
|
assign O = I1 | I2;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
techmap
|
||||||
|
abc -g AND
|
||||||
|
|
||||||
|
select -assert-count 0 t:$_OR_
|
||||||
|
select -assert-count 1 t:$_AND_
|
||||||
24
tests/techmap/dfflibmap_dff_not_next.lib
Normal file
24
tests/techmap/dfflibmap_dff_not_next.lib
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
library (test_not_next) {
|
||||||
|
cell (dff_not_next) {
|
||||||
|
area: 1.0;
|
||||||
|
pin (QN) {
|
||||||
|
direction : output;
|
||||||
|
function : "STATE";
|
||||||
|
}
|
||||||
|
pin (CLK) {
|
||||||
|
direction : input;
|
||||||
|
clock : true;
|
||||||
|
}
|
||||||
|
pin (D) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
pin (RN) {
|
||||||
|
direction : input;
|
||||||
|
}
|
||||||
|
ff (STATE, STATEN) {
|
||||||
|
clocked_on: "CLK";
|
||||||
|
next_state: "!D";
|
||||||
|
preset : "!RN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -108,6 +108,37 @@ copy top top_unmapped
|
||||||
simplemap top
|
simplemap top
|
||||||
dfflibmap -liberty dfflibmap_dffn_dffe.lib -liberty dfflibmap_dffsr_not_next.lib top
|
dfflibmap -liberty dfflibmap_dffn_dffe.lib -liberty dfflibmap_dffsr_not_next.lib top
|
||||||
|
|
||||||
|
async2sync
|
||||||
|
flatten
|
||||||
|
opt_clean -purge
|
||||||
|
equiv_make top top_unmapped equiv
|
||||||
|
equiv_induct equiv
|
||||||
|
equiv_status -assert equiv
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog <<EOT
|
||||||
|
|
||||||
|
module top(input C, D, R, output Q);
|
||||||
|
// DFF with preset
|
||||||
|
always @(posedge C or negedge R) begin
|
||||||
|
if (!R) Q <= 1'b1;
|
||||||
|
else Q <= D;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc
|
||||||
|
opt
|
||||||
|
read_liberty dfflibmap_dffn_dffe.lib
|
||||||
|
read_liberty dfflibmap_dff_not_next.lib
|
||||||
|
|
||||||
|
copy top top_unmapped
|
||||||
|
simplemap top
|
||||||
|
dfflibmap -liberty dfflibmap_dffn_dffe.lib -liberty dfflibmap_dff_not_next.lib top
|
||||||
|
|
||||||
async2sync
|
async2sync
|
||||||
flatten
|
flatten
|
||||||
opt_clean -purge
|
opt_clean -purge
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o)))
|
||||||
|
|
||||||
all: prepare $(TESTS) run-tests
|
all: prepare $(TESTS) run-tests
|
||||||
|
|
||||||
$(BINTEST)/%: $(OBJTEST)/%.o
|
$(BINTEST)/%: $(OBJTEST)/%.o | prepare
|
||||||
$(CXX) -L$(ROOTPATH) $(RPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \
|
$(CXX) -L$(ROOTPATH) $(RPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \
|
||||||
$(GTEST_LDFLAGS) $(EXTRAFLAGS)
|
$(GTEST_LDFLAGS) $(EXTRAFLAGS)
|
||||||
|
|
||||||
$(OBJTEST)/%.o: $(basename $(subst $(OBJTEST),.,%)).cc
|
$(OBJTEST)/%.o: $(basename $(subst $(OBJTEST),.,%)).cc | prepare
|
||||||
$(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $(GTEST_CXXFLAGS) $^
|
$(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $(GTEST_CXXFLAGS) $^
|
||||||
|
|
||||||
.PHONY: prepare run-tests clean
|
.PHONY: prepare run-tests clean
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace RTLIL {
|
||||||
void checkAll(std::initializer_list<std::string> expressions, std::string expected) {
|
void checkAll(std::initializer_list<std::string> expressions, std::string expected) {
|
||||||
for (const auto& e : expressions) {
|
for (const auto& e : expressions) {
|
||||||
auto helper = LibertyExpression::Lexer(e);
|
auto helper = LibertyExpression::Lexer(e);
|
||||||
auto tree_s = LibertyExpression::parse(helper).str();
|
auto tree_s = LibertyExpression::parse(helper).sexpr_str();
|
||||||
EXPECT_EQ(tree_s, expected);
|
EXPECT_EQ(tree_s, expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +82,11 @@ namespace RTLIL {
|
||||||
}, "(and (pin \"x\")\n"
|
}, "(and (pin \"x\")\n"
|
||||||
" (not (pin \"y\")))"
|
" (not (pin \"y\")))"
|
||||||
);
|
);
|
||||||
|
checkAll({
|
||||||
|
"( D & EN )",
|
||||||
|
}, "(and (pin \"D\")\n"
|
||||||
|
" (pin \"EN\"))"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
tests/various/timeest.ys
Normal file
12
tests/various/timeest.ys
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
read_verilog <<EOF
|
||||||
|
module top(input [3:0] a, input [3:0] b, output [7:0] y);
|
||||||
|
assign y = a * b;
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module top2(input [7:0] a, input [7:0] b, output [15:0] y);
|
||||||
|
assign y = a * b;
|
||||||
|
endmodule
|
||||||
|
EOF
|
||||||
|
|
||||||
|
synth
|
||||||
|
timeest
|
||||||
13
tests/verific/port_bus_order.ys
Normal file
13
tests/verific/port_bus_order.ys
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
verific -sv <<EOT
|
||||||
|
module simple (
|
||||||
|
input [3:0] I2,
|
||||||
|
input [3:0] I1,
|
||||||
|
output [3:0] result
|
||||||
|
);
|
||||||
|
assign result = I2 & I1;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
verific -import simple
|
||||||
|
|
||||||
|
write_verilog verilog_port_bus_order.out
|
||||||
|
!grep -qF 'simple(I2, I1, result)' verilog_port_bus_order.out
|
||||||
2
tests/verilog/.gitignore
vendored
2
tests/verilog/.gitignore
vendored
|
|
@ -4,3 +4,5 @@
|
||||||
/roundtrip_proc_1.v
|
/roundtrip_proc_1.v
|
||||||
/roundtrip_proc_2.v
|
/roundtrip_proc_2.v
|
||||||
/assign_to_reg.v
|
/assign_to_reg.v
|
||||||
|
/subdir
|
||||||
|
/temp_foo.v
|
||||||
|
|
|
||||||
30
tests/verilog/local_include.sh
Executable file
30
tests/verilog/local_include.sh
Executable file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# only works with read_verilog
|
||||||
|
yosys='../../yosys -f verilog'
|
||||||
|
test='-p hierarchy'
|
||||||
|
subdir=subdir
|
||||||
|
source=local_include.v
|
||||||
|
include=temp_foo.v
|
||||||
|
|
||||||
|
# no include file should fail
|
||||||
|
rm -f $include
|
||||||
|
echo "logger -expect error $include 1; read_verilog $source" | $yosys
|
||||||
|
|
||||||
|
# both files local
|
||||||
|
echo 'module foo (input a, output b); assign b = a; endmodule' > $include
|
||||||
|
$yosys $test $source
|
||||||
|
|
||||||
|
# include local to cwd
|
||||||
|
mkdir -p $subdir
|
||||||
|
cp $source $subdir
|
||||||
|
$yosys $test $subdir/$source
|
||||||
|
|
||||||
|
# include local to source
|
||||||
|
mv $include $subdir
|
||||||
|
$yosys $test $subdir/$source
|
||||||
|
|
||||||
|
# include local to source, and source is given as an absolute path
|
||||||
|
$yosys $test $(pwd)/$subdir/$source
|
||||||
4
tests/verilog/local_include.v
Normal file
4
tests/verilog/local_include.v
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
`include "temp_foo.v"
|
||||||
|
module top (input x, output y);
|
||||||
|
foo bar (.a(x), .b(y));
|
||||||
|
endmodule
|
||||||
14
tests/verilog/package_import_specific.sv
Normal file
14
tests/verilog/package_import_specific.sv
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
package package_import_specific;
|
||||||
|
|
||||||
|
localparam integer
|
||||||
|
DATA_WIDTH = 8,
|
||||||
|
ADDR_WIDTH = 4;
|
||||||
|
|
||||||
|
localparam logic [2:0]
|
||||||
|
IDLE = 3'b000,
|
||||||
|
START = 3'b001,
|
||||||
|
DATA = 3'b010,
|
||||||
|
STOP = 3'b100,
|
||||||
|
DONE = 3'b101;
|
||||||
|
|
||||||
|
endpackage
|
||||||
5
tests/verilog/package_import_specific.ys
Normal file
5
tests/verilog/package_import_specific.ys
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
read_verilog -sv package_import_specific.sv
|
||||||
|
read_verilog -sv package_import_specific_module.sv
|
||||||
|
hierarchy -check
|
||||||
|
proc
|
||||||
|
opt -full
|
||||||
16
tests/verilog/package_import_specific_module.sv
Normal file
16
tests/verilog/package_import_specific_module.sv
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import package_import_specific::DATA_WIDTH;
|
||||||
|
import package_import_specific::IDLE;
|
||||||
|
|
||||||
|
module package_import_specific_module;
|
||||||
|
logic [DATA_WIDTH-1:0] data;
|
||||||
|
logic [3:0] addr;
|
||||||
|
logic [2:0] state;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (state)
|
||||||
|
IDLE: data = 8'h00;
|
||||||
|
default: data = 8'hFF;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Add table
Add a link
Reference in a new issue