mirror of
https://github.com/YosysHQ/yosys
synced 2026-06-22 08:40:28 +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
|
||||
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:
|
||||
using: composite
|
||||
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'
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
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
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.6.0
|
||||
with:
|
||||
packages: gawk git make python3
|
||||
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
|
||||
if: runner.os == 'macOS'
|
||||
|
|
@ -32,3 +83,9 @@ runs:
|
|||
echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
|
||||
echo "$(brew --prefix flex)/bin" >> $GITHUB_PATH
|
||||
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
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install deps
|
||||
run: sudo apt-get install bison flex libfl-dev libreadline-dev tcl-dev libffi-dev
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-build-env
|
||||
with:
|
||||
runs-on: ubuntu-latest
|
||||
get-build-deps: true
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
|
|
|
|||
4
.github/workflows/extra-builds.yml
vendored
4
.github/workflows/extra-builds.yml
vendored
|
|
@ -73,8 +73,8 @@ jobs:
|
|||
persist-credentials: false
|
||||
- name: Build
|
||||
run: |
|
||||
WASI_SDK=wasi-sdk-19.0
|
||||
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
|
||||
WASI_SDK=wasi-sdk-27.0-x86_64-linux
|
||||
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz
|
||||
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
|
||||
|
||||
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
|
||||
uses: ./.github/actions/setup-build-env
|
||||
with:
|
||||
runs-on: ${{ matrix.os }}
|
||||
get-build-deps: true
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
|
|
@ -105,48 +108,10 @@ jobs:
|
|||
|
||||
- name: Setup environment
|
||||
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:
|
||||
path: .local/
|
||||
key: ${{ matrix.os }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
|
||||
|
||||
- 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
|
||||
runs-on: ${{ matrix.os }}
|
||||
get-test-deps: true
|
||||
get-iverilog: true
|
||||
|
||||
- name: Download build artifact
|
||||
uses: actions/download-artifact@v4
|
||||
|
|
@ -191,6 +156,8 @@ jobs:
|
|||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-build-env
|
||||
with:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
- name: Download build artifact
|
||||
uses: actions/download-artifact@v4
|
||||
|
|
@ -229,6 +196,10 @@ jobs:
|
|||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-build-env
|
||||
with:
|
||||
runs-on: ${{ matrix.os }}
|
||||
get-build-deps: true
|
||||
get-docs-deps: true
|
||||
|
||||
- name: Download build artifact
|
||||
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'
|
||||
include:
|
||||
# macOS x86
|
||||
- os: macos-13
|
||||
- os: macos-15-intel
|
||||
compiler: 'clang-19'
|
||||
# macOS arm
|
||||
- os: macos-latest
|
||||
|
|
@ -60,6 +60,9 @@ jobs:
|
|||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-build-env
|
||||
with:
|
||||
runs-on: ${{ matrix.os }}
|
||||
get-build-deps: true
|
||||
|
||||
- name: Setup Cpp
|
||||
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
|
||||
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:
|
||||
path: .local/
|
||||
key: ${{ matrix.os }}-${{ steps.get-iverilog.outputs.IVERILOG_GIT }}
|
||||
|
||||
- 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: Check iverilog
|
||||
shell: bash
|
||||
run: |
|
||||
iverilog -V
|
||||
runs-on: ${{ matrix.os }}
|
||||
get-build-deps: true
|
||||
get-test-deps: true
|
||||
get-iverilog: true
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
|
|
|
|||
12
.github/workflows/wheels.yml
vendored
12
.github/workflows/wheels.yml
vendored
|
|
@ -25,15 +25,15 @@ jobs:
|
|||
archs: "aarch64",
|
||||
},
|
||||
{
|
||||
name: "macOS 13",
|
||||
name: "macOS 15 x64",
|
||||
family: "macos",
|
||||
runner: "macos-13",
|
||||
runner: "macos-15-intel",
|
||||
archs: "x86_64",
|
||||
},
|
||||
{
|
||||
name: "macOS 14",
|
||||
name: "macOS 15 arm64",
|
||||
family: "macos",
|
||||
runner: "macos-14",
|
||||
runner: "macos-15",
|
||||
archs: "arm64",
|
||||
},
|
||||
## Windows is disabled because of an issue with compiling FFI as
|
||||
|
|
@ -59,7 +59,7 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
mkdir -p ffi
|
||||
curl -L https://github.com/libffi/libffi/releases/download/v3.4.6/libffi-3.4.6.tar.gz | tar --strip-components=1 -xzC ffi
|
||||
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' }}
|
||||
name: "[Linux] Bison 3.8.2"
|
||||
shell: bash
|
||||
|
|
@ -114,7 +114,7 @@ jobs:
|
|||
path: ./wheelhouse/*.whl
|
||||
upload_wheels:
|
||||
name: Upload Wheels
|
||||
if: github.repository == 'YosysHQ/Yosys'
|
||||
if: (github.repository == 'YosysHQ/Yosys') && (github.event_name == 'workflow_dispatch')
|
||||
runs-on: ubuntu-latest
|
||||
# Specifying a GitHub environment is optional, but strongly encouraged
|
||||
environment: pypi
|
||||
|
|
|
|||
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]
|
||||
|
||||
for source in ["boost", "ffi", "bison"]:
|
||||
for source in ["ffi", "bison"]:
|
||||
if not (__yosys_root__ / source).is_dir():
|
||||
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)
|
||||
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -55,7 +55,6 @@
|
|||
# pyosys
|
||||
/kernel/*.pyh
|
||||
/kernel/python_wrappers.cc
|
||||
/boost
|
||||
/ffi
|
||||
/bison
|
||||
/venv
|
||||
|
|
|
|||
2
Brewfile
2
Brewfile
|
|
@ -6,9 +6,9 @@ brew "git"
|
|||
brew "graphviz"
|
||||
brew "pkg-config"
|
||||
brew "python3"
|
||||
brew "uv"
|
||||
brew "xdot"
|
||||
brew "bash"
|
||||
brew "boost-python3"
|
||||
brew "llvm@20"
|
||||
brew "lld"
|
||||
brew "googletest"
|
||||
|
|
|
|||
20
CHANGELOG
20
CHANGELOG
|
|
@ -2,9 +2,27 @@
|
|||
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
|
||||
--------------------------
|
||||
* Various
|
||||
|
|
|
|||
34
Makefile
34
Makefile
|
|
@ -28,6 +28,7 @@ ENABLE_HELP_SOURCE := 0
|
|||
|
||||
# python wrappers
|
||||
ENABLE_PYOSYS := 0
|
||||
PYOSYS_USE_UV := 1
|
||||
|
||||
# other configuration flags
|
||||
ENABLE_GCOV := 0
|
||||
|
|
@ -94,14 +95,14 @@ TARGETS = $(PROGRAM_PREFIX)yosys$(EXE) $(PROGRAM_PREFIX)yosys-config
|
|||
PRETTY = 1
|
||||
SMALL = 0
|
||||
|
||||
# Unit test
|
||||
UNITESTPATH := tests/unit
|
||||
|
||||
all: top-all
|
||||
|
||||
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
|
||||
VPATH := $(YOSYS_SRC)
|
||||
|
||||
# Unit test
|
||||
UNITESTPATH := $(YOSYS_SRC)/tests/unit
|
||||
|
||||
export CXXSTD ?= c++17
|
||||
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include
|
||||
LIBS := $(LIBS) -lstdc++ -lm
|
||||
|
|
@ -160,7 +161,7 @@ ifeq ($(OS), Haiku)
|
|||
CXXFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
|
||||
YOSYS_VER := 0.58+89
|
||||
YOSYS_VER := 0.59+0
|
||||
YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1)
|
||||
YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1)
|
||||
YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)
|
||||
|
|
@ -183,7 +184,7 @@ endif
|
|||
OBJS = kernel/version_$(GIT_REV).o
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -282,12 +283,11 @@ ifeq ($(WASI_SDK),)
|
|||
CXX = clang++
|
||||
AR = llvm-ar
|
||||
RANLIB = llvm-ranlib
|
||||
WASIFLAGS := -target wasm32-wasi --sysroot $(WASI_SYSROOT) $(WASIFLAGS)
|
||||
WASIFLAGS := -target wasm32-wasi $(WASIFLAGS)
|
||||
else
|
||||
CXX = $(WASI_SDK)/bin/clang++
|
||||
AR = $(WASI_SDK)/bin/ar
|
||||
RANLIB = $(WASI_SDK)/bin/ranlib
|
||||
WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS)
|
||||
endif
|
||||
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))
|
||||
|
|
@ -352,16 +352,22 @@ PYTHON_OBJECTS = pyosys/wrappers.o kernel/drivers.o kernel/yosys.o passes/cmds/p
|
|||
|
||||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
# 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))
|
||||
LIBS += $(shell $(PYTHON_CONFIG) --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 += $(shell $(PYTHON_CONFIG) --includes) -DYOSYS_ENABLE_PYTHON
|
||||
|
||||
OBJS += $(PY_WRAPPER_FILE).o
|
||||
PY_GEN_SCRIPT = pyosys/generator.py
|
||||
PY_WRAP_INCLUDES := $(shell $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) --print-includes)
|
||||
PY_GEN_SCRIPT = $(YOSYS_SRC)/pyosys/generator.py
|
||||
PY_WRAP_INCLUDES := $(shell $(UV_ENV) $(PYTHON_EXECUTABLE) $(PY_GEN_SCRIPT) --print-includes)
|
||||
endif # ENABLE_PYOSYS
|
||||
|
||||
ifeq ($(ENABLE_READLINE),1)
|
||||
|
|
@ -777,7 +783,7 @@ endif
|
|||
ifeq ($(ENABLE_PYOSYS),1)
|
||||
$(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT) pyosys/wrappers_tpl.cc $(PY_WRAP_INCLUDES) pyosys/hashlib.h
|
||||
$(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
|
||||
|
||||
%.o: %.cpp
|
||||
|
|
@ -1129,7 +1135,7 @@ DOC_TARGET ?= html
|
|||
docs: docs/prep
|
||||
$(Q) $(MAKE) -C docs $(DOC_TARGET)
|
||||
|
||||
clean: clean-py
|
||||
clean: clean-py clean-unit-test
|
||||
rm -rf share
|
||||
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
|
||||
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/tools/cmp_tbdata
|
||||
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 -f libyosys.so
|
||||
|
||||
|
|
@ -1156,7 +1162,7 @@ clean-py:
|
|||
rm -rf kernel/*.pyh
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
prerequisites for building yosys:
|
||||
|
||||
$ sudo apt-get install 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
|
||||
$ sudo apt-get install gawk git make python3 lld bison clang flex \
|
||||
libffi-dev libfl-dev libreadline-dev pkg-config tcl-dev zlib1g-dev \
|
||||
graphviz xdot
|
||||
$ curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
The environment variable `CXX` can be used to control the C++ compiler used, or
|
||||
run one of the following to override it:
|
||||
|
|
|
|||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
std::string get_hdl_name(T *object)
|
||||
{
|
||||
|
|
@ -2858,7 +2844,7 @@ struct CxxrtlWorker {
|
|||
}
|
||||
|
||||
if (split_intf)
|
||||
f << "#include \"" << basename(intf_filename) << "\"\n";
|
||||
f << "#include \"" << name_from_file_path(intf_filename) << "\"\n";
|
||||
else
|
||||
f << "#include <cxxrtl/cxxrtl.h>\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);
|
||||
} else {
|
||||
f << stringf("{ ");
|
||||
for (const auto& chunk : reversed(sig.chunks())) {
|
||||
auto chunks = sig.chunks();
|
||||
for (const auto& chunk : reversed(chunks)) {
|
||||
dump_sigchunk(f, chunk, false);
|
||||
f << stringf(" ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -382,8 +382,9 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
|
|||
dump_sigchunk(f, sig.as_chunk());
|
||||
} else {
|
||||
f << stringf("{ ");
|
||||
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
|
||||
if (it != sig.chunks().rbegin())
|
||||
auto chunks = sig.chunks();
|
||||
for (auto it = chunks.rbegin(); it != chunks.rend(); ++it) {
|
||||
if (it != chunks.rbegin())
|
||||
f << stringf(", ");
|
||||
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'
|
||||
author = 'YosysHQ GmbH'
|
||||
copyright ='2025 YosysHQ GmbH'
|
||||
yosys_ver = "0.58"
|
||||
yosys_ver = "0.59"
|
||||
|
||||
# select HTML theme
|
||||
html_theme = 'furo-ys'
|
||||
|
|
@ -50,7 +50,7 @@ rst_prolog = """
|
|||
:language: yoscrypt
|
||||
"""
|
||||
|
||||
extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex']
|
||||
extensions = ['sphinx.ext.autosectionlabel', 'sphinxcontrib.bibtex', 'sphinx_inline_tabs']
|
||||
|
||||
if os.getenv("READTHEDOCS"):
|
||||
# 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
|
||||
`show` command to display schematics.
|
||||
|
||||
Installing all prerequisites for Ubuntu 22.04:
|
||||
Installing all prerequisites:
|
||||
|
||||
.. code:: console
|
||||
|
||||
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):
|
||||
.. tab:: Ubuntu 22.04
|
||||
|
||||
.. 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
|
||||
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:
|
||||
|
||||
.. code:: console
|
||||
|
||||
|
||||
make
|
||||
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.
|
||||
|
||||
.. seealso::
|
||||
.. seealso::
|
||||
|
||||
Refer to :doc:`/yosys_internals/extending_yosys/test_suites` for details on
|
||||
testing Yosys once compiled.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
furo-ys @ git+https://github.com/YosysHQ/furo-ys
|
||||
sphinxcontrib-bibtex
|
||||
rtds-action
|
||||
sphinx-inline-tabs
|
||||
|
|
|
|||
|
|
@ -28,6 +28,14 @@ methods:
|
|||
|
||||
``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
|
||||
|
||||
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:
|
||||
|
||||
- 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
|
||||
|
||||
|
|
@ -356,21 +356,29 @@ from SystemVerilog:
|
|||
files being read into the same design afterwards.
|
||||
|
||||
- typedefs are supported (including inside packages)
|
||||
- type casts are currently not supported
|
||||
|
||||
- type casts are currently not supported
|
||||
|
||||
- enums are supported (including inside packages)
|
||||
- but are currently not strongly typed
|
||||
|
||||
- but are currently not strongly typed
|
||||
|
||||
- packed structs and unions are supported
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- multidimensional arrays are supported
|
||||
- array assignment of unpacked arrays is currently not supported
|
||||
- array literals are currently not supported
|
||||
|
||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
||||
ports are inputs or outputs are supported.
|
||||
- array assignment of unpacked arrays is currently not 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,72 @@
|
|||
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
|
||||
-----------------
|
||||
|
|
@ -14,8 +79,6 @@ compiler versions. For up to date information, including OS versions, refer to
|
|||
.. _Yosys Git repo: https://github.com/YosysHQ/yosys
|
||||
.. _the git actions page: https://github.com/YosysHQ/yosys/actions
|
||||
|
||||
.. todo:: are unit tests currently working
|
||||
|
||||
..
|
||||
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.
|
||||
|
||||
- | 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``
|
||||
|
||||
- | All bits of a wire or a selection of bits from a wire
|
||||
| 1em For example: ``mywire, mywire[24], mywire[15:8]``
|
||||
|
||||
- | 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.
|
||||
The ``RTLIL::SigSpec`` data type is used to represent signals.
|
||||
It contains a single ``RTLIL::SigChunk`` or a vector of ``RTLIL::SigBit``.
|
||||
The ``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||
|
||||
In addition, connections between wires are represented using a pair of
|
||||
``RTLIL::SigSpec`` objects. Such pairs are needed in different locations.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
packages.default = yosys;
|
||||
defaultPackage = yosys;
|
||||
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 "frontends/verilog/verilog_frontend.h"
|
||||
#include "ast.h"
|
||||
#include "kernel/io.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdarg.h>
|
||||
|
|
@ -888,6 +889,52 @@ static void check_auto_nosync(AstNode *node)
|
|||
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
|
||||
// values, unrolled for-loops, expanded generate blocks, etc. when this function
|
||||
// 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) {
|
||||
// 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) {
|
||||
if (pkg_child->type == AST_PARAMETER || pkg_child->type == AST_LOCALPARAM ||
|
||||
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);
|
||||
}
|
||||
}
|
||||
importer.import(current_scope, pkg_child.get());
|
||||
}
|
||||
// Remove the import node since it's been processed
|
||||
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;
|
||||
f.open(mem_filename.c_str());
|
||||
if (f.fail()) {
|
||||
#ifdef _WIN32
|
||||
char slash = '\\';
|
||||
#else
|
||||
char slash = '/';
|
||||
#endif
|
||||
std::string path = location.begin.filename->substr(0, location.begin.filename->find_last_of(slash)+1);
|
||||
std::string path = parent_from_file_path(*location.begin.filename);
|
||||
f.open(path + mem_filename.c_str());
|
||||
yosys_input_files.insert(path + mem_filename);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1576,6 +1576,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma
|
|||
SetIter si ;
|
||||
Port *port ;
|
||||
FOREACH_PORT_OF_PORTBUS(portbus, si, port) {
|
||||
wire->port_id = nl->IndexOf(port) + 1;
|
||||
import_attributes(wire->attributes, port->GetNet(), nl, portbus->Size());
|
||||
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
|
||||
// currently read file is given with a path, then try again relative to its directory
|
||||
ff.clear();
|
||||
#ifdef _WIN32
|
||||
fixed_fn = filename.substr(0, filename.find_last_of("/\\")+1) + fn;
|
||||
#else
|
||||
fixed_fn = filename.substr(0, filename.rfind('/')+1) + fn;
|
||||
#endif
|
||||
fixed_fn = parent_from_file_path(filename) + fn;
|
||||
ff.open(fixed_fn);
|
||||
}
|
||||
if (ff.fail() && fn.size() > 0 && fn_relative) {
|
||||
|
|
|
|||
|
|
@ -829,11 +829,31 @@ package_body_stmt:
|
|||
typedef_decl | localparam_decl | param_decl | task_func_decl;
|
||||
|
||||
import_stmt:
|
||||
TOK_IMPORT hierarchical_id TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL {
|
||||
// Create an import node to track package imports
|
||||
TOK_IMPORT TOK_ID TOK_PACKAGESEP TOK_ASTER TOK_SEMICOL {
|
||||
// Create an import node to track wildcard package imports
|
||||
auto import_node = std::make_unique<AstNode>(@$, AST_IMPORT);
|
||||
import_node->str = *$2;
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -1021,7 +1021,7 @@ protected:
|
|||
if (hashtable.empty()) {
|
||||
entries.emplace_back(std::forward<K>(rvalue), -1);
|
||||
do_rehash();
|
||||
hash = do_hash(rvalue);
|
||||
hash = do_hash(entries.back().udata);
|
||||
} else {
|
||||
entries.emplace_back(std::forward<K>(rvalue), hashtable[hash]);
|
||||
hashtable[hash] = entries.size() - 1;
|
||||
|
|
|
|||
19
kernel/io.cc
19
kernel/io.cc
|
|
@ -2,6 +2,7 @@
|
|||
#include "kernel/log.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#if !defined(WIN32)
|
||||
#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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
result.reserve(result.size() + fmt.size());
|
||||
|
|
|
|||
|
|
@ -470,6 +470,8 @@ void remove_directory(std::string dirname);
|
|||
bool create_directory(const std::string& dirname);
|
||||
std::string escape_filename_spaces(const std::string& filename);
|
||||
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
|
||||
|
||||
|
|
|
|||
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) \
|
||||
YOSYS_NAMESPACE_PREFIX IDMacroHelper< \
|
||||
YOSYS_NAMESPACE_PREFIX lookup_well_known_id(#_id) \
|
||||
|
|
@ -1222,9 +1223,10 @@ struct RTLIL::SigSpecConstIterator
|
|||
typedef RTLIL::SigBit& reference;
|
||||
|
||||
const RTLIL::SigSpec *sig_p;
|
||||
RTLIL::SigBit bit;
|
||||
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::SigSpecIterator &other) const { return index == other.index; }
|
||||
inline void operator++() { index++; }
|
||||
|
|
@ -1233,33 +1235,84 @@ struct RTLIL::SigSpecConstIterator
|
|||
struct RTLIL::SigSpec
|
||||
{
|
||||
private:
|
||||
int width_;
|
||||
Hasher::hash_t hash_;
|
||||
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
|
||||
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
|
||||
enum Representation : char {
|
||||
CHUNK,
|
||||
BITS,
|
||||
};
|
||||
// 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;
|
||||
void unpack() const;
|
||||
void updhash() const;
|
||||
std::atomic<Hasher::hash_t> atomic_;
|
||||
};
|
||||
|
||||
inline bool packed() const {
|
||||
return bits_.empty();
|
||||
Representation rep_;
|
||||
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 {
|
||||
if (!chunks_.empty())
|
||||
void unpack();
|
||||
inline void inline_unpack() {
|
||||
if (rep_ == CHUNK)
|
||||
unpack();
|
||||
}
|
||||
void try_repack();
|
||||
|
||||
// Only used by Module::remove(const pool<Wire*> &wires)
|
||||
// but cannot be more specific as it isn't yet declared
|
||||
friend struct RTLIL::Module;
|
||||
Hasher::hash_t updhash() const;
|
||||
void destroy() {
|
||||
if (rep_ == CHUNK)
|
||||
chunk_.~SigChunk();
|
||||
else
|
||||
bits_.~vector();
|
||||
}
|
||||
friend struct Chunks;
|
||||
|
||||
public:
|
||||
SigSpec() : width_(0), hash_(0) {}
|
||||
SigSpec() { init_empty_bits(); }
|
||||
SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
|
||||
SigSpec(const SigSpec &value) = default;
|
||||
SigSpec(SigSpec &&value) = default;
|
||||
SigSpec(const SigSpec &value) : rep_(value.rep_), hash_(value.hash_) {
|
||||
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(RTLIL::Const &&value);
|
||||
SigSpec(const RTLIL::SigChunk &chunk);
|
||||
|
|
@ -1275,24 +1328,138 @@ public:
|
|||
SigSpec(const pool<RTLIL::SigBit> &bits);
|
||||
SigSpec(const std::set<RTLIL::SigBit> &bits);
|
||||
explicit SigSpec(bool bit);
|
||||
~SigSpec() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
SigSpec &operator=(const SigSpec &rhs) = default;
|
||||
SigSpec &operator=(SigSpec &&rhs) = default;
|
||||
SigSpec &operator=(const SigSpec &rhs) {
|
||||
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_; }
|
||||
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }
|
||||
// SigSpec::Chunks holds one reconstructed chunk at a time
|
||||
// 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_; }
|
||||
inline bool empty() const { return width_ == 0; }
|
||||
const SigSpec &spec;
|
||||
int bit_index;
|
||||
SigChunk chunk;
|
||||
|
||||
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); }
|
||||
inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); }
|
||||
const_iterator(const SigSpec &spec) : spec(spec) {
|
||||
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 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 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_and_unify();
|
||||
|
|
@ -1324,10 +1491,14 @@ public:
|
|||
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(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]; };
|
||||
RTLIL::SigBit msb() const { log_assert(width_); return (*this)[width_ - 1]; };
|
||||
void rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite);
|
||||
|
||||
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);
|
||||
inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); }
|
||||
|
|
@ -1350,7 +1521,7 @@ public:
|
|||
|
||||
bool is_wire() 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;
|
||||
|
||||
|
|
@ -1387,6 +1558,9 @@ public:
|
|||
int as_int_saturating(bool is_signed = false) 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::Wire *as_wire() 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_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::SigBit>() const { return bits(); }
|
||||
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
|
||||
operator std::vector<RTLIL::SigChunk>() const;
|
||||
operator std::vector<RTLIL::SigBit>() const { return to_sigbit_vector(); }
|
||||
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
|
||||
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, const RTLIL::Cell *other);
|
||||
|
||||
RTLIL::Memory *addMemory(RTLIL::IdString name);
|
||||
RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other);
|
||||
|
||||
RTLIL::Process *addProcess(RTLIL::IdString name);
|
||||
|
|
@ -2312,13 +2495,15 @@ inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
|
|||
return (*sig_p)[index];
|
||||
}
|
||||
|
||||
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const {
|
||||
return (*sig_p)[index];
|
||||
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() {
|
||||
bit = (*sig_p)[index];
|
||||
return bit;
|
||||
}
|
||||
|
||||
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
|
||||
log_assert(sig.size() == 1 && sig.chunks().size() == 1);
|
||||
*this = SigBit(sig.chunks().front());
|
||||
log_assert(sig.size() == 1);
|
||||
auto it = sig.chunks().begin();
|
||||
*this = SigBit(*it);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -277,14 +277,26 @@ inline int ceil_log2(int x)
|
|||
#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>
|
||||
auto reversed(const T& container) {
|
||||
struct reverse_view {
|
||||
const T& cont;
|
||||
auto begin() const { return cont.rbegin(); }
|
||||
auto end() const { return cont.rend(); }
|
||||
};
|
||||
return reverse_view{container};
|
||||
struct reverse_view {
|
||||
reverse_view(const T& container) : container(container) {}
|
||||
auto begin() const { return container.rbegin(); }
|
||||
auto end() const { return container.rend(); }
|
||||
const T& container;
|
||||
};
|
||||
return reverse_view{container};
|
||||
}
|
||||
|
||||
YOSYS_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -278,11 +278,12 @@ struct ShowWorker
|
|||
std::vector<std::string> label_pieces;
|
||||
int bitpos = sig.size()-1;
|
||||
|
||||
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);
|
||||
RTLIL::SigSpec::Chunks sig_chunks = sig.chunks();
|
||||
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
|
||||
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;
|
||||
cl = c.offset + c.width - 1;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ const arrivalint INF_PAST = std::numeric_limits<arrivalint>::min();
|
|||
struct EstimateSta {
|
||||
SigMap sigmap;
|
||||
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<Cell *, Aig *> cell_aigs;
|
||||
|
|
@ -73,15 +74,18 @@ struct EstimateSta {
|
|||
}
|
||||
|
||||
// TODO: ignores clock polarity
|
||||
EstimateSta(Module *m, SigBit clk)
|
||||
: sigmap(m), m(m), clk(clk)
|
||||
EstimateSta(Module *m, std::optional<SigBit> clk, bool top_port_endpoints)
|
||||
: sigmap(m), m(m), clk(clk), top_port_endpoints(top_port_endpoints)
|
||||
{
|
||||
sigmap.apply(clk);
|
||||
if (clk.has_value())
|
||||
sigmap.apply(*clk);
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
// each toposort node is either a SigBit or a pair of Cell * / AigNode *
|
||||
|
|
@ -360,7 +380,7 @@ struct TimeestPass : Pass {
|
|||
log("\n");
|
||||
log(" timeest [-clk <clk_signal>] [options] [selection]\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(" -all_paths\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");
|
||||
|
||||
std::string clk;
|
||||
std::string clk_name;
|
||||
bool clk_domain_specified = false;
|
||||
bool all_paths = false;
|
||||
bool select = false;
|
||||
size_t argidx;
|
||||
|
|
@ -388,26 +409,30 @@ struct TimeestPass : Pass {
|
|||
continue;
|
||||
}
|
||||
if (args[argidx] == "-clk" && argidx + 1 < args.size()) {
|
||||
clk = args[++argidx];
|
||||
clk_domain_specified = true;
|
||||
clk_name = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, d);
|
||||
|
||||
if (clk.empty())
|
||||
log_cmd_error("No -clk argument provided\n");
|
||||
|
||||
if (select && d->selected_modules().size() > 1)
|
||||
log_cmd_error("The -select option operates on a single selected module\n");
|
||||
|
||||
for (auto m : d->selected_modules()) {
|
||||
if (!m->wire(RTLIL::escape_id(clk))) {
|
||||
log_warning("No domain '%s' in module %s\n", clk, log_id(m));
|
||||
continue;
|
||||
std::optional<SigBit> clk;
|
||||
|
||||
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.select = select;
|
||||
sta.run();
|
||||
|
|
|
|||
|
|
@ -156,6 +156,21 @@ std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
|
|||
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
|
||||
struct IFExpander
|
||||
{
|
||||
|
|
@ -283,15 +298,42 @@ struct IFExpander
|
|||
RTLIL::IdString conn_name,
|
||||
const RTLIL::SigSpec &conn_signals)
|
||||
{
|
||||
// Check if the connection is present as an interface in the sub-module's port list
|
||||
const RTLIL::Wire *wire = submodule.wire(conn_name);
|
||||
if (!wire || !wire->get_bool_attribute(ID::is_interface))
|
||||
// Does the connection look like an interface
|
||||
if (
|
||||
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;
|
||||
|
||||
// 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.
|
||||
const auto &bits = conn_signals;
|
||||
if (bits.size() == 1 && bits[0].wire->get_bool_attribute(ID::is_interface))
|
||||
on_interface(submodule, conn_name, conn_signals);
|
||||
on_interface(submodule, conn_name, conn_signals);
|
||||
}
|
||||
|
||||
// Iterate over the connections in a cell, tracking any interface
|
||||
|
|
@ -376,21 +418,6 @@ RTLIL::Module *get_module(RTLIL::Design &design,
|
|||
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
|
||||
// on the type: each named connection should match the name of a port
|
||||
// and each positional connection should have an index smaller than
|
||||
|
|
|
|||
|
|
@ -117,15 +117,6 @@ struct gate_t
|
|||
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
|
||||
{
|
||||
std::string global_tempdir_name;
|
||||
|
|
@ -146,6 +137,12 @@ struct AbcConfig
|
|||
bool show_tempdir = false;
|
||||
bool sop_mode = 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 {
|
||||
|
|
@ -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));
|
||||
fclose(f);
|
||||
} 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());
|
||||
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 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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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_)));
|
||||
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));
|
||||
if (mapped_mod == nullptr)
|
||||
log_error("ABC output file does not contain a module `netlist'.\n");
|
||||
bool markgroups = run_abc.config.markgroups;
|
||||
for (auto w : mapped_mod->wires()) {
|
||||
RTLIL::Wire *orig_wire = nullptr;
|
||||
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);
|
||||
luts_arg = design->scratchpad_get_string("abc.luts", luts_arg);
|
||||
config.sop_mode = design->scratchpad_get_bool("abc.sop", false);
|
||||
map_mux4 = design->scratchpad_get_bool("abc.mux4", map_mux4);
|
||||
map_mux8 = design->scratchpad_get_bool("abc.mux8", map_mux8);
|
||||
map_mux16 = design->scratchpad_get_bool("abc.mux16", map_mux16);
|
||||
config.map_mux4 = design->scratchpad_get_bool("abc.mux4", false);
|
||||
config.map_mux8 = design->scratchpad_get_bool("abc.mux8", false);
|
||||
config.map_mux16 = design->scratchpad_get_bool("abc.mux16", false);
|
||||
config.abc_dress = design->scratchpad_get_bool("abc.dress", false);
|
||||
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.cleanup = !design->scratchpad_get_bool("abc.nocleanup", 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)
|
||||
config.global_tempdir_name = get_base_tmpdir() + "/";
|
||||
|
|
@ -2094,15 +2092,15 @@ struct AbcPass : public Pass {
|
|||
continue;
|
||||
}
|
||||
if (arg == "-mux4") {
|
||||
map_mux4 = true;
|
||||
config.map_mux4 = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-mux8") {
|
||||
map_mux8 = true;
|
||||
config.map_mux8 = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-mux16") {
|
||||
map_mux16 = true;
|
||||
config.map_mux16 = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-dress") {
|
||||
|
|
@ -2143,7 +2141,7 @@ struct AbcPass : public Pass {
|
|||
continue;
|
||||
}
|
||||
if (arg == "-markgroups") {
|
||||
markgroups = true;
|
||||
config.markgroups = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
|
@ -2236,14 +2234,14 @@ struct AbcPass : public Pass {
|
|||
}
|
||||
if (g == "cmos2") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
config.cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
goto ok_alias;
|
||||
}
|
||||
if (g == "cmos3") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
config.cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
gate_list.push_back("AOI3");
|
||||
|
|
@ -2252,7 +2250,7 @@ struct AbcPass : public Pass {
|
|||
}
|
||||
if (g == "cmos4") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
config.cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
gate_list.push_back("AOI3");
|
||||
|
|
@ -2263,7 +2261,7 @@ struct AbcPass : public Pass {
|
|||
}
|
||||
if (g == "cmos") {
|
||||
if (!remove_gates)
|
||||
cmos_cost = true;
|
||||
config.cmos_cost = true;
|
||||
gate_list.push_back("NAND");
|
||||
gate_list.push_back("NOR");
|
||||
gate_list.push_back("AOI3");
|
||||
|
|
@ -2322,9 +2320,9 @@ struct AbcPass : public Pass {
|
|||
ok_alias:
|
||||
for (auto gate : gate_list) {
|
||||
if (remove_gates)
|
||||
enabled_gates.erase(gate);
|
||||
config.enabled_gates.erase(gate);
|
||||
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()))
|
||||
log_cmd_error("Got -constr but no -liberty/-genlib!\n");
|
||||
|
||||
if (enabled_gates.empty()) {
|
||||
enabled_gates.insert("AND");
|
||||
enabled_gates.insert("NAND");
|
||||
enabled_gates.insert("OR");
|
||||
enabled_gates.insert("NOR");
|
||||
enabled_gates.insert("XOR");
|
||||
enabled_gates.insert("XNOR");
|
||||
enabled_gates.insert("ANDNOT");
|
||||
enabled_gates.insert("ORNOT");
|
||||
// enabled_gates.insert("AOI3");
|
||||
// enabled_gates.insert("OAI3");
|
||||
// enabled_gates.insert("AOI4");
|
||||
// enabled_gates.insert("OAI4");
|
||||
enabled_gates.insert("MUX");
|
||||
// enabled_gates.insert("NMUX");
|
||||
if (config.enabled_gates.empty()) {
|
||||
config.enabled_gates.insert("AND");
|
||||
config.enabled_gates.insert("NAND");
|
||||
config.enabled_gates.insert("OR");
|
||||
config.enabled_gates.insert("NOR");
|
||||
config.enabled_gates.insert("XOR");
|
||||
config.enabled_gates.insert("XNOR");
|
||||
config.enabled_gates.insert("ANDNOT");
|
||||
config.enabled_gates.insert("ORNOT");
|
||||
// config.enabled_gates.insert("AOI3");
|
||||
// config.enabled_gates.insert("OAI3");
|
||||
// config.enabled_gates.insert("AOI4");
|
||||
// config.enabled_gates.insert("OAI4");
|
||||
config.enabled_gates.insert("MUX");
|
||||
// config.enabled_gates.insert("NMUX");
|
||||
}
|
||||
|
||||
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
|
||||
for (auto conn : mapped_mod->connections()) {
|
||||
if (!conn.first.is_fully_const()) {
|
||||
auto chunks = conn.first.chunks();
|
||||
std::vector<RTLIL::SigChunk> chunks = conn.first.chunks();
|
||||
for (auto &c : chunks)
|
||||
c.wire = module->wires_.at(remap_name(c.wire->name));
|
||||
conn.first = std::move(chunks);
|
||||
}
|
||||
if (!conn.second.is_fully_const()) {
|
||||
auto chunks = conn.second.chunks();
|
||||
std::vector<RTLIL::SigChunk> chunks = conn.second.chunks();
|
||||
for (auto &c : chunks)
|
||||
if (c.wire)
|
||||
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;
|
||||
}
|
||||
|
||||
auto pin_names = pool<std::string>{};
|
||||
auto pin_names = std::unordered_set<std::string>{};
|
||||
tree.get_pin_names(pin_names);
|
||||
|
||||
// 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());
|
||||
int lut = 0;
|
||||
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[1], (n & 2) == 2));
|
||||
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;
|
||||
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;
|
||||
|
||||
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 (!parse_pin(cell, ff->find("clear"), cell_rst_pin, cell_rst_pol) || cell_rst_pol != rstpol)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -25,9 +25,22 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#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"
|
||||
void warn(std::string str) {
|
||||
Yosys::log_formatted_warning("", str);
|
||||
}
|
||||
#endif
|
||||
|
||||
using namespace Yosys;
|
||||
|
|
@ -110,7 +123,9 @@ int LibertyInputStream::peek_cold(size_t offset)
|
|||
if (!extend_buffer_at_least(offset + 1))
|
||||
return EOF;
|
||||
}
|
||||
|
||||
#ifdef log_assert
|
||||
log_assert(buf_pos + offset < buffer.size());
|
||||
#endif
|
||||
return buffer[buf_pos + offset];
|
||||
}
|
||||
|
||||
|
|
@ -162,13 +177,15 @@ void LibertyAst::dump(FILE *f, sieve &blacklist, sieve &whitelist, std::string i
|
|||
fprintf(f, " ;\n");
|
||||
}
|
||||
|
||||
#ifndef FILTERLIB
|
||||
|
||||
// binary operators excluding ' '
|
||||
bool LibertyExpression::is_nice_binop(char c) {
|
||||
bool LibertyExpression::char_is_nice_binop(char 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
|
||||
LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
||||
if (s.empty())
|
||||
|
|
@ -177,7 +194,7 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
char c = s.peek();
|
||||
auto lhs = LibertyExpression{};
|
||||
|
||||
while (isspace(c)) {
|
||||
while (isspace(c) || c == '"') {
|
||||
if (s.empty())
|
||||
return lhs;
|
||||
s.next();
|
||||
|
|
@ -191,7 +208,9 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
s.next();
|
||||
lhs = parse(s);
|
||||
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;
|
||||
}
|
||||
s.next();
|
||||
|
|
@ -200,10 +219,11 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
lhs.kind = Kind::NOT;
|
||||
lhs.children.push_back(parse(s, 7));
|
||||
} 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;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (s.empty())
|
||||
break;
|
||||
|
|
@ -246,9 +266,10 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
s.next();
|
||||
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
|
||||
// and we just discard it as meaningless whitespace
|
||||
// Tail operators also imply this isn't an AND
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -286,7 +307,7 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) {
|
|||
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) {
|
||||
names.insert(name);
|
||||
} 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;
|
||||
switch (kind) {
|
||||
case Kind::AND:
|
||||
|
|
@ -324,7 +345,7 @@ bool LibertyExpression::eval(dict<std::string, bool>& values) {
|
|||
return false;
|
||||
}
|
||||
|
||||
std::string LibertyExpression::str(int indent)
|
||||
std::string LibertyExpression::sexpr_str(int indent)
|
||||
{
|
||||
std::string prefix;
|
||||
switch (kind) {
|
||||
|
|
@ -355,16 +376,55 @@ std::string LibertyExpression::str(int indent)
|
|||
if (!first) {
|
||||
prefix += "\n" + std::string(indent + add_indent, ' ');
|
||||
}
|
||||
prefix += child.str(indent + add_indent);
|
||||
prefix += child.sexpr_str(indent + add_indent);
|
||||
first = false;
|
||||
}
|
||||
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;
|
||||
|
||||
|
|
@ -390,11 +450,9 @@ int LibertyParser::lexer(std::string &str)
|
|||
|
||||
if (str == "+" || str == "-") {
|
||||
/* Single operator is not an identifier */
|
||||
// fprintf(stderr, "LEX: char >>%s<<\n", str.c_str());
|
||||
return str[0];
|
||||
}
|
||||
else {
|
||||
// fprintf(stderr, "LEX: identifier >>%s<<\n", str.c_str());
|
||||
return 'v';
|
||||
}
|
||||
}
|
||||
|
|
@ -406,20 +464,19 @@ int LibertyParser::lexer(std::string &str)
|
|||
while (true) {
|
||||
c = f.peek(i);
|
||||
line += (c == '\n');
|
||||
if (c != '"')
|
||||
if (c != '"' && c != EOF)
|
||||
i += 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
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);
|
||||
f.consume(i + 1);
|
||||
// Usage in filterlib is expected to retain quotes
|
||||
// but yosys expects to get unquoted
|
||||
#ifdef FILTERLIB
|
||||
str = "\"" + str + "\"";
|
||||
#endif
|
||||
f.consume(i + 1);
|
||||
return 'v';
|
||||
}
|
||||
|
||||
|
|
@ -442,13 +499,12 @@ int LibertyParser::lexer(std::string &str)
|
|||
return lexer(str);
|
||||
}
|
||||
f.unget();
|
||||
// fprintf(stderr, "LEX: char >>/<<\n");
|
||||
return '/'; // a single '/' charater.
|
||||
}
|
||||
|
||||
// check for a backslash
|
||||
if (c == '\\') {
|
||||
c = f.get();
|
||||
c = f.get();
|
||||
if (c == '\r')
|
||||
c = f.get();
|
||||
if (c == '\n') {
|
||||
|
|
@ -467,14 +523,22 @@ int LibertyParser::lexer(std::string &str)
|
|||
|
||||
// anything else, such as ';' will get passed
|
||||
// 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
std::string str;
|
||||
|
|
@ -591,7 +674,14 @@ LibertyAst *LibertyParser::parse(bool top_level)
|
|||
if (tok == '[') {
|
||||
parse_vector_range(tok);
|
||||
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 == '!') {
|
||||
ast->value += tok;
|
||||
|
|
@ -601,7 +691,7 @@ LibertyAst *LibertyParser::parse(bool top_level)
|
|||
ast->value += str;
|
||||
tok = lexer(str);
|
||||
}
|
||||
|
||||
|
||||
// In a liberty file, all key : value pairs should end in ';'
|
||||
// However, there are some liberty files in the wild that
|
||||
// just have a newline. We'll be kind and accept a newline
|
||||
|
|
@ -621,11 +711,11 @@ LibertyAst *LibertyParser::parse(bool top_level)
|
|||
continue;
|
||||
if (tok == ')')
|
||||
break;
|
||||
|
||||
|
||||
if (tok == '[')
|
||||
{
|
||||
parse_vector_range(tok);
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
if (tok == 'n')
|
||||
continue;
|
||||
|
|
@ -727,42 +817,13 @@ const LibertyAst *find_non_null(const LibertyAst *node, const char *name)
|
|||
|
||||
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")) {
|
||||
char c_left = pos > 0 ? str[pos-1] : ' ';
|
||||
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] = '|';
|
||||
}
|
||||
auto helper = LibertyExpression::Lexer(str);
|
||||
return LibertyExpression::parse(helper).vlog_str();
|
||||
}
|
||||
|
||||
std::string vlog_identifier(std::string str)
|
||||
{
|
||||
str.erase(std::remove(str.begin(), str.end(), '\"'), str.end());
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
@ -772,11 +833,13 @@ void event2vl(const LibertyAst *ast, std::string &edge, std::string &expr)
|
|||
expr.clear();
|
||||
|
||||
if (ast != NULL) {
|
||||
expr = func2vl(ast->value);
|
||||
if (expr.size() > 0 && expr[0] == '~')
|
||||
edge = "negedge " + expr.substr(1);
|
||||
auto helper = LibertyExpression::Lexer(ast->value);
|
||||
auto parsed = LibertyExpression::parse(helper);
|
||||
expr = parsed.vlog_str();
|
||||
if (parsed.kind == LibertyExpression::Kind::NOT)
|
||||
edge = "negedge " + parsed.children[0].vlog_str();
|
||||
else
|
||||
edge = "posedge " + expr;
|
||||
edge = "posedge " + parsed.vlog_str();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -806,13 +869,13 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
|||
return;
|
||||
|
||||
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;
|
||||
for (auto child : ast->children) {
|
||||
if (child->id != "pin")
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
printf(");\n");
|
||||
|
|
@ -823,7 +886,7 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
|||
printf(" reg ");
|
||||
first = true;
|
||||
for (auto arg : child->args) {
|
||||
printf("%s%s", first ? "" : ", ", arg.c_str());
|
||||
printf("%s%s", first ? "" : ", ", vlog_identifier(arg).c_str());
|
||||
first = false;
|
||||
}
|
||||
printf(";\n");
|
||||
|
|
@ -835,9 +898,10 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
|||
CHECK_NV(child->args.size(), == 1);
|
||||
const LibertyAst *dir = find_non_null(child, "direction");
|
||||
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)
|
||||
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)
|
||||
|
|
@ -845,8 +909,8 @@ void gen_verilogsim_cell(const LibertyAst *ast)
|
|||
if (child->id != "ff" || child->args.size() != 2)
|
||||
continue;
|
||||
|
||||
std::string iq_var = child->args[0];
|
||||
std::string iqn_var = child->args[1];
|
||||
std::string iq_var = vlog_identifier(child->args[0]);
|
||||
std::string iqn_var = vlog_identifier(child->args[1]);
|
||||
|
||||
std::string 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)
|
||||
continue;
|
||||
|
||||
std::string iq_var = child->args[0];
|
||||
std::string iqn_var = child->args[1];
|
||||
std::string iq_var = vlog_identifier(child->args[0]);
|
||||
std::string iqn_var = vlog_identifier(child->args[1]);
|
||||
|
||||
std::string enable_edge, enable_expr;
|
||||
event2vl(child->find("enable"), enable_edge, enable_expr);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace Yosys
|
|||
}
|
||||
|
||||
std::string pin() {
|
||||
auto length = s.find_first_of("\t()'!^*& +|");
|
||||
auto length = s.find_first_of("\t()'!^*& +|\"");
|
||||
if (length == std::string::npos) {
|
||||
// nothing found so use size of s
|
||||
length = s.size();
|
||||
|
|
@ -91,11 +91,13 @@ namespace Yosys
|
|||
LibertyExpression() : kind(Kind::EMPTY) {}
|
||||
|
||||
static LibertyExpression parse(Lexer &s, int min_prio = 0);
|
||||
void get_pin_names(pool<std::string>& names);
|
||||
bool eval(dict<std::string, bool>& values);
|
||||
std::string str(int indent = 0);
|
||||
void get_pin_names(std::unordered_set<std::string>& names);
|
||||
bool eval(std::unordered_map<std::string, bool>& values);
|
||||
std::string sexpr_str(int indent = 0);
|
||||
std::string vlog_str();
|
||||
private:
|
||||
static bool is_nice_binop(char c);
|
||||
static bool char_is_nice_binop(char c);
|
||||
bool is_binop();
|
||||
};
|
||||
|
||||
class LibertyInputStream {
|
||||
|
|
@ -170,10 +172,12 @@ namespace Yosys
|
|||
'n': newline
|
||||
anything else is a single character.
|
||||
*/
|
||||
int lexer_inner(std::string &str);
|
||||
int lexer(std::string &str);
|
||||
|
||||
void report_unexpected_token(int tok);
|
||||
void parse_vector_range(int tok);
|
||||
int consume_wrecked_str(int tok, std::string& out_str);
|
||||
LibertyAst *parse(bool top_level);
|
||||
void error() const;
|
||||
void error(const std::string &str) const;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ from cxxheaderparser.types import (
|
|||
Variable,
|
||||
Array,
|
||||
FundamentalSpecifier,
|
||||
FunctionType,
|
||||
)
|
||||
|
||||
__file_dir__ = Path(__file__).absolute().parent
|
||||
|
|
@ -177,11 +178,11 @@ pyosys_headers = [
|
|||
denylist=frozenset({"bits", "bitvectorize"}),
|
||||
),
|
||||
PyosysClass("AttrObject", denylist=frozenset({"get_blackbox_attribute"})),
|
||||
PyosysClass("NamedObject", denylist=frozenset({"get_blackbox_attribute"})),
|
||||
PyosysClass("NamedObject"),
|
||||
PyosysClass("Selection"),
|
||||
# PyosysClass("Monitor"), # Virtual methods, manually bridged
|
||||
PyosysClass("CaseRule", denylist=frozenset({"get_blackbox_attribute"})),
|
||||
PyosysClass("SwitchRule", denylist=frozenset({"get_blackbox_attribute"})),
|
||||
PyosysClass("CaseRule"),
|
||||
PyosysClass("SwitchRule"),
|
||||
PyosysClass("SyncRule"),
|
||||
PyosysClass(
|
||||
"Process",
|
||||
|
|
@ -191,7 +192,7 @@ pyosys_headers = [
|
|||
),
|
||||
PyosysClass("SigChunk"),
|
||||
PyosysClass("SigBit", hash_expr="s"),
|
||||
PyosysClass("SigSpec", hash_expr="s"),
|
||||
PyosysClass("SigSpec", hash_expr="s", denylist={"chunks"}),
|
||||
PyosysClass(
|
||||
"Cell",
|
||||
ref_only=True,
|
||||
|
|
@ -219,7 +220,7 @@ pyosys_headers = [
|
|||
),
|
||||
PyosysClass(
|
||||
"Design",
|
||||
string_expr="s.hashidx_",
|
||||
string_expr="std::to_string(s.hashidx_)",
|
||||
hash_expr="s",
|
||||
denylist=frozenset({"selected_whole_modules"}), # deprecated
|
||||
),
|
||||
|
|
@ -241,13 +242,17 @@ class PyosysType:
|
|||
|
||||
@classmethod
|
||||
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):
|
||||
ptr_to = Self.from_type(type_obj.ptr_to)
|
||||
return Self("ptr", (ptr_to,), const)
|
||||
elif isinstance(type_obj, Reference):
|
||||
ref_to = Self.from_type(type_obj.ref_to)
|
||||
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(
|
||||
type_obj, Type
|
||||
), f"unexpected c++ type object of type {type(type_obj)}"
|
||||
|
|
@ -270,6 +275,16 @@ class PyosysType:
|
|||
if title == "Dict":
|
||||
key, value = self.specialization
|
||||
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 (
|
||||
"".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()} *"
|
||||
elif self.base == "ref":
|
||||
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:
|
||||
return (
|
||||
const_prefix
|
||||
|
|
@ -301,7 +319,7 @@ class PyosysWrapperGenerator(object):
|
|||
self.f = wrapper_stream
|
||||
self.f_inc = header_stream
|
||||
self.found_containers: Dict[PyosysType, Any] = {}
|
||||
self.class_registry: Dict[str, ClassScope] = {}
|
||||
self.class_registry: Dict[str, Tuple[ClassScope, PyosysClass]] = {}
|
||||
|
||||
# entry point
|
||||
def generate(self):
|
||||
|
|
@ -380,7 +398,7 @@ class PyosysWrapperGenerator(object):
|
|||
if isinstance(type_info, Reference):
|
||||
return PyosysWrapperGenerator.find_containers(containers, type_info.ref_to)
|
||||
if not isinstance(type_info, Type):
|
||||
return ()
|
||||
return {}
|
||||
segments = type_info.typename.segments
|
||||
containers_found = {}
|
||||
for segment in segments:
|
||||
|
|
@ -411,19 +429,23 @@ class PyosysWrapperGenerator(object):
|
|||
def get_parameter_types(function: Function) -> str:
|
||||
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")
|
||||
found = False
|
||||
if isinstance(target, Function):
|
||||
self.found_containers.update(
|
||||
self.find_containers(supported, target.return_type)
|
||||
)
|
||||
return_type_containers = 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:
|
||||
self.found_containers.update(
|
||||
self.find_containers(supported, parameter.type)
|
||||
)
|
||||
parameter_containers = self.find_containers(supported, parameter.type)
|
||||
found = found or len(parameter_containers)
|
||||
self.found_containers.update(parameter_containers)
|
||||
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
|
||||
def get_overload_cast(
|
||||
|
|
@ -470,9 +492,9 @@ class PyosysWrapperGenerator(object):
|
|||
|
||||
def_args = [f'"{python_function_basename}"']
|
||||
def_args.append(self.get_overload_cast(function, class_basename))
|
||||
for parameter in function.parameters:
|
||||
# ASSUMPTION: there are no unnamed parameters in the yosys codebase
|
||||
parameter_arg = f'py::arg("{parameter.name}")'
|
||||
for i, parameter in enumerate(function.parameters):
|
||||
name = parameter.name or f"arg{i}"
|
||||
parameter_arg = f'py::arg("{name}")'
|
||||
if parameter.default is not None:
|
||||
parameter_arg += f" = {parameter.default.format()}"
|
||||
def_args.append(parameter_arg)
|
||||
|
|
@ -525,8 +547,12 @@ class PyosysWrapperGenerator(object):
|
|||
if function.static:
|
||||
definition_fn = "def_static"
|
||||
|
||||
definition_args = self.get_definition_args(
|
||||
function, metadata.name, python_name_override
|
||||
)
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
|
|
@ -565,7 +591,7 @@ class PyosysWrapperGenerator(object):
|
|||
# care
|
||||
return
|
||||
|
||||
self.register_containers(field)
|
||||
has_containers = self.register_containers(field)
|
||||
|
||||
definition_fn = f"def_{'readonly' if field.type.const else 'readwrite'}"
|
||||
if field.static:
|
||||
|
|
@ -573,8 +599,13 @@ class PyosysWrapperGenerator(object):
|
|||
|
||||
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(
|
||||
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,
|
||||
)
|
||||
|
||||
|
|
@ -603,16 +634,20 @@ class PyosysWrapperGenerator(object):
|
|||
)
|
||||
|
||||
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:
|
||||
if method.name.segments[-1].name in metadata.denylist:
|
||||
if method.name.segments[-1].name in base_metadata.denylist:
|
||||
continue
|
||||
self.process_method(metadata, method)
|
||||
|
||||
visited_anonymous_unions = set()
|
||||
for field_ in cls.fields:
|
||||
if field_.name in metadata.denylist:
|
||||
if field_.name in base_metadata.denylist:
|
||||
continue
|
||||
self.process_field(metadata, field_)
|
||||
|
||||
|
|
@ -627,6 +662,16 @@ class PyosysWrapperGenerator(object):
|
|||
for subfield in subclass.fields:
|
||||
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(
|
||||
self,
|
||||
metadata: PyosysClass,
|
||||
|
|
@ -638,7 +683,7 @@ class PyosysWrapperGenerator(object):
|
|||
segment.format() for segment in pqname.segments
|
||||
]
|
||||
basename = full_path.pop()
|
||||
self.class_registry[basename] = cls
|
||||
self.class_registry[basename] = (cls, metadata)
|
||||
|
||||
declaration_namespace = "::".join(full_path)
|
||||
tpl_args = [basename]
|
||||
|
|
@ -649,19 +694,17 @@ class PyosysWrapperGenerator(object):
|
|||
file=self.f,
|
||||
)
|
||||
|
||||
self.process_class_members(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)
|
||||
self.process_class_members(metadata, metadata, cls, basename)
|
||||
|
||||
if expr := metadata.string_expr:
|
||||
print(
|
||||
f'\t\t.def("__str__", [](const {basename} &s) {{ return {expr}; }})',
|
||||
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:
|
||||
print(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@
|
|||
// <!-- generated includes -->
|
||||
#include <pybind11/pybind11.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"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
|
@ -28,7 +34,7 @@ namespace py = pybind11;
|
|||
USING_YOSYS_NAMESPACE
|
||||
|
||||
using std::set;
|
||||
using std::regex;
|
||||
using std::function;
|
||||
using std::ostream;
|
||||
using namespace RTLIL;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
requires = [
|
||||
"setuptools>=42",
|
||||
"pybind11>=3,<4",
|
||||
"cxxheaderparser",
|
||||
"cxxheaderparser"
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -51,6 +51,7 @@ class libyosys_so_ext(Extension):
|
|||
"ENABLE_TCL=0",
|
||||
"ENABLE_READLINE=0",
|
||||
"ENABLE_EDITLINE=0",
|
||||
"PYOSYS_USE_UV=0", # + install requires takes its role when building wheels
|
||||
# Always compile and include ABC in wheel
|
||||
"ABCEXTERNAL=",
|
||||
# Show compile commands
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
OBJS += techlibs/gatemate/synth_gatemate.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/mux_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_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',
|
||||
'TLVDS_OEN_BK', 'DLL', 'DCC', 'I3C', 'IODELAYA', 'IODELAYC', 'IODELAYB',
|
||||
'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):
|
||||
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('\n')
|
||||
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;
|
||||
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 (...);
|
||||
parameter STAGE_NUM = 2'b00;
|
||||
parameter ENCDEC_NUM = 2'b00;
|
||||
|
|
@ -2575,3 +2492,266 @@ parameter RD_PNTR = 3'b000;
|
|||
parameter DQS_MODE = "X1";
|
||||
parameter HWL = "false";
|
||||
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 A;
|
||||
output Y;
|
||||
assign Y = !(B&!A|!B&A); // "!(B&!A|!B&A)"
|
||||
assign Y = (~((B&(~A))|((~B)&A))); // "!(B&!A|!B&A)"
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ library(dff) {
|
|||
area : 1;
|
||||
ff("IQ", "IQN") {
|
||||
next_state : "(D)";
|
||||
clocked_on : "CLK";
|
||||
clocked_on : (CLK);
|
||||
}
|
||||
pin(D) {
|
||||
direction : input;
|
||||
|
|
@ -15,7 +15,7 @@ library(dff) {
|
|||
}
|
||||
pin(Q) {
|
||||
direction: output;
|
||||
function : "IQ";
|
||||
function : IQ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ library(dff) {
|
|||
area : 1 ;
|
||||
ff("IQ", "IQN") {
|
||||
next_state : "(D)" ;
|
||||
clocked_on : "CLK" ;
|
||||
clocked_on : ( CLK ) ;
|
||||
}
|
||||
pin(D) {
|
||||
direction : input ;
|
||||
|
|
@ -13,7 +13,7 @@ library(dff) {
|
|||
}
|
||||
pin(Q) {
|
||||
direction : output ;
|
||||
function : "IQ" ;
|
||||
function : IQ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
module dff (D, CLK, Q);
|
||||
reg "IQ", "IQN";
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input CLK;
|
||||
output Q;
|
||||
assign Q = IQ; // "IQ"
|
||||
assign Q = IQ; // IQ
|
||||
always @(posedge CLK) begin
|
||||
// "(D)"
|
||||
"IQ" <= (D);
|
||||
"IQN" <= ~((D));
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
module inv (A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = ~A; // "A'"
|
||||
assign Y = (~A); // "A'"
|
||||
endmodule
|
||||
module tri_inv (A, S, Z);
|
||||
input A;
|
||||
input S;
|
||||
output Z;
|
||||
assign Z = ~A; // "A'"
|
||||
assign Z = (~A); // "A'"
|
||||
endmodule
|
||||
module buffer (A, Y);
|
||||
input A;
|
||||
|
|
@ -18,29 +18,29 @@ module nand2 (A, B, Y);
|
|||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = ~(A&B); // "(A * B)'"
|
||||
assign Y = (~(A&B)); // "(A * B)'"
|
||||
endmodule
|
||||
module nor2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = ~(A|B); // "(A + B)'"
|
||||
assign Y = (~(A|B)); // "(A + B)'"
|
||||
endmodule
|
||||
module xor2 (A, B, Y);
|
||||
input A;
|
||||
input B;
|
||||
output Y;
|
||||
assign Y = (A&~B)|(~A&B); // "(A *B') + (A' * B)"
|
||||
assign Y = ((A&(~B))|((~A)&B)); // "(A *B') + (A' * B)"
|
||||
endmodule
|
||||
module imux2 (A, B, S, Y);
|
||||
input A;
|
||||
input B;
|
||||
input S;
|
||||
output Y;
|
||||
assign Y = ~(&(A&S)|(B&~S)&); // "( (A * S) + (B * S') )'"
|
||||
assign Y = (~((A&S)|(B&(~S)))); // "( (A * S) + (B * S') )'"
|
||||
endmodule
|
||||
module dff (D, CLK, RESET, PRESET, Q, QN);
|
||||
reg "IQ", "IQN";
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input CLK;
|
||||
input RESET;
|
||||
|
|
@ -51,26 +51,26 @@ module dff (D, CLK, RESET, PRESET, Q, QN);
|
|||
assign QN = IQN; // "IQN"
|
||||
always @(posedge CLK, posedge RESET, posedge PRESET) begin
|
||||
if ((RESET) && (PRESET)) begin
|
||||
"IQ" <= 0;
|
||||
"IQN" <= 0;
|
||||
IQ <= 0;
|
||||
IQN <= 0;
|
||||
end
|
||||
else if (RESET) begin
|
||||
"IQ" <= 0;
|
||||
"IQN" <= 1;
|
||||
IQ <= 0;
|
||||
IQN <= 1;
|
||||
end
|
||||
else if (PRESET) begin
|
||||
"IQ" <= 1;
|
||||
"IQN" <= 0;
|
||||
IQ <= 1;
|
||||
IQN <= 0;
|
||||
end
|
||||
else begin
|
||||
// "D"
|
||||
"IQ" <= D;
|
||||
"IQN" <= ~(D);
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
module latch (D, G, Q, QN);
|
||||
reg "IQ", "IQN";
|
||||
reg IQ, IQN;
|
||||
input D;
|
||||
input G;
|
||||
output Q;
|
||||
|
|
@ -79,8 +79,8 @@ module latch (D, G, Q, QN);
|
|||
assign QN = IQN; // "IQN"
|
||||
always @* begin
|
||||
if (G) begin
|
||||
"IQ" <= D;
|
||||
"IQN" <= ~(D);
|
||||
IQ <= D;
|
||||
IQN <= ~(D);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -89,14 +89,14 @@ module aoi211 (A, B, C, Y);
|
|||
input B;
|
||||
input C;
|
||||
output Y;
|
||||
assign Y = ~((A&B)|C); // "((A * B) + C)'"
|
||||
assign Y = (~((A&B)|C)); // "((A * B) + C)'"
|
||||
endmodule
|
||||
module oai211 (A, B, C, Y);
|
||||
input A;
|
||||
input B;
|
||||
input C;
|
||||
output Y;
|
||||
assign Y = ~((A|B)&C); // "((A + B) * C)'"
|
||||
assign Y = (~((A|B)&C)); // "((A + B) * C)'"
|
||||
endmodule
|
||||
module halfadder (A, B, C, Y);
|
||||
input A;
|
||||
|
|
@ -104,7 +104,7 @@ module halfadder (A, B, C, Y);
|
|||
output C;
|
||||
assign C = (A&B); // "(A * B)"
|
||||
output Y;
|
||||
assign Y = (A&~B)|(~A&B); // "(A *B') + (A' * B)"
|
||||
assign Y = ((A&(~B))|((~A)&B)); // "(A *B') + (A' * B)"
|
||||
endmodule
|
||||
module fulladder (A, B, CI, CO, Y);
|
||||
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())
|
||||
|
||||
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("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 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
|
||||
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
|
||||
flatten
|
||||
opt_clean -purge
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o)))
|
|||
|
||||
all: prepare $(TESTS) run-tests
|
||||
|
||||
$(BINTEST)/%: $(OBJTEST)/%.o
|
||||
$(BINTEST)/%: $(OBJTEST)/%.o | prepare
|
||||
$(CXX) -L$(ROOTPATH) $(RPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \
|
||||
$(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) $^
|
||||
|
||||
.PHONY: prepare run-tests clean
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace RTLIL {
|
|||
void checkAll(std::initializer_list<std::string> expressions, std::string expected) {
|
||||
for (const auto& e : expressions) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -82,6 +82,11 @@ namespace RTLIL {
|
|||
}, "(and (pin \"x\")\n"
|
||||
" (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_2.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