3
0
Fork 0
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:
Eder Monteiro 2025-11-11 13:07:02 -03:00 committed by GitHub
commit 8ffca44e62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 2635 additions and 1137 deletions

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

@ -55,7 +55,6 @@
# pyosys
/kernel/*.pyh
/kernel/python_wrappers.cc
/boost
/ffi
/bison
/venv

View file

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

View file

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

View file

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

View file

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

@ -1 +1 @@
Subproject commit fa186342baefea06e7c2aa13fe51f338ffc84912
Subproject commit 1c5ed1ce378cc04beac30bb31abc4c37c8467042

View file

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

View file

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

View file

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

View file

@ -1,5 +0,0 @@
ECP5
------------------
.. autocmdgroup:: techlibs/ecp5
:members:

View file

@ -1,5 +0,0 @@
Lattice Nexus
------------------
.. autocmdgroup:: techlibs/nexus
:members:

View file

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

View file

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

View file

@ -1,3 +1,4 @@
furo-ys @ git+https://github.com/YosysHQ/furo-ys
sphinxcontrib-bibtex
rtds-action
sphinx-inline-tabs

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
requires = [
"setuptools>=42",
"pybind11>=3,<4",
"cxxheaderparser",
"cxxheaderparser"
]
build-backend = "setuptools.build_meta"

View file

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

View file

@ -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
View 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 input1/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 selection1/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_SEL1,ciu_clk
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared0,mck_adc_clk_osc1,io_clk
parameter VSEN_CTL = 3'b000; //Input source selection
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection0,VSEN_CTL1,ciu_vsen_ctl
parameter ADC_MODE = 1'b0; //Mode selection
parameter DIV_CTL = 2'd0; //clock division0:/11:/22:/43:/8Clock 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、64other 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_SEL1,ciu_clk
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared0,mck_adc_clk_osc1,io_clk
parameter VSEN_CTL = 3'b000; //Input source selection
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection0,VSEN_CTL1,ciu_vsen_ctl
parameter ADC_MODE = 1'b0; //Mode selection
parameter DIV_CTL = 2'd0; //clock division0:/11:/22:/43:/8Clock 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、64other 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 mode1: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 division0:/11:/22:/43:/8Clock 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、64other 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、64other 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、64other 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

View file

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

View file

@ -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 input1/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 selection1/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_SEL1,ciu_clk
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared0,mck_adc_clk_osc1,io_clk
parameter VSEN_CTL = 3'b000; //Input source selection
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection0,VSEN_CTL1,ciu_vsen_ctl
parameter ADC_MODE = 1'b0; //Mode selection
parameter DIV_CTL = 2'd0; //clock division0:/11:/22:/43:/8Clock 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、64other 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_SEL1,ciu_clk
parameter PIOCLK_SEL = 1'b0; //Clock source selection. 1/2 shared0,mck_adc_clk_osc1,io_clk
parameter VSEN_CTL = 3'b000; //Input source selection
parameter VSEN_CTL_SEL = 1'b0; //vsen_ctl source selection0,VSEN_CTL1,ciu_vsen_ctl
parameter ADC_MODE = 1'b0; //Mode selection
parameter DIV_CTL = 2'd0; //clock division0:/11:/22:/43:/8Clock 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、64other 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 mode1: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 division0:/11:/22:/43:/8Clock 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、64other 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、64other 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、64other 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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

View 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

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

View 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

View file

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

View 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

View file

@ -5,3 +5,4 @@
./run_simple.sh load_and_derive
./run_simple.sh resolve_types
./run_simple.sh positional_args

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

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

View file

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

View file

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

View file

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

View 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

View file

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

View file

@ -0,0 +1,4 @@
`include "temp_foo.v"
module top (input x, output y);
foo bar (.a(x), .b(y));
endmodule

View 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

View 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

View 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