Merge remote-tracking branch 'origin/master' into github-action-optimizations

This commit is contained in:
Ashton Snelgrove 2020-12-22 11:37:39 -07:00
commit b29fca6bfa
1174 changed files with 326 additions and 195312 deletions

33
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,33 @@
---
name: Pull request
about: Push a change to this project
---
### Motivate of the pull request
- [ ] To address an existing issue. If so, please provide a link to the issue.
- [ ] Breaking new feature. If so, please decribe details in the description part.
### Describe the technical details
- What is currently done? (Provide issue link if applicable)
- What does this pull request change?
### Which part of the code base require a change
**In general, modification on existing submodules are not acceptable. You should push changes to upstream.**
- [ ] VPR
- [ ] OpenFPGA libraries
- [ ] FPGA-Verilog
- [ ] FPGA-Bitstream
- [ ] FPGA-SDC
- [ ] FPGA-SPICE
- [ ] Flow scripts
- [ ] Architecture library
- [ ] Cell library
### Checklist of the pull request
- [ ] Require code changes.
- [ ] Require new tests to be added
- [ ] Require an update on documentation
### Impact of the pull request
- [ ] Require a change on Quality of Results (QoR)
- [ ] Break back-compatibility. If so, please list who may be influenced.

View File

@ -0,0 +1,33 @@
---
name: Pull request
about: Push a change to this project
---
### Motivate of the pull request
- [ ] To address an existing issue. If so, please provide a link to the issue.
- [ ] Breaking new feature. If so, please decribe details in the description part.
### Describe the technical details
- What is currently done? (Provide issue link if applicable)
- What does this pull request change?
### Which part of the code base require a change
**In general, modification on existing submodules are not acceptable. You should push changes to upstream.**
- [ ] VPR
- [ ] OpenFPGA libraries
- [ ] FPGA-Verilog
- [ ] FPGA-Bitstream
- [ ] FPGA-SDC
- [ ] FPGA-SPICE
- [ ] Flow scripts
- [ ] Architecture library
- [ ] Cell library
### Checklist of the pull request
- [ ] Require code changes.
- [ ] Require new tests to be added
- [ ] Require an update on documentation
### Impact of the pull request
- [ ] Require a change on Quality of Results (QoR)
- [ ] Break back-compatibility. If so, please list who may be influenced.

103
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,103 @@
# See https://github.com/actions/labeler#common-examples for defining patterns.
# The globs use "minimatch" syntax found at https://github.com/isaacs/minimatch
#
# WARNING: Due to this file being yaml, any string starting with `*` must be
# wrapped in quotes.
# Third-party tools
ABC:
- abc/*
- abc/**/*
ACE2:
- ace2/*
- ace2/**/*
VPR:
- vpr/*
- vpr/**/*
- libs/**/*
# General areas
documentation:
- docs/*
- docs/**/*
- "*README*"
- "*.md"
- tutorial
- "*.rst"
- ".readthedocs.yml"
github:
- .github/*
- .github/**/*
docker:
- Dockerfile
- "*docker*"
build:
- Makefile
- "*.make"
- CMakeLists.txt
- cmake
libopenfpga:
- "libopenfpga/**"
libopenfpga-bitstream:
- "libopenfpga/libfpgabitstream/**"
libopenfpga-arch-parser:
- "libopenfpga/libarchopenfpga/**"
libopenfpga-fabric-key:
- "libopenfpga/libfabrickey/**"
libopenfpga-shell:
- "libopenfpga/libopenfpgashell/**"
libopenfpga-utils:
- "libopenfpga/libopenfpgautil/**"
openfpga-tools:
- "openfpga/**"
openfpga-verilog:
- "openfpga/*/fpga_verilog/**"
openfpga-sdc:
- "openfpga/*/fpga_sdc/**"
openfpga-bitstream:
- "openfpga/*/fpga_bitstream/**"
openfpga-spice:
- "openfpga/*/fpga_spice/**"
flow-scripts:
- "openfpga_flow/scripts/**"
- "openfpga_flow/openfpga_shell_scripts/**"
- "openfpga_flow/openfpga_simulation_settings/**"
- "openfpga_flow/misc/**"
architecture-description:
- "openfpga_flow/vpr_arch/**"
- "openfpga_flow/openfpga_arch/**"
- "openfpga_flow/fabric_keys/**"
bitstream:
- "openfpga_flow/fabric_keys/**"
cell-library:
- "openfpga_flow/openfpga_cell_library/**"
- "openfpga_flow/tech/**"
benchmarks:
- "openfpga_flow/benchmarks/**"
tests:
- "openfpga_flow/tasks/**"
# Tag pull requests with the languages used to make it easy to see what is
# being used.
lang-hdl:
- "*.v"
- "*.sv"
lang-cpp:
- "*.c*"
- "*.h"
lang-perl:
- "*.pl"
- "*perl*"
lang-python:
- "*.py"
lang-shell:
- "*.sh"
lang-netlist:
- "*.blif"
- "*.eblif"
- "*.edif"
- "*.vqm"
lang-make:
- "*.make"
- Makefile
- CMakeLists.txt

View File

@ -61,6 +61,8 @@ jobs:
steps:
- name: Checkout OpenFPGA repo
uses: actions/checkout@v2
with:
submodules: true
- name: Dump tool versions
run: |

53
.github/workflows/install_dependency.sh vendored Normal file
View File

@ -0,0 +1,53 @@
# Install all the dependency for OpenFPGA in Ubuntu-18.04
sudo apt-get update
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install bash
sudo apt-get install bison
sudo apt-get install build-essential
sudo apt-get install cmake
sudo apt-get install ccache
sudo apt-get install ctags
sudo apt-get install curl
sudo apt-get install doxygen
sudo apt-get install flex
sudo apt-get install fontconfig
sudo apt-get install gdb
sudo apt-get install git
sudo apt-get install gperf
sudo apt-get install iverilog
sudo apt-get install libcairo2-dev
sudo apt-get install libevent-dev
sudo apt-get install libfontconfig1-dev
sudo apt-get install liblist-moreutils-perl
sudo apt-get install libncurses5-dev
sudo apt-get install libx11-dev
sudo apt-get install libxft-dev
sudo apt-get install libxml++2.6-dev
sudo apt-get install perl
sudo apt-get install python
sudo apt-get install python3-setuptools
sudo apt-get install python-lxml
sudo apt-get install tcllib
sudo apt-get install tcl8.6-dev
sudo apt-get install texinfo
sudo apt-get install time
sudo apt-get install valgrind
sudo apt-get install zip
sudo apt-get install qt5-default
sudo apt-get install clang-format-7
# Add all the supported compilers
sudo apt-get install g++-5
sudo apt-get install gcc-5
sudo apt-get install g++-6
sudo apt-get install gcc-6
sudo apt-get install g++-7
sudo apt-get install gcc-7
sudo apt-get install g++-8
sudo apt-get install gcc-8
sudo apt-get install g++-9
sudo apt-get install gcc-9
sudo apt-get install clang-6.0
sudo apt-get install clang-8
# Python dependencies
python3 -m pip install -r /home/runner/work/OpenFPGA/OpenFPGA/requirements.txt

12
.github/workflows/labeler.yml vendored Normal file
View File

@ -0,0 +1,12 @@
name: "Pull Request Labeler"
on:
- pull_request_target
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
configuration-path: ".github/labeler.yml"

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "yosys"]
path = yosys
url = https://github.com/QuickLogic-Corp/yosys.git
branch = quicklogic-rebased

View File

@ -185,12 +185,60 @@ endif()
#add_subdirectory(iverilog)
add_subdirectory(libs)
add_subdirectory(libopenfpga)
add_subdirectory(yosys)
#add_subdirectory(yosys)
add_subdirectory(abc)
add_subdirectory(ace2)
add_subdirectory(vpr)
add_subdirectory(openfpga)
# yosys compilation starts
# Compilation options for yosys
include(CMakeParseArguments)
##project(yosys)
# Options to enable/disable dependencies
option(YOSYS_ENABLE_TCL, "Enable TCL parser integrated in yosys" ON)
option(YOSYS_ENABLE_ABC, "Enable ABC library integrated in yosys" ON)
option(YOSYS_ENABLE_PLUGINS, "Enable plug-in in yosys" ON)
option(YOSYS_ENABLE_READLINE, "Enable readline library in yosys" ON)
option(YOSYS_ENABLE_VERIFIC, "Enable verification library in yosys" OFF)
option(YOSYS_ENABLE_COVER, "Enable coverage test in yosys" ON)
option(YOSYS_ENABLE_LIBYOSYS, "Enable static library compiled yosys" OFF)
option(YOSYS_ENABLE_GPROF, "Enable profiling in compiled yosys" OFF)
option(YOSYS_ENABLE_NDEBUG, "Enable non-debugging feature in compiled yosys" OFF)
#
## Search and link dependent packages
## We need readline to compile
if (YOSYS_ENABLE_READLINE)
find_package(Readline REQUIRED)
endif()
#
#########################
## #
## Compiler Flags Setup #
## #
#########################
#
## Compiler flag configuration checks
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
#
# run makefile provided, we pass-on the options to the local make file
add_custom_target(
yosys ALL
COMMAND $(MAKE) config-gcc
COMMAND $(MAKE)
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/yosys
COMMENT "Compile Yosys with given Makefile"
)
# yosys compilation ends
# run make to extract compiler options, linker options and list of source files
#add_custom_target(
# yosys

32
Makefile Normal file
View File

@ -0,0 +1,32 @@
# Makefile
ifeq ($(origin CMAKE_COMMAND),undefined)
CMAKE_COMMAND := cmake
else
CMAKE_COMMAND := ${CMAKE_COMMAND}
endif
.PHONY: all checkout compile
all: checkout
mkdir -p build && cd build && $(CMAKE_COMMAND) ${CMAKE_FLAGS} ..
cd build && $(MAKE)
checkout:
git submodule init
git submodule update --init --recursive
compile:
mkdir -p build && cd build && $(CMAKE_COMMAND) ${CMAKE_FLAGS} ..
cd build && $(MAKE)
clean:
rm -rf build
build/Makefile:
make checkout
.PHONY: Makefile
%: build/Makefile
cd build && $(MAKE) $@

View File

@ -6,7 +6,7 @@
The award-winning OpenFPGA framework is the **first open-source FPGA IP generator** supporting highly-customizable homogeneous FPGA architectures. OpenFPGA provides a full set of EDA support for customized FPGAs, including Verilog-to-bitstream generation and self-testing verification. OpenFPGA opens the door to democratizing FPGA technology and EDA techniques, with agile prototyping approaches and constantly evolving EDA tools for chip designers and researchers.
A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/tools.html).
A quick overview of OpenFPGA tools can be found [**here**](https://openfpga.readthedocs.io/en/master/tutorials/tools/).
We also recommend potential users to checkout the summary of [**technical capabilities**](https://openfpga.readthedocs.io/en/master/overview/tech_highlights.html) before compiling.
## Compilation
@ -21,9 +21,7 @@ It also includes detailed information about docker image.
```bash
# Clone the repository and go inside it
git clone https://github.com/LNIS-Projects/OpenFPGA.git && cd OpenFPGA
mkdir build && cd build # Create a folder named build in the OpenPFGA repository
cmake .. # Create a Makefile in this folder using cmake
make # Compile the tool and its dependencies
make all
```
---

View File

@ -6,7 +6,7 @@
#recommonmark
#Handle references in bibtex format
sphinxcontrib-bibtex
sphinxcontrib-bibtex<2.0.0
#Work-around bug "AttributeError: 'Values' object has no attribute 'character_level_inline_markup'" with docutils 0.13.1
#See:

View File

@ -12,10 +12,7 @@ In general, please follow the steps to compile
git clone https://github.com/LNIS-Projects/OpenFPGA.git
cd OpenFPGA
mkdir build
cd build
cmake ..
make
make all
.. note:: OpenFPGA requires gcc/g++ version >5

1
yosys Submodule

@ -0,0 +1 @@
Subproject commit aec2c41441bffa981092095d25655e80dae6ef06

View File

@ -1,13 +0,0 @@
# Default Linux style
BasedOnStyle: LLVM
IndentWidth: 8
UseTab: Always
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
# From CodingReadme
TabWidth: 8
ContinuationIndentWidth: 2
ColumnLimit: 150
# BreakBeforeBraces: Linux

View File

@ -1,13 +0,0 @@
.editorconfig
.gitignore
.gitmodules
.github
.git
Dockerfile
README.md
manual
CodingReadme
CodeOfConduct
.travis
.travis.yml

View File

@ -1,7 +0,0 @@
root = true
[*]
indent_style = tab
indent_size = tab
trim_trailing_whitespace = true
insert_final_newline = true

View File

@ -1,24 +0,0 @@
## Steps to reproduce the issue
*Provide instructions for reproducing the issue. Make sure to include
all necessary source files. (You can simply drag&drop a .zip file into
the issue editor.)*
Also, make sure that the issue is actually reproducable in current git
master of Yosys.
See https://stackoverflow.com/help/mcve for some information on how to
create a Minimal, Complete, and Verifiable example (MCVE).
Please do not waste our time with issues that lack sufficient information
to reproduce the issue easily. We will simply close those issues.
Contact https://www.symbioticeda.com/ if you need commercial support for Yosys.
## Expected behavior
*Please describe the behavior you would have expected from the tool.*
## Actual behavior
*Please describe how the behavior you see differs from the expected behavior.*

42
yosys/.gitignore vendored
View File

@ -1,42 +0,0 @@
*.o
*.d
.*.swp
*.gch
*.gcda
*.gcno
__pycache__
/.cproject
/.project
/.settings
/qtcreator.files
/qtcreator.includes
/qtcreator.config
/qtcreator.creator
/qtcreator.creator.user
/coverage.info
/coverage_html
/Makefile.conf
/abc
/viz.js
/yosys
/yosys.exe
/yosys.js
/yosys-abc
/yosys-abc.exe
/yosys-config
/yosys-smtbmc
/yosys-smtbmc.exe
/yosys-smtbmc-script.py
/yosys-filterlib
/yosys-filterlib.exe
/kernel/*.pyh
/kernel/python_wrappers.cc
/kernel/version_*.cc
/share
/yosys-win32-mxebin-*
/yosys-win32-vcxsrc-*
/yosysjs-*
/libyosys.so
/tests/unit/bintest/
/tests/unit/objtest/
/tests/ystests

View File

@ -1,140 +0,0 @@
sudo: false
language: cpp
cache:
ccache: true
directories:
- ~/.local-bin
env:
global:
- MAKEFLAGS="-j 2"
matrix:
include:
# Latest gcc-4.8, earliest version supported by Travis
- os: linux
addons:
apt:
packages:
- g++-4.8
- gperf
- build-essential
- bison
- flex
- libreadline-dev
- gawk
- tcl-dev
- libffi-dev
- git
- graphviz
- xdot
- pkg-config
- python
- python3
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
# Latest gcc supported on Travis Linux
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-9
- gperf
- build-essential
- bison
- flex
- libreadline-dev
- gawk
- tcl-dev
- libffi-dev
- git
- graphviz
- xdot
- pkg-config
- python
- python3
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
env:
- MATRIX_EVAL="CONFIG=gcc && CC=gcc-9 && CXX=g++-9"
# Clang which ships on Trusty Linux
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages:
- clang-3.8
- gperf
- build-essential
- bison
- flex
- libreadline-dev
- gawk
- tcl-dev
- libffi-dev
- git
- graphviz
- xdot
- pkg-config
- python
- python3
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8"
# Latest clang supported by Travis Linux
- os: linux
addons:
apt:
sources:
- llvm-toolchain-xenial-8
packages:
- clang-8
- gperf
- build-essential
- bison
- flex
- libreadline-dev
- gawk
- tcl-dev
- libffi-dev
- git
- graphviz
- xdot
- pkg-config
- python
- python3
- libboost-system-dev
- libboost-python-dev
- libboost-filesystem-dev
env:
- MATRIX_EVAL="CONFIG=clang && CC=clang-8 && CXX=clang++-8"
# # Latest clang on Mac OS X
# - os: osx
# osx_image: xcode9.4
# env:
# - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
before_install:
- ./.travis/setup.sh
script:
- ./.travis/build-and-test.sh
after_success:
- ./.travis/deploy-after-success.sh

View File

@ -1,51 +0,0 @@
#! /bin/bash
set -e
source .travis/common.sh
##########################################################################
echo
echo 'Configuring...' && echo -en 'travis_fold:start:script.configure\\r'
echo
if [ "$CONFIG" = "gcc" ]; then
echo "Configuring for gcc."
make config-gcc
elif [ "$CONFIG" = "clang" ]; then
echo "Configuring for clang."
make config-clang
fi
echo
echo -en 'travis_fold:end:script.configure\\r'
echo
##########################################################################
echo
echo 'Building...' && echo -en 'travis_fold:start:script.build\\r'
echo
make
echo
echo -en 'travis_fold:end:script.build\\r'
echo
##########################################################################
./yosys tests/simple/fiedler-cooley.v
echo
echo 'Testing...' && echo -en 'travis_fold:start:script.test\\r'
echo
make test
echo
echo -en 'travis_fold:end:script.test\\r'
echo
##########################################################################

View File

@ -1,15 +0,0 @@
#! /bin/bash
# Setup the CC / CXX from the matrix config
eval "${MATRIX_EVAL}"
# Look for location binaries first
export PATH="$HOME/.local-bin/bin:$PATH"
# OS X specific common setup
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
export PATH="/usr/local/opt/ccache/libexec:$PATH"
fi
# Parallel builds!
MAKEFLAGS="-j 2"

View File

@ -1,6 +0,0 @@
#! /bin/bash
set -x
set -e
# FIXME: Upload the build results somewhere...

View File

@ -1,63 +0,0 @@
#! /bin/bash
set -e
source .travis/common.sh
##########################################################################
# Output status information.
(
set +e
set -x
git status
git branch -v
git log -n 5 --graph
git log --format=oneline -n 20 --graph
)
echo
echo -en 'travis_fold:end:before_install.git\\r'
echo
##########################################################################
# Mac OS X specific setup.
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
(
echo
echo 'Setting up brew...' && echo -en 'travis_fold:start:before_install.brew\\r'
echo
brew update
brew tap Homebrew/bundle
brew bundle
brew install ccache
echo
echo -en 'travis_fold:end:before_install.brew\\r'
echo
)
fi
##########################################################################
# Install iverilog
(
if [ ! -e ~/.local-bin/bin/iverilog ]; then
echo
echo 'Building iverilog...' && echo -en 'travis_fold:start:before_install.iverilog\\r'
echo
mkdir -p ~/.local-src
mkdir -p ~/.local-bin
cd ~/.local-src
git clone git://github.com/steveicarus/iverilog.git
cd iverilog
autoconf
CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin
make
make install
echo
echo -en 'travis_fold:end:before_install.iverilog\\r'
echo
fi
)
##########################################################################

View File

@ -1,9 +0,0 @@
brew "bison"
brew "flex"
brew "gawk"
brew "libffi"
brew "git"
brew "graphviz"
brew "pkg-config"
brew "python3"
brew "tcl-tk"

View File

@ -1,729 +0,0 @@
List of major changes and improvements between releases
=======================================================
Yosys 0.8 .. Yosys 0.9
--------------------------
* Various
- Many bugfixes and small improvements
- Added support for SystemVerilog interfaces and modports
- Added "write_edif -attrprop"
- Added "opt_lut" pass
- Added "gate2lut.v" techmap rule
- Added "rename -src"
- Added "equiv_opt" pass
- Added "flowmap" LUT mapping pass
- Added "rename -wire" to rename cells based on the wires they drive
- Added "bugpoint" for creating minimised testcases
- Added "write_edif -gndvccy"
- "write_verilog" to escape Verilog keywords
- Fixed sign handling of real constants
- "write_verilog" to write initial statement for initial flop state
- Added pmgen pattern matcher generator
- Fixed opt_rmdff handling of $_DFFSR_???_ and $_DLATCHSR_???_
- Added "setundef -params" to replace undefined cell parameters
- Renamed "yosys -D" to "yosys -U", added "yosys -D" to set Verilog defines
- Fixed handling of defparam when default_nettype is none
- Fixed "wreduce" flipflop handling
- Fixed FIRRTL to Verilog process instance subfield assignment
- Added "write_verilog -siminit"
- Several fixes and improvements for mem2reg memories
- Fixed handling of task output ports in clocked always blocks
- Improved handling of and-with-1 and or-with-0 in "opt_expr"
- Added "read_aiger" frontend
- Added "mutate" pass
- Added "hdlname" attribute
- Added "rename -output"
- Added "read_ilang -lib"
- Improved "proc" full_case detection and handling
- Added "whitebox" and "lib_whitebox" attributes
- Added "read_verilog -nowb", "flatten -wb" and "wbflip"
- Added Python bindings and support for Python plug-ins
- Added "pmux2shiftx"
- Added log_debug framework for reduced default verbosity
- Improved "opt_expr" and "opt_clean" handling of (partially) undriven and/or unused wires
- Added "peepopt" peephole optimisation pass using pmgen
- Added approximate support for SystemVerilog "var" keyword
- Added parsing of "specify" blocks into $specrule and $specify[23]
- Added support for attributes on parameters and localparams
- Added support for parsing attributes on port connections
- Added "wreduce -keepdc"
- Added support for optimising $dffe and $_DFFE_* cells in "opt_rmdff"
- Added Verilog wand/wor wire type support
- Added support for elaboration system tasks
- Added "muxcover -mux{4,8,16}=<cost>"
- Added "muxcover -dmux=<cost>"
- Added "muxcover -nopartial"
- Added "muxpack" pass
- Added "pmux2shiftx -norange"
- Added support for "~" in filename parsing
- Added "read_verilog -pwires" feature to turn parameters into wires
- Fixed sign extension of unsized constants with 'bx and 'bz MSB
- Fixed genvar to be a signed type
- Added support for attributes on case rules
- Added "upto" and "offset" to JSON frontend and backend
- Several liberty file parser improvements
- Fixed handling of more complex BRAM patterns
- Add "write_aiger -I -O -B"
* Formal Verification
- Added $changed support to read_verilog
- Added "read_verilog -noassert -noassume -assert-assumes"
- Added btor ops for $mul, $div, $mod and $concat
- Added yosys-smtbmc support for btor witnesses
- Added "supercover" pass
- Fixed $global_clock handling vs autowire
- Added $dffsr support to "async2sync"
- Added "fmcombine" pass
- Added memory init support in "write_btor"
- Added "cutpoint" pass
- Changed "ne" to "neq" in btor2 output
- Added support for SVA "final" keyword
- Added "fmcombine -initeq -anyeq"
- Added timescale and generated-by header to yosys-smtbmc vcd output
- Improved BTOR2 handling of undriven wires
* Verific support
- Enabled Verific flags vhdl_support_variable_slice and veri_elaborate_top_level_modules_having_interface_ports
- Improved support for asymmetric memories
- Added "verific -chparam"
- Fixed "verific -extnets" for more complex situations
- Added "read -verific" and "read -noverific"
- Added "hierarchy -chparam"
* New back-ends
- Added initial Anlogic support
- Added initial SmartFusion2 and IGLOO2 support
* ECP5 support
- Added "synth_ecp5 -nowidelut"
- Added BRAM inference support to "synth_ecp5"
- Added support for transforming Diamond IO and flipflop primitives
* iCE40 support
- Added "ice40_unlut" pass
- Added "synth_ice40 -relut"
- Added "synth_ice40 -noabc"
- Added "synth_ice40 -dffe_min_ce_use"
- Added DSP inference support using pmgen
- Added support for initialising BRAM primitives from a file
- Added iCE40 Ultra RGB LED driver cells
* Xilinx support
- Use "write_edif -pvector bra" for Xilinx EDIF files
- Fixes for VPR place and route support with "synth_xilinx"
- Added more cell simulation models
- Added "synth_xilinx -family"
- Added "stat -tech xilinx" to estimate logic cell usage
- Added "synth_xilinx -nocarry"
- Added "synth_xilinx -nowidelut"
- "synth_xilinx" to now infer hard shift registers (-nosrl to disable)
- Added support for mapping RAM32X1D
Yosys 0.7 .. Yosys 0.8
----------------------
* Various
- Many bugfixes and small improvements
- Strip debug symbols from installed binary
- Replace -ignore_redef with -[no]overwrite in front-ends
- Added write_verilog hex dump support, add -nohex option
- Added "write_verilog -decimal"
- Added "scc -set_attr"
- Added "verilog_defines" command
- Remember defines from one read_verilog to next
- Added support for hierarchical defparam
- Added FIRRTL back-end
- Improved ABC default scripts
- Added "design -reset-vlog"
- Added "yosys -W regex", "yosys -w regex", and "yosys -e regex"
- Added Verilog $rtoi and $itor support
- Added "check -initdrv"
- Added "read_blif -wideports"
- Added support for SystemVerilog "++" and "--" operators
- Added support for SystemVerilog unique, unique0, and priority case
- Added "write_edif" options for edif "flavors"
- Added support for resetall compiler directive
- Added simple C beck-end (bitwise combinatorical only atm)
- Added $_ANDNOT_ and $_ORNOT_ cell types
- Added cell library aliases to "abc -g"
- Added "setundef -anyseq"
- Added "chtype" command
- Added "design -import"
- Added "write_table" command
- Added "read_json" command
- Added "sim" command
- Added "extract_fa" and "extract_reduce" commands
- Added "extract_counter" command
- Added "opt_demorgan" command
- Added support for $size and $bits SystemVerilog functions
- Added "blackbox" command
- Added "ltp" command
- Added support for editline as replacement for readline
- Added warnings for driver-driver conflicts between FFs (and other cells) and constants
- Added "yosys -E" for creating Makefile dependencies files
- Added "synth -noshare"
- Added "memory_nordff"
- Added "setundef -undef -expose -anyconst"
- Added "expose -input"
- Added specify/specparam parser support (simply ignore them)
- Added "write_blif -inames -iattr"
- Added "hierarchy -simcheck"
- Added an option to statically link abc into yosys
- Added protobuf back-end
- Added BLIF parsing support for .conn and .cname
- Added read_verilog error checking for reg/wire/logic misuse
- Added "make coverage" and ENABLE_GCOV build option
* Changes in Yosys APIs
- Added ConstEval defaultval feature
- Added {get,set}_src_attribute() methods on RTLIL::AttrObject
- Added SigSpec::is_fully_ones() and Const::is_fully_ones()
- Added log_file_warning() and log_file_error() functions
* Formal Verification
- Added "write_aiger"
- Added "yosys-smtbmc --aig"
- Added "always <positive_int>" to .smtc format
- Added $cover cell type and support for cover properties
- Added $fair/$live cell type and support for liveness properties
- Added smtbmc support for memory vcd dumping
- Added "chformal" command
- Added "write_smt2 -stbv" and "write_smt2 -stdt"
- Fix equiv_simple, old behavior now available with "equiv_simple -short"
- Change to Yices2 as default SMT solver (it is GPL now)
- Added "yosys-smtbmc --presat" (now default in SymbiYosys)
- Added "yosys-smtbmc --smtc-init --smtc-top --noinit"
- Added a brand new "write_btor" command for BTOR2
- Added clk2fflogic memory support and other improvements
- Added "async memory write" support to write_smt2
- Simulate clock toggling in yosys-smtbmc VCD output
- Added $allseq/$allconst cells for EA-solving
- Make -nordff the default in "prep"
- Added (* gclk *) attribute
- Added "async2sync" pass for single-clock designs with async resets
* Verific support
- Many improvements in Verific front-end
- Added proper handling of concurent SVA properties
- Map "const" and "rand const" to $anyseq/$anyconst
- Added "verific -import -flatten" and "verific -import -extnets"
- Added "verific -vlog-incdir -vlog-define -vlog-libdir"
- Remove PSL support (because PSL has been removed in upstream Verific)
- Improve integration with "hierarchy" command design elaboration
- Added YOSYS_NOVERIFIC for running non-verific test cases with verific bin
- Added simpilied "read" command that automatically uses verific if available
- Added "verific -set-<severity> <msg_id>.."
- Added "verific -work <libname>"
* New back-ends
- Added initial Coolrunner-II support
- Added initial eASIC support
- Added initial ECP5 support
* GreenPAK Support
- Added support for GP_DLATCH, GP_SPI, GP_DCMx, GP_COUNTx, etc.
* iCE40 Support
- Add "synth_ice40 -vpr"
- Add "synth_ice40 -nodffe"
- Add "synth_ice40 -json"
- Add Support for UltraPlus cells
* MAX10 and Cyclone IV Support
- Added initial version of metacommand "synth_intel".
- Improved write_verilog command to produce VQM netlist for Quartus Prime.
- Added support for MAX10 FPGA family synthesis.
- Added support for Cyclone IV family synthesis.
- Added example of implementation for DE2i-150 board.
- Added example of implementation for MAX10 development kit.
- Added LFSR example from Asic World.
- Added "dffinit -highlow" for mapping to Intel primitives
Yosys 0.6 .. Yosys 0.7
----------------------
* Various
- Added "yosys -D" feature
- Added support for installed plugins in $(DATDIR)/plugins/
- Renamed opt_const to opt_expr
- Renamed opt_share to opt_merge
- Added "prep -flatten" and "synth -flatten"
- Added "prep -auto-top" and "synth -auto-top"
- Using "mfs" and "lutpack" in ABC lut mapping
- Support for abstract modules in chparam
- Cleanup abstract modules at end of "hierarchy -top"
- Added tristate buffer support to iopadmap
- Added opt_expr support for div/mod by power-of-two
- Added "select -assert-min <N> -assert-max <N>"
- Added "attrmvcp" pass
- Added "attrmap" command
- Added "tee +INT -INT"
- Added "zinit" pass
- Added "setparam -type"
- Added "shregmap" pass
- Added "setundef -init"
- Added "nlutmap -assert"
- Added $sop cell type and "abc -sop -I <num> -P <num>"
- Added "dc2" to default ABC scripts
- Added "deminout"
- Added "insbuf" command
- Added "prep -nomem"
- Added "opt_rmdff -keepdc"
- Added "prep -nokeepdc"
- Added initial version of "synth_gowin"
- Added "fsm_expand -full"
- Added support for fsm_encoding="user"
- Many improvements in GreenPAK4 support
- Added black box modules for all Xilinx 7-series lib cells
- Added synth_ice40 support for latches via logic loops
- Fixed ice40_opt lut unmapping, added "ice40_opt -unlut"
* Build System
- Added ABCEXTERNAL and ABCURL make variables
- Added BINDIR, LIBDIR, and DATDIR make variables
- Added PKG_CONFIG make variable
- Added SEED make variable (for "make test")
- Added YOSYS_VER_STR make variable
- Updated min GCC requirement to GCC 4.8
- Updated required Bison version to Bison 3.x
* Internal APIs
- Added ast.h to exported headers
- Added ScriptPass helper class for script-like passes
- Added CellEdgesDatabase API
* Front-ends and Back-ends
- Added filename glob support to all front-ends
- Added avail (black-box) module params to ilang format
- Added $display %m support
- Added support for $stop Verilog system task
- Added support for SystemVerilog packages
- Fixed procedural assignments to non-unique lvalues, e.g. {y,y} = {a,b}
- Added support for "active high" and "active low" latches in read_blif and write_blif
- Use init value "2" for all uninitialized FFs in BLIF back-end
- Added "read_blif -sop"
- Added "write_blif -noalias"
- Added various write_blif options for VTR support
- write_json: also write module attributes.
- Added "write_verilog -nodec -nostr -defparam"
- Added "read_verilog -norestrict -assume-asserts"
- Added support for bus interfaces to "read_liberty -lib"
- Added liberty parser support for types within cell decls
- Added "write_verilog -renameprefix -v"
- Added "write_edif -nogndvcc"
* Formal Verification
- Support for hierarchical designs in smt2 back-end
- Yosys-smtbmc: Support for hierarchical VCD dumping
- Added $initstate cell type and vlog function
- Added $anyconst and $anyseq cell types and vlog functions
- Added printing of code loc of failed asserts to yosys-smtbmc
- Added memory_memx pass, "memory -memx", and "prep -memx"
- Added "proc_mux -ifx"
- Added "yosys-smtbmc -g"
- Deprecated "write_smt2 -regs" (by default on now)
- Made "write_smt2 -bv -mem" default, added "write_smt2 -nobv -nomem"
- Added support for memories to smtio.py
- Added "yosys-smtbmc --dump-vlogtb"
- Added "yosys-smtbmc --smtc --dump-smtc"
- Added "yosys-smtbmc --dump-all"
- Added assertpmux command
- Added "yosys-smtbmc --unroll"
- Added $past, $stable, $rose, $fell SVA functions
- Added "yosys-smtbmc --noinfo and --dummy"
- Added "yosys-smtbmc --noincr"
- Added "yosys-smtbmc --cex <filename>"
- Added $ff and $_FF_ cell types
- Added $global_clock verilog syntax support for creating $ff cells
- Added clk2fflogic
Yosys 0.5 .. Yosys 0.6
----------------------
* Various
- Added Contributor Covenant Code of Conduct
- Various improvements in dict<> and pool<>
- Added hashlib::mfp and refactored SigMap
- Improved support for reals as module parameters
- Various improvements in SMT2 back-end
- Added "keep_hierarchy" attribute
- Verilog front-end: define `BLACKBOX in -lib mode
- Added API for converting internal cells to AIGs
- Added ENABLE_LIBYOSYS Makefile option
- Removed "techmap -share_map" (use "-map +/filename" instead)
- Switched all Python scripts to Python 3
- Added support for $display()/$write() and $finish() to Verilog front-end
- Added "yosys-smtbmc" formal verification flow
- Added options for clang sanitizers to Makefile
* New commands and options
- Added "scc -expect <N> -nofeedback"
- Added "proc_dlatch"
- Added "check"
- Added "select %xe %cie %coe %M %C %R"
- Added "sat -dump_json" (WaveJSON format)
- Added "sat -tempinduct-baseonly -tempinduct-inductonly"
- Added "sat -stepsize" and "sat -tempinduct-step"
- Added "sat -show-regs -show-public -show-all"
- Added "write_json" (Native Yosys JSON format)
- Added "write_blif -attr"
- Added "dffinit"
- Added "chparam"
- Added "muxcover"
- Added "pmuxtree"
- Added memory_bram "make_outreg" feature
- Added "splice -wires"
- Added "dff2dffe -direct-match"
- Added simplemap $lut support
- Added "read_blif"
- Added "opt_share -share_all"
- Added "aigmap"
- Added "write_smt2 -mem -regs -wires"
- Added "memory -nordff"
- Added "write_smv"
- Added "synth -nordff -noalumacc"
- Added "rename -top new_name"
- Added "opt_const -clkinv"
- Added "synth -nofsm"
- Added "miter -assert"
- Added "read_verilog -noautowire"
- Added "read_verilog -nodpi"
- Added "tribuf"
- Added "lut2mux"
- Added "nlutmap"
- Added "qwp"
- Added "test_cell -noeval"
- Added "edgetypes"
- Added "equiv_struct"
- Added "equiv_purge"
- Added "equiv_mark"
- Added "equiv_add -try -cell"
- Added "singleton"
- Added "abc -g -luts"
- Added "torder"
- Added "write_blif -cname"
- Added "submod -copy"
- Added "dffsr2dff"
- Added "stat -liberty"
* Synthesis metacommands
- Various improvements in synth_xilinx
- Added synth_ice40 and synth_greenpak4
- Added "prep" metacommand for "synthesis lite"
* Cell library changes
- Added cell types to "help" system
- Added $meminit cell type
- Added $assume cell type
- Added $_MUX4_, $_MUX8_, and $_MUX16_ cells
- Added $tribuf and $_TBUF_ cell types
- Added read-enable to memory model
* YosysJS
- Various improvements in emscripten build
- Added alternative webworker-based JS API
- Added a few example applications
Yosys 0.4 .. Yosys 0.5
----------------------
* API changes
- Added log_warning()
- Added eval_select_args() and eval_select_op()
- Added cell->known(), cell->input(portname), cell->output(portname)
- Skip blackbox modules in design->selected_modules()
- Replaced std::map<> and std::set<> with dict<> and pool<>
- New SigSpec::extend() is what used to be SigSpec::extend_u0()
- Added YS_OVERRIDE, YS_FINAL, YS_ATTRIBUTE, YS_NORETURN
* Cell library changes
- Added flip-flops with enable ($dffe etc.)
- Added $equiv cells for equivalence checking framework
* Various
- Updated ABC to hg rev 61ad5f908c03
- Added clock domain partitioning to ABC pass
- Improved plugin building (see "yosys-config --build")
- Added ENABLE_NDEBUG Makefile flag for high-performance builds
- Added "yosys -d", "yosys -L" and other driver improvements
- Added support for multi-bit (array) cell ports to "write_edif"
- Now printing most output to stdout, not stderr
- Added "onehot" attribute (set by "fsm_map")
- Various performance improvements
- Vastly improved Xilinx flow
- Added "make unsintall"
* Equivalence checking
- Added equivalence checking commands:
equiv_make equiv_simple equiv_status
equiv_induct equiv_miter
equiv_add equiv_remove
* Block RAM support:
- Added "memory_bram" command
- Added BRAM support to Xilinx flow
* Other New Commands and Options
- Added "dff2dffe"
- Added "fsm -encfile"
- Added "dfflibmap -prepare"
- Added "write_blid -unbuf -undef -blackbox"
- Added "write_smt2" for writing SMT-LIBv2 files
- Added "test_cell -w -muxdiv"
- Added "select -read"
Yosys 0.3.0 .. Yosys 0.4
------------------------
* Platform Support
- Added support for mxe-based cross-builds for win32
- Added sourcecode-export as VisualStudio project
- Added experimental EMCC (JavaScript) support
* Verilog Frontend
- Added -sv option for SystemVerilog (and automatic *.sv file support)
- Added support for real-valued constants and constant expressions
- Added support for non-standard "via_celltype" attribute on task/func
- Added support for non-standard "module mod_name(...);" syntax
- Added support for non-standard """ macro bodies
- Added support for array with more than one dimension
- Added support for $readmemh and $readmemb
- Added support for DPI functions
* Changes in internal cell library
- Added $shift and $shiftx cell types
- Added $alu, $lcu, $fa and $macc cell types
- Removed $bu0 and $safe_pmux cell types
- $mem/$memwr WR_EN input is now a per-data-bit enable signal
- Added $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_
- Renamed ports of $lut cells (from I->O to A->Y)
- Renamed $_INV_ to $_NOT_
* Changes for simple synthesis flows
- There is now a "synth" command with a recommended default script
- Many improvements in synthesis of arithmetic functions to gates
- Multipliers and adders with many operands are using carry-save adder trees
- Remaining adders are now implemented using Brent-Kung carry look-ahead adders
- Various new high-level optimizations on RTL netlist
- Various improvements in FSM optimization
- Updated ABC to hg 5b5af75f1dda (from 2014-11-07)
* Changes in internal APIs and RTLIL
- Added log_id() and log_cell() helper functions
- Added function-like cell creation helpers
- Added GetSize() function (like .size() but with int)
- Major refactoring of RTLIL::Module and related classes
- Major refactoring of RTLIL::SigSpec and related classes
- Now RTLIL::IdString is essentially an int
- Added macros for code coverage counters
- Added some Makefile magic for pretty make logs
- Added "kernel/yosys.h" with all the core definitions
- Changed a lot of code from FILE* to c++ streams
- Added RTLIL::Monitor API and "trace" command
- Added "Yosys" C++ namespace
* Changes relevant to SAT solving
- Added ezSAT::keep_cnf() and ezSAT::non_incremental()
- Added native ezSAT support for vector shift ops
- Updated MiniSAT to git 37dc6c67e2 (from 2013-09-25)
* New commands (or large improvements to commands)
- Added "synth" command with default script
- Added "share" (finally some real resource sharing)
- Added "memory_share" (reduce number of ports on memories)
- Added "wreduce" and "alumacc" commands
- Added "opt -keepdc -fine -full -fast"
- Added some "test_*" commands
* Various other changes
- Added %D and %c select operators
- Added support for labels in yosys scripts
- Added support for here-documents in yosys scripts
- Support "+/" prefix for files from proc_share_dir
- Added "autoidx" statement to ilang language
- Switched from "yosys-svgviewer" to "xdot"
- Renamed "stdcells.v" to "techmap.v"
- Various bug fixes and small improvements
- Improved welcome and bye messages
Yosys 0.2.0 .. Yosys 0.3.0
--------------------------
* Driver program and overall behavior:
- Added "design -push" and "design -pop"
- Added "tee" command for redirecting log output
* Changes in the internal cell library:
- Added $dlatchsr and $_DLATCHSR_???_ cell types
* Improvements in Verilog frontend:
- Improved support for const functions (case, always, repeat)
- The generate..endgenerate keywords are now optional
- Added support for arrays of module instances
- Added support for "`default_nettype" directive
- Added support for "`line" directive
* Other front- and back-ends:
- Various changes to "write_blif" options
- Various improvements in EDIF backend
- Added "vhdl2verilog" pseudo-front-end
- Added "verific" pseudo-front-end
* Improvements in technology mapping:
- Added support for recursive techmap
- Added CONSTMSK and CONSTVAL features to techmap
- Added _TECHMAP_CONNMAP_*_ feature to techmap
- Added _TECHMAP_REPLACE_ feature to techmap
- Added "connwrappers" command for wrap-extract-unwrap method
- Added "extract -map %<design_name>" feature
- Added "extract -ignore_param ..." and "extract -ignore_parameters"
- Added "techmap -max_iter" option
* Improvements to "eval" and "sat" framework:
- Now include a copy of Minisat (with build fixes applied)
- Switched to Minisat::SimpSolver as SAT back-end
- Added "sat -dump_vcd" feature
- Added "sat -dump_cnf" feature
- Added "sat -initsteps <N>" feature
- Added "freduce -stop <N>" feature
- Added "freduce -dump <prefix>" feature
* Integration with ABC:
- Updated ABC rev to 7600ffb9340c
* Improvements in the internal APIs:
- Added RTLIL::Module::add... helper methods
- Various build fixes for OSX (Darwin) and OpenBSD
Yosys 0.1.0 .. Yosys 0.2.0
--------------------------
* Changes to the driver program:
- Added "yosys -h" and "yosys -H"
- Added support for backslash line continuation in scripts
- Added support for #-comments in same line as command
- Added "echo" and "log" commands
* Improvements in Verilog frontend:
- Added support for local registers in named blocks
- Added support for "case" in "generate" blocks
- Added support for $clog2 system function
- Added support for basic SystemVerilog assert statements
- Added preprocessor support for macro arguments
- Added preprocessor support for `elsif statement
- Added "verilog_defaults" command
- Added read_verilog -icells option
- Added support for constant sizes from parameters
- Added "read_verilog -setattr"
- Added support for function returning 'integer'
- Added limited support for function calls in parameter values
- Added "read_verilog -defer" to suppress evaluation of modules with default parameters
* Other front- and back-ends:
- Added BTOR backend
- Added Liberty frontend
* Improvements in technology mapping:
- The "dfflibmap" command now strongly prefers solutions with
no inverters in clock paths
- The "dfflibmap" command now prefers cells with smaller area
- Added support for multiple -map options to techmap
- Added "dfflibmap" support for //-comments in liberty files
- Added "memory_unpack" command to revert "memory_collect"
- Added standard techmap rule "techmap -share_map pmux2mux.v"
- Added "iopadmap -bits"
- Added "setundef" command
- Added "hilomap" command
* Changes in the internal cell library:
- Major rewrite of simlib.v for better compatibility with other tools
- Added PRIORITY parameter to $memwr cells
- Added TRANSPARENT parameter to $memrd cells
- Added RD_TRANSPARENT parameter to $mem cells
- Added $bu0 cell (always 0-extend, even undef MSB)
- Added $assert cell type
- Added $slice and $concat cell types
* Integration with ABC:
- Updated ABC to hg rev 2058c8ccea68
- Tighter integration of ABC build with Yosys build. The make
targets 'make abc' and 'make install-abc' are now obsolete.
- Added support for passing FFs from one clock domain through ABC
- Now always use BLIF as exchange format with ABC
- Added support for "abc -script +<command_sequence>"
- Improved standard ABC recipe
- Added support for "keep" attribute to abc command
- Added "abc -dff / -clk / -keepff" options
* Improvements to "eval" and "sat" framework:
- Added support for "0" and "~0" in right-hand side -set expressions
- Added "eval -set-undef" and "eval -table"
- Added "sat -set-init" and "sat -set-init-*" for sequential problems
- Added undef support to SAT solver, incl. various new "sat" options
- Added correct support for === and !== for "eval" and "sat"
- Added "sat -tempinduct" (default -seq is now non-induction sequential)
- Added "sat -prove-asserts"
- Complete rewrite of the 'freduce' command
- Added "miter" command
- Added "sat -show-inputs" and "sat -show-outputs"
- Added "sat -ignore_unknown_cells" (now produce an error by default)
- Added "sat -falsify"
- Now "sat -verify" and "sat -falsify" can also be used without "-prove"
- Added "expose" command
- Added support for @<sel_name> to sat and eval signal expressions
* Changes in the 'make test' framework and auxiliary test tools:
- Added autotest.sh -p and -f options
- Replaced autotest.sh ISIM support with XSIM support
- Added test cases for SAT framework
* Added "abbreviated IDs":
- Now $<something>$foo can be abbreviated as $foo.
- Usually this last part is a unique id (from RTLIL::autoidx)
- This abbreviated IDs are now also used in "show" output
* Other changes to selection framework:
- Now */ is optional in */<mode>:<arg> expressions
- Added "select -assert-none" and "select -assert-any"
- Added support for matching modules by attribute (A:<expr>)
- Added "select -none"
- Added support for r:<expr> pattern for matching cell parameters
- Added support for !=, <, <=, >=, > for attribute and parameter matching
- Added support for %s for selecting sub-modules
- Added support for %m for expanding selections to whole modules
- Added support for i:*, o:* and x:* pattern for selecting module ports
- Added support for s:<expr> pattern for matching wire width
- Added support for %a operation to select wire aliases
* Various other changes to commands and options:
- The "ls" command now supports wildcards
- Added "show -pause" and "show -format dot"
- Added "show -color" support for cells
- Added "show -label" and "show -notitle"
- Added "dump -m" and "dump -n"
- Added "history" command
- Added "rename -hide"
- Added "connect" command
- Added "splitnets -driver"
- Added "opt_const -mux_undef"
- Added "opt_const -mux_bool"
- Added "opt_const -undriven"
- Added "opt -mux_undef -mux_bool -undriven -purge"
- Added "hierarchy -libdir"
- Added "hierarchy -purge_lib" (by default now do not remove lib cells)
- Added "delete" command
- Added "dump -append"
- Added "setattr" and "setparam" commands
- Added "design -stash/-copy-from/-copy-to"
- Added "copy" command
- Added "splice" command

View File

@ -1,103 +0,0 @@
cmake_minimum_required(VERSION 3.3.0)
include(CMakeParseArguments)
project(yosys)
# Version number
set(YOSYS_VERSION_MAJOR 0.7)
set(YOSYS_VERSION_MINOR 0)
set(YOSYS_VERSION_PATCH 0)
# Options to enable/disable dependencies
option(YOSYS_ENABLE_TCL, "Enable TCL parser integrated in yosys" ON)
option(YOSYS_ENABLE_ABC, "Enable ABC library integrated in yosys" ON)
option(YOSYS_ENABLE_PLUGINS, "Enable plug-in in yosys" ON)
option(YOSYS_ENABLE_READLINE, "Enable readline library in yosys" ON)
option(YOSYS_ENABLE_VERIFIC, "Enable verification library in yosys" OFF)
option(YOSYS_ENABLE_COVER, "Enable coverage test in yosys" ON)
option(YOSYS_ENABLE_LIBYOSYS, "Enable static library compiled yosys" OFF)
option(YOSYS_ENABLE_GPROF, "Enable profiling in compiled yosys" OFF)
option(YOSYS_ENABLE_NDEBUG, "Enable non-debugging feature in compiled yosys" OFF)
#
## Search and link dependent packages
## We need readline to compile
if (YOSYS_ENABLE_READLINE)
find_package(Readline REQUIRED)
endif()
#
#########################
## #
## Compiler Flags Setup #
## #
#########################
#
## Compiler flag configuration checks
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
#
## Required Compiler Standard
#set(CMAKE_CXX_STANDARD 11) # need at least c+11 standard
#set(CMAKE_CXX_STANDARD_REQUIRED ON)
#
## Set warning flags
#set(WARN_FLAGS_TO_CHECK "") # checklist of warning flags
#set(WARN_FLAGS "") # actual warning flags to be added during compilation
## Add warning flags depending on options
#if (YOSYS_ENABLE_NDEBUG)
# set(WARN_FLAGS_TO_CHECK, ${WARN_FLAGS_TO_CHECK}, "-O3")
#endif()
#
#
##Collect the source files
#file(GLOB_RECURSE EXEC_YOSYS kernel/yosys.cc)
#file(GLOB_RECURSE LIB_SOURCES kernel/*.cc)
#file(GLOB_RECURSE LIB_HEADERS kernel/*.h)
#files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#
## Use c++ compiler for c source files
#set_source_files_properties(${LIB_SOURCES} PROPERTIES LANGUAGE CXX)
#set_source_files_properties(${EXEC_SOURCES} PROPERTIES LANGUAGE CXX)
#set_source_files_properties(${EXEC_SOURCES_SHELL} PROPERTIES LANGUAGE CXX)
#
##Build the library
#add_library(libyosys STATIC
# ${LIB_HEADERS}
# ${LIB_SOURCES})
#
## add header files to be included
#target_include_directories(libyosys PUBLIC ${LIB_INCLUDE_DIRS})
#set_target_properties(libyosys PROPERTIES PREFIX "") #Avoid extra 'lib' prefix#Create the executable
#
##Specify link-time dependancies
#target_link_libraries(libyosys
# readline)
#
## Build targets
## 1. yosys
#add_executable(yosys ${EXEC_SOURCES})
#target_link_libraries(vpr
# libyosys)
# 2. yosys-config
# run makefile provided, we pass-on the options to the local make file
add_custom_target(
yosys ALL
COMMAND
$(MAKE)
#CC=${CMAKE_C_COMPILER}
#CXX=${CMAKE_CXX_COMPILER}
#LD=${CMAKE_CXX_COMPILER}
#ENABLE_TCL=${YOSYS_ENABLE_TCL}
#ENABLE_ABC=${YOSYS_ENABLE_ABC}
#ENABLE_PLUGINS=${YOSYS_ENABLE_PLUGINS}
#ENABLE_READLINE=${YOSYS_ENABLE_READLINE}
#ENABLE_VERIFIC=${YOSYS_ENABLE_VERIFIC}
#ENABLE_COVER=${YOSYS_ENABLE_COVER}
#ENABLE_LIBYOSYS=${YOSYS_ENABLE_LIBYOSYS}
#ENABLE_GPROF=${YOSYS_ENABLE_GPROF}
#ENABLE_NDEBUG=${YOSYS_ENABLE_NDEBUG}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Compile Yosys with given Makefile"
)

View File

@ -1,13 +0,0 @@
Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,73 +0,0 @@
Contributor Covenant Code of Conduct
Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at clifford@clifford.at (and/or
cliffordvienna@gmail.com if you think your mail to the other address got
stuck in the spam filter). All complaints will be reviewed and investigated and
will result in a response that is deemed necessary and appropriate to the
circumstances. The project team is obligated to maintain confidentiality with
regard to the reporter of an incident. Further details of specific enforcement
policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at http://contributor-covenant.org/version/1/4/

View File

@ -1,509 +0,0 @@
This file contains some very brief documentation on things like programming APIs.
Also consult the Yosys manual and the section about programming in the presentation.
(Both can be downloaded as PDF from the yosys webpage.)
--snip-- only the lines below this mark are included in the yosys manual --snip--
Getting Started
===============
Outline of a Yosys command
--------------------------
Here is a the C++ code for a "hello_world" Yosys command (hello.cc):
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct HelloWorldPass : public Pass {
HelloWorldPass() : Pass("hello_world") { }
void execute(vector<string>, Design*) override {
log("Hello World!\n");
}
} HelloWorldPass;
PRIVATE_NAMESPACE_END
This can be built into a Yosys module using the following command:
yosys-config --exec --cxx --cxxflags --ldflags -o hello.so -shared hello.cc --ldlibs
Or short:
yosys-config --build hello.so hello.cc
And then executed using the following command:
yosys -m hello.so -p hello_world
Yosys Data Structures
---------------------
Here is a short list of data structures that you should make yourself familiar
with before you write C++ code for Yosys. The following data structures are all
defined when "kernel/yosys.h" is included and USING_YOSYS_NAMESPACE is used.
1. Yosys Container Classes
Yosys uses dict<K, T> and pool<T> as main container classes. dict<K, T> is
essentially a replacement for std::unordered_map<K, T> and pool<T> is a
replacement for std::unordered_set<T>. The main characteristics are:
- dict<K, T> and pool<T> are about 2x faster than the std containers
- references to elements in a dict<K, T> or pool<T> are invalidated by
insert and remove operations (similar to std::vector<T> on push_back()).
- some iterators are invalidated by erase(). specifically, iterators
that have not passed the erased element yet are invalidated. (erase()
itself returns valid iterator to the next element.)
- no iterators are invalidated by insert(). elements are inserted at
begin(). i.e. only a new iterator that starts at begin() will see the
inserted elements.
- the method .count(key, iterator) is like .count(key) but only
considers elements that can be reached via the iterator.
- iterators can be compared. it1 < it2 means that the position of t2
can be reached via t1 but not vice versa.
- the method .sort() can be used to sort the elements in the container
the container stays sorted until elements are added or removed.
- dict<K, T> and pool<T> will have the same order of iteration across
all compilers, standard libraries and architectures.
In addition to dict<K, T> and pool<T> there is also an idict<K> that
creates a bijective map from K to the integers. For example:
idict<string, 42> si;
log("%d\n", si("hello")); // will print 42
log("%d\n", si("world")); // will print 43
log("%d\n", si.at("world")); // will print 43
log("%d\n", si.at("dummy")); // will throw exception
log("%s\n", si[42].c_str())); // will print hello
log("%s\n", si[43].c_str())); // will print world
log("%s\n", si[44].c_str())); // will throw exception
It is not possible to remove elements from an idict.
Finally mfp<K> implements a merge-find set data structure (aka. disjoint-set or
union-find) over the type K ("mfp" = merge-find-promote).
2. Standard STL data types
In Yosys we use std::vector<T> and std::string whenever applicable. When
dict<K, T> and pool<T> are not suitable then std::map<K, T> and std::set<T>
are used instead.
The types std::vector<T> and std::string are also available as vector<T>
and string in the Yosys namespace.
3. RTLIL objects
The current design (essentially a collection of modules, each defined by a
netlist) is stored in memory using RTLIL object (declared in kernel/rtlil.h,
automatically included by kernel/yosys.h). You should glance over at least
the declarations for the following types in kernel/rtlil.h:
RTLIL::IdString
This is a handle for an identifier (e.g. cell or wire name).
It feels a lot like a std::string, but is only a single int
in size. (The actual string is stored in a global lookup
table.)
RTLIL::SigBit
A single signal bit. I.e. either a constant state (0, 1,
x, z) or a single bit from a wire.
RTLIL::SigSpec
Essentially a vector of SigBits.
RTLIL::Wire
RTLIL::Cell
The building blocks of the netlist in a module.
RTLIL::Module
RTLIL::Design
The module is a container with connected cells and wires
in it. The design is a container with modules in it.
All this types are also available without the RTLIL:: prefix in the Yosys
namespace.
4. SigMap and other Helper Classes
There are a couple of additional helper classes that are in wide use
in Yosys. Most importantly there is SigMap (declared in kernel/sigtools.h).
When a design has many wires in it that are connected to each other, then a
single signal bit can have multiple valid names. The SigMap object can be used
to map SigSpecs or SigBits to unique SigSpecs and SigBits that consistently
only use one wire from such a group of connected wires. For example:
SigBit a = module->addWire(NEW_ID);
SigBit b = module->addWire(NEW_ID);
module->connect(a, b);
log("%d\n", a == b); // will print 0
SigMap sigmap(module);
log("%d\n", sigmap(a) == sigmap(b)); // will print 1
Using the RTLIL Netlist Format
------------------------------
In the RTLIL netlist format the cell ports contain SigSpecs that point to the
Wires. There are no references in the other direction. This has two direct
consequences:
(1) It is very easy to go from cells to wires but hard to go in the other way.
(2) There is no danger in removing cells from the netlists, but removing wires
can break the netlist format when there are still references to the wire
somewhere in the netlist.
The solution to (1) is easy: Create custom indexes that allow you to make fast
lookups for the wire-to-cell direction. You can either use existing generic
index structures to do that (such as the ModIndex class) or write your own
index. For many application it is simplest to construct a custom index. For
example:
SigMap sigmap(module);
dict<SigBit, Cell*> sigbit_to_driver_index;
for (auto cell : module->cells())
for (auto &conn : cell->connections())
if (cell->output(conn.first))
for (auto bit : sigmap(conn.second))
sigbit_to_driver_index[bit] = cell;
Regarding (2): There is a general theme in Yosys that you don't remove wires
from the design. You can rename them, unconnect them, but you do not actually remove
the Wire object from the module. Instead you let the "clean" command take care
of the dangling wires. On the other hand it is safe to remove cells (as long as
you make sure this does not invalidate a custom index you are using in your code).
Example Code
------------
The following yosys commands are a good starting point if you are looking for examples
of how to use the Yosys API:
manual/CHAPTER_Prog/stubnets.cc
manual/PRESENTATION_Prog/my_cmd.cc
Notes on the existing codebase
------------------------------
For historical reasons not all parts of Yosys adhere to the current coding
style. When adding code to existing parts of the system, adhere to this guide
for the new code instead of trying to mimic the style of the surrounding code.
Coding Style
============
Formatting of code
------------------
- Yosys code is using tabs for indentation. Tabs are 8 characters.
- A continuation of a statement in the following line is indented by
two additional tabs.
- Lines are as long as you want them to be. A good rule of thumb is
to break lines at about column 150.
- Opening braces can be put on the same or next line as the statement
opening the block (if, switch, for, while, do). Put the opening brace
on its own line for larger blocks, especially blocks that contains
blank lines.
- Otherwise stick to the Linux Kernel Coding Style:
https://www.kernel.org/doc/Documentation/CodingStyle
C++ Language
-------------
Yosys is written in C++11. At the moment only constructs supported by
gcc 4.8 are allowed in Yosys code. This will change in future releases.
In general Yosys uses "int" instead of "size_t". To avoid compiler
warnings for implicit type casts, always use "GetSize(foobar)" instead
of "foobar.size()". (GetSize() is defined in kernel/yosys.h)
Use range-based for loops whenever applicable.
--snap-- only the lines above this mark are included in the yosys manual --snap--
Creating the Visual Studio Template Project
===========================================
1. Create an empty Visual C++ Win32 Console App project
Microsoft Visual Studio Express 2013 for Windows Desktop
Open New Project Wizard (File -> New Project..)
Project Name: YosysVS
Solution Name: YosysVS
[X] Create directory for solution
[ ] Add to source control
[X] Console applications
[X] Empty Project
[ ] SDL checks
2. Open YosysVS Project Properties
Select Configuration: All Configurations
C/C++ -> General -> Additional Include Directories
Add: ..\yosys
C/C++ -> Preprocessor -> Preprocessor Definitions
Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS
3. Resulting file system tree:
YosysVS/
YosysVS/YosysVS
YosysVS/YosysVS/YosysVS.vcxproj
YosysVS/YosysVS/YosysVS.vcxproj.filters
YosysVS/YosysVS.sdf
YosysVS/YosysVS.sln
YosysVS/YosysVS.v12.suo
4. Zip YosysVS as YosysVS-Tpl-v1.zip
Checklist for adding internal cell types
========================================
Things to do right away:
- Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
- Add to InternalCellChecker::check() in kernel/rtlil.cc
- Add to techlibs/common/simlib.v
- Add to techlibs/common/techmap.v
Things to do after finalizing the cell interface:
- Add support to kernel/satgen.h for the new cell type
- Add to manual/CHAPTER_CellLib.tex (or just add a fixme to the bottom)
- Maybe add support to the Verilog backend for dumping such cells as expression
Checklist for creating Yosys releases
=====================================
Update the CHANGELOG file:
cd ~yosys
gitk &
vi CHANGELOG
Update and check documentation:
cd ~yosys
make update-manual
make manual
- sanity check the figures in the appnotes and presentation
- if there are any odd things -> investigate
- make cosmetic changes to the .tex files if necessary
cd ~yosys
vi README CodingReadme
- is the information provided in those file still up to date
Then with default config setting:
cd ~yosys
make vgtest
cd ~yosys
./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
./yosys -p 'synth; show' tests/simple/fiedler-cooley.v
./yosys -p 'synth_xilinx -top up3down5; show' tests/simple/fiedler-cooley.v
cd ~yosys/examples/cmos
bash testbench.sh
cd ~yosys/examples/basys3
bash run.sh
Test building plugins with various of the standard passes:
yosys-config --build test.so equiv_simple.cc
- also check the code examples in CodingReadme
And if a version of the verific library is currently available:
cd ~yosys
cat frontends/verific/build_amd64.txt
- follow instructions
cd frontends/verific
../../yosys test_navre.ys
Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
cd ~yosys
make clean
make test
make ystests
make vloghtb
make install
cd ~yosys-bigsim
make clean
make full
cd ~vloghammer
make purge gen_issues gen_samples
make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
chromium-browser report.html
Release:
- set YOSYS_VER to x.y.z in Makefile
- update version string in CHANGELOG
git commit -am "Yosys x.y.z"
- push tag to github
- post changelog on github
- post short release note on reddit
Updating the website:
cd ~yosys
make manual
make install
- update pdf files on the website
cd ~yosys-web
make update_cmd
make update_show
git commit -am update
make push
Cross-Building for Windows with MXE
===================================
Check http://mxe.cc/#requirements and install all missing requirements.
As root (or other user with write access to /usr/local/src):
cd /usr/local/src
git clone https://github.com/mxe/mxe.git
cd mxe
make -j$(nproc) MXE_PLUGIN_DIRS="plugins/tcl.tk" \
MXE_TARGETS="i686-w64-mingw32.static" \
gcc tcl readline
Then as regular user in some directory where you build stuff:
git clone https://github.com/cliffordwolf/yosys.git yosys-win32
cd yosys-win32
make config-mxe
make -j$(nproc) mxebin
How to add unit test
====================
Unit test brings some advantages, briefly, we can list some of them (reference
[1](https://en.wikipedia.org/wiki/Unit_testing)):
* Tests reduce bugs in new features;
* Tests reduce bugs in existing features;
* Tests are good documentation;
* Tests reduce the cost of change;
* Tests allow refactoring;
With those advantages in mind, it was required to choose a framework which fits
well with C/C++ code. Hence, it was chosen (google test)
[https://github.com/google/googletest], because it is largely used and it is
relatively easy learn.
Install and configure google test (manually)
--------------------------------------------
In this section, you will see a brief description of how to install google
test. However, it is strongly recommended that you take a look to the official
repository (https://github.com/google/googletest) and refers to that if you
have any problem to install it. Follow the steps below:
* Install: cmake and pthread
* Clone google test project from: https://github.com/google/googletest and
enter in the project directory
* Inside project directory, type:
```
cmake -DBUILD_SHARED_LIBS=ON .
make
```
* After compilation, copy all "*.so" inside directory "googlemock" and
"googlemock/gtest" to "/usr/lib/"
* Done! Now you can compile your tests.
If you have any problem, go to the official repository to find help.
Ps.: Some distros already have googletest packed. If your distro supports it,
you can use it instead of compile.
Create new unit test
--------------------
If you want to add new unit tests for Yosys, just follow the steps below:
* Go to directory "yosys/test/unit/"
* In this directory you can find something similar Yosys's directory structure.
To create your unit test file you have to follow this pattern:
fileNameToImplementUnitTest + Test.cc. E.g.: if you want to implement the
unit test for kernel/celledges.cc, you will need to create a file like this:
tests/unit/kernel/celledgesTest.cc;
* Implement your unit test
Run unit test
-------------
To compile and run all unit tests, just go to yosys root directory and type:
```
make unit-test
```
If you want to remove all unit test files, type:
```
make clean-unit-test
```

View File

@ -1,33 +0,0 @@
FROM ubuntu:18.04 as builder
LABEL author="Abdelrahman Hosny <abdelrahman.hosny@hotmail.com>"
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y build-essential \
clang \
bison \
flex \
libreadline-dev \
gawk \
tcl-dev \
libffi-dev \
git \
pkg-config \
python3 && \
rm -rf /var/lib/apt/lists
COPY . /
RUN make && \
make install
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y libreadline-dev tcl-dev
COPY --from=builder /yosys /build/yosys
COPY --from=builder /yosys-abc /build/yosys-abc
COPY --from=builder /yosys-config /build/yosys-config
COPY --from=builder /yosys-filterlib /build/yosys-filterlib
COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc
ENV PATH /build:$PATH
RUN useradd -m yosys
USER yosys
ENTRYPOINT ["yosys"]

View File

@ -1,903 +0,0 @@
# CONFIG := clang
CONFIG := gcc
# CONFIG := gcc-4.8
# CONFIG := afl-gcc
# CONFIG := emcc
# CONFIG := mxe
# CONFIG := msys2
# CONFIG := msys2-64
# features (the more the better)
ENABLE_TCL := 0
ENABLE_ABC := 1
ENABLE_GLOB := 1
ENABLE_PLUGINS := 1
ENABLE_READLINE := 1
ENABLE_EDITLINE := 0
ENABLE_VERIFIC := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
ENABLE_PROTOBUF := 0
# python wrappers
ENABLE_PYOSYS := 0
# other configuration flags
ENABLE_GCOV := 0
ENABLE_GPROF := 0
ENABLE_DEBUG := 0
ENABLE_NDEBUG := 0
LINK_CURSES := 0
LINK_TERMCAP := 0
LINK_ABC := 0
# Needed for environments that don't have proper thread support (i.e. emscripten)
DISABLE_ABC_THREADS := 0
# clang sanitizers
SANITIZER =
# SANITIZER = address
# SANITIZER = memory
# SANITIZER = undefined
# SANITIZER = cfi
OS := $(shell uname -s)
PREFIX ?= /usr/local
INSTALL_SUDO :=
ifneq ($(wildcard Makefile.conf),)
include Makefile.conf
endif
BINDIR := $(PREFIX)/bin
LIBDIR := $(PREFIX)/lib
DATDIR := $(PREFIX)/share/yosys
EXE =
OBJS =
GENFILES =
EXTRA_OBJS =
EXTRA_TARGETS =
TARGETS = yosys$(EXE) yosys-config
PRETTY = 1
SMALL = 0
# Unit test
UNITESTPATH := tests/unit
all: top-all
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
VPATH := $(YOSYS_SRC)
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include
LDFLAGS := $(LDFLAGS) -L$(LIBDIR)
LDLIBS := $(LDLIBS) -lstdc++ -lm
PLUGIN_LDFLAGS :=
PKG_CONFIG ?= pkg-config
SED ?= sed
BISON ?= bison
STRIP ?= strip
AWK ?= awk
ifeq ($(OS), Darwin)
PLUGIN_LDFLAGS += -undefined dynamic_lookup
# homebrew search paths
ifneq ($(shell which brew),)
BREW_PREFIX := $(shell brew --prefix)/opt
$(info $$BREW_PREFIX is [${BREW_PREFIX}])
ifeq ($(ENABLE_PYOSYS),1)
CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost
LDFLAGS += -L$(BREW_PREFIX)/boost/lib
endif
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
LDFLAGS += -L$(BREW_PREFIX)/readline/lib
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH)
export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH)
# macports search paths
else ifneq ($(shell which port),)
PORT_PREFIX := $(patsubst %/bin/port,%,$(shell which port))
CXXFLAGS += -I$(PORT_PREFIX)/include
LDFLAGS += -L$(PORT_PREFIX)/lib
PKG_CONFIG_PATH := $(PORT_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)
export PATH := $(PORT_PREFIX)/bin:$(PATH)
endif
else
LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
YOSYS_VER := 0.9
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
# set 'ABCREV = default' to use abc/ as it is
#
# Note: If you do ABC development, make sure that 'abc' in this directory
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
ABCREV = 3709744
ABCPULL = 1
ABCURL ?= https://github.com/berkeley-abc/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
# set ABCEXTERNAL = <abc-command> to use an external ABC instance
# Note: The in-tree ABC (yosys-abc) will not be installed when ABCEXTERNAL is set.
ABCEXTERNAL ?=
define newline
endef
ifneq ($(wildcard Makefile.conf),)
$(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; s,$$,$$--$$,;' < Makefile.conf | tr -d '\n' | sed 's,\$$--\$$$$,,')))
include Makefile.conf
endif
ifeq ($(ENABLE_PYOSYS),1)
PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)"
PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi)
PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"")
PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.)
PYTHON_PREFIX := $(shell $(PYTHON_EXECUTABLE)-config --prefix)
PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
# Reload Makefile.conf to override python specific variables if defined
ifneq ($(wildcard Makefile.conf),)
include Makefile.conf
endif
endif
ifeq ($(CONFIG),clang)
CXX = clang
LD = clang++
CXXFLAGS += -std=c++11 -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
CXXFLAGS += -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER)
LDFLAGS += -g -fsanitize=$(SANITIZER)
ifeq ($(SANITIZER),address)
ENABLE_COVER := 0
endif
ifeq ($(SANITIZER),memory)
CXXFLAGS += -fPIE -fsanitize-memory-track-origins
LDFLAGS += -fPIE -fsanitize-memory-track-origins
endif
ifeq ($(SANITIZER),cfi)
CXXFLAGS += -flto
LDFLAGS += -flto
endif
endif
else ifeq ($(CONFIG),gcc)
CXX = gcc
LD = gcc
CXXFLAGS += -std=c++11 -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),gcc-static)
LD = $(CXX)
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -static
LDLIBS := $(filter-out -lrt,$(LDLIBS))
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
CXXFLAGS += -std=c++11 -Os
ABCMKARGS = CC="$(CC)" CXX="$(CXX)" LD="$(LD)" ABC_USE_LIBSTDCXX=1 LIBS="-lm -lpthread -static" OPTFLAGS="-O" \
ARCHFLAGS="-DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING=1 -Wno-unused-but-set-variable $(ARCHFLAGS)" ABC_USE_NO_READLINE=1
ifeq ($(DISABLE_ABC_THREADS),1)
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
endif
else ifeq ($(CONFIG),gcc-4.8)
CXX = gcc-4.8
LD = gcc-4.8
CXXFLAGS += -std=c++11 -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),afl-gcc)
CXX = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
LD = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
CXXFLAGS += -std=c++11 -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),cygwin)
CXX = gcc
LD = gcc
CXXFLAGS += -std=gnu++11 -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),emcc)
CXX = emcc
LD = emcc
CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS))
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8"
EMCCFLAGS := -Os -Wno-warn-absolute-paths
EMCCFLAGS += --memory-init-file 0 --embed-file share -s NO_EXIT_RUNTIME=1
EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']"
EMCCFLAGS += -s TOTAL_MEMORY=128*1024*1024
# https://github.com/kripken/emscripten/blob/master/src/settings.js
CXXFLAGS += $(EMCCFLAGS)
LDFLAGS += $(EMCCFLAGS)
LDLIBS =
EXE = .js
TARGETS := $(filter-out yosys-config,$(TARGETS))
EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
ifeq ($(ENABLE_ABC),1)
LINK_ABC := 1
DISABLE_ABC_THREADS := 1
endif
viz.js:
wget -O viz.js.part https://github.com/mdaines/viz.js/releases/download/0.0.3/viz.js
mv viz.js.part viz.js
yosysjs-$(YOSYS_VER).zip: yosys.js viz.js misc/yosysjs/*
rm -rf yosysjs-$(YOSYS_VER) yosysjs-$(YOSYS_VER).zip
mkdir -p yosysjs-$(YOSYS_VER)
cp viz.js misc/yosysjs/* yosys.js yosysjs-$(YOSYS_VER)/
zip -r yosysjs-$(YOSYS_VER).zip yosysjs-$(YOSYS_VER)
yosys.html: misc/yosys.html
$(P) cp misc/yosys.html yosys.html
else ifeq ($(CONFIG),mxe)
PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config
CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
LD = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_MXE_HACKS -Wno-attributes
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
# TODO: Try to solve pthread linking issue in more appropriate way
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LDFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
EXE = .exe
else ifeq ($(CONFIG),msys2)
CXX = i686-w64-mingw32-g++
LD = i686-w64-mingw32-g++
CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
EXE = .exe
else ifeq ($(CONFIG),msys2-64)
CXX = x86_64-w64-mingw32-g++
LD = x86_64-w64-mingw32-g++
CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
EXE = .exe
else ifneq ($(CONFIG),none)
$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2, msys2-64)
endif
ifeq ($(ENABLE_LIBYOSYS),1)
TARGETS += libyosys.so
endif
ifeq ($(ENABLE_PYOSYS),1)
#Detect name of boost_python library. Some distros usbe boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
ifeq ($(OS), Darwin)
BOOST_PYTHON_LIB ?= $(shell \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_EXECUTABLE)-config --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
echo ""; fi; fi; fi; fi;)
else
BOOST_PYTHON_LIB ?= $(shell \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_EXECUTABLE)-config --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
echo ""; fi; fi; fi; fi;)
endif
ifeq ($(BOOST_PYTHON_LIB),)
$(error BOOST_PYTHON_LIB could not be detected. Please define manualy)
endif
ifeq ($(OS), Darwin)
ifeq ($(PYTHON_MAJOR_VERSION),3)
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
else
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
endif
else
ifeq ($(PYTHON_MAJOR_VERSION),3)
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
else
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
endif
endif
ifeq ($(ENABLE_PYOSYS),1)
PY_WRAPPER_FILE = kernel/python_wrappers
OBJS += $(PY_WRAPPER_FILE).o
PY_GEN_SCRIPT= py_wrap_generator
PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
endif
endif
ifeq ($(ENABLE_READLINE),1)
CXXFLAGS += -DYOSYS_ENABLE_READLINE
ifeq ($(OS), FreeBSD)
CXXFLAGS += -I/usr/local/include
endif
LDLIBS += -lreadline
ifeq ($(LINK_CURSES),1)
LDLIBS += -lcurses
ABCMKARGS += "ABC_READLINE_LIBRARIES=-lcurses -lreadline"
endif
ifeq ($(LINK_TERMCAP),1)
LDLIBS += -ltermcap
ABCMKARGS += "ABC_READLINE_LIBRARIES=-lreadline -ltermcap"
endif
ifeq ($(CONFIG),mxe)
LDLIBS += -ltermcap
endif
else
ifeq ($(ENABLE_EDITLINE),1)
CXXFLAGS += -DYOSYS_ENABLE_EDITLINE
LDLIBS += -ledit -ltinfo -lbsd
else
ABCMKARGS += "ABC_USE_NO_READLINE=1"
endif
endif
ifeq ($(DISABLE_ABC_THREADS),1)
ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
endif
ifeq ($(ENABLE_PLUGINS),1)
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi)
ifneq ($(OS), FreeBSD)
LDLIBS += -ldl
endif
endif
ifeq ($(ENABLE_GLOB),1)
CXXFLAGS += -DYOSYS_ENABLE_GLOB
endif
ifeq ($(ENABLE_TCL),1)
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
ifeq ($(OS), FreeBSD)
TCL_INCLUDE ?= /usr/local/include/$(TCL_VERSION)
else
TCL_INCLUDE ?= /usr/include/$(TCL_VERSION)
endif
ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv
else
CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
ifeq ($(OS), FreeBSD)
# FreeBSD uses tcl8.6, but lib is named "libtcl86"
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION) | tr -d '.')
else
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION))
endif
endif
endif
ifeq ($(ENABLE_GCOV),1)
CXXFLAGS += --coverage
LDFLAGS += --coverage
endif
ifeq ($(ENABLE_GPROF),1)
CXXFLAGS += -pg
LDFLAGS += -pg
endif
ifeq ($(ENABLE_NDEBUG),1)
CXXFLAGS := -O3 -DNDEBUG $(filter-out -Os -ggdb,$(CXXFLAGS))
endif
ifeq ($(ENABLE_DEBUG),1)
ifeq ($(CONFIG),clang)
CXXFLAGS := -O0 -DDEBUG $(filter-out -Os,$(CXXFLAGS))
else
CXXFLAGS := -Og -DDEBUG $(filter-out -Os,$(CXXFLAGS))
endif
endif
ifeq ($(ENABLE_ABC),1)
CXXFLAGS += -DYOSYS_ENABLE_ABC
ifeq ($(LINK_ABC),1)
CXXFLAGS += -DYOSYS_LINK_ABC
ifeq ($(DISABLE_ABC_THREADS),0)
LDLIBS += -lpthread
endif
else
ifeq ($(ABCEXTERNAL),)
TARGETS += yosys-abc$(EXE)
endif
endif
endif
ifeq ($(ENABLE_VERIFIC),1)
VERIFIC_DIR ?= /usr/local/src/verific_lib
VERIFIC_COMPONENTS ?= verilog vhdl database util containers hier_tree
CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC
ifeq ($(OS), Darwin)
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-mac.a,$(VERIFIC_COMPONENTS)) -lz
else
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz
endif
endif
ifeq ($(ENABLE_PROTOBUF),1)
LDLIBS += $(shell pkg-config --cflags --libs protobuf)
endif
ifeq ($(ENABLE_COVER),1)
CXXFLAGS += -DYOSYS_ENABLE_COVER
endif
define add_share_file
EXTRA_TARGETS += $(subst //,/,$(1)/$(notdir $(2)))
$(subst //,/,$(1)/$(notdir $(2))): $(2)
$$(P) mkdir -p $(1)
$$(Q) cp "$(YOSYS_SRC)"/$(2) $(subst //,/,$(1)/$(notdir $(2)))
endef
define add_gen_share_file
EXTRA_TARGETS += $(subst //,/,$(1)/$(notdir $(2)))
$(subst //,/,$(1)/$(notdir $(2))): $(2)
$$(P) mkdir -p $(1)
$$(Q) cp $(2) $(subst //,/,$(1)/$(notdir $(2)))
endef
define add_include_file
$(eval $(call add_share_file,$(dir share/include/$(1)),$(1)))
endef
ifeq ($(PRETTY), 1)
P_STATUS = 0
P_OFFSET = 0
P_UPDATE = $(eval P_STATUS=$(shell echo $(OBJS) yosys$(EXE) | $(AWK) 'BEGIN { RS = " "; I = $(P_STATUS)+0; } $$1 == "$@" && NR > I { I = NR; } END { print I; }'))
P_SHOW = [$(shell $(AWK) "BEGIN { N=$(words $(OBJS) yosys$(EXE)); printf \"%3d\", $(P_OFFSET)+90*$(P_STATUS)/N; exit; }")%]
P = @echo "$(if $(findstring $@,$(TARGETS) $(EXTRA_TARGETS)),$(eval P_OFFSET = 10))$(call P_UPDATE)$(call P_SHOW) Building $@";
Q = @
S = -s
else
P_SHOW = ->
P =
Q =
S =
endif
$(eval $(call add_include_file,kernel/yosys.h))
$(eval $(call add_include_file,kernel/hashlib.h))
$(eval $(call add_include_file,kernel/log.h))
$(eval $(call add_include_file,kernel/rtlil.h))
$(eval $(call add_include_file,kernel/register.h))
$(eval $(call add_include_file,kernel/celltypes.h))
$(eval $(call add_include_file,kernel/celledges.h))
$(eval $(call add_include_file,kernel/consteval.h))
$(eval $(call add_include_file,kernel/sigtools.h))
$(eval $(call add_include_file,kernel/modtools.h))
$(eval $(call add_include_file,kernel/macc.h))
$(eval $(call add_include_file,kernel/utils.h))
$(eval $(call add_include_file,kernel/satgen.h))
$(eval $(call add_include_file,libs/ezsat/ezsat.h))
$(eval $(call add_include_file,libs/ezsat/ezminisat.h))
$(eval $(call add_include_file,libs/sha1/sha1.h))
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
$(eval $(call add_include_file,frontends/ast/ast.h))
$(eval $(call add_include_file,backends/ilang/ilang_backend.h))
OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o
OBJS += kernel/cellaigs.o kernel/celledges.o
kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"'
OBJS += libs/bigint/BigIntegerAlgorithms.o libs/bigint/BigInteger.o libs/bigint/BigIntegerUtils.o
OBJS += libs/bigint/BigUnsigned.o libs/bigint/BigUnsignedInABase.o
OBJS += libs/sha1/sha1.o
ifneq ($(SMALL),1)
OBJS += libs/subcircuit/subcircuit.o
OBJS += libs/ezsat/ezsat.o
OBJS += libs/ezsat/ezminisat.o
OBJS += libs/minisat/Options.o
OBJS += libs/minisat/SimpSolver.o
OBJS += libs/minisat/Solver.o
OBJS += libs/minisat/System.o
include $(YOSYS_SRC)/frontends/*/Makefile.inc
include $(YOSYS_SRC)/passes/*/Makefile.inc
include $(YOSYS_SRC)/backends/*/Makefile.inc
include $(YOSYS_SRC)/techlibs/*/Makefile.inc
else
include frontends/verilog/Makefile.inc
include frontends/ilang/Makefile.inc
include frontends/ast/Makefile.inc
include frontends/blif/Makefile.inc
OBJS += passes/hierarchy/hierarchy.o
OBJS += passes/cmds/select.o
OBJS += passes/cmds/show.o
OBJS += passes/cmds/stat.o
OBJS += passes/cmds/cover.o
OBJS += passes/cmds/design.o
OBJS += passes/cmds/plugin.o
include passes/proc/Makefile.inc
include passes/opt/Makefile.inc
include passes/techmap/Makefile.inc
include backends/verilog/Makefile.inc
include backends/ilang/Makefile.inc
include techlibs/common/Makefile.inc
endif
ifeq ($(LINK_ABC),1)
OBJS += yosys-libabc.a
endif
top-all: $(TARGETS) $(EXTRA_TARGETS)
@echo ""
@echo " Build successful."
@echo ""
ifeq ($(CONFIG),emcc)
yosys.js: $(filter-out yosysjs-$(YOSYS_VER).zip,$(EXTRA_TARGETS))
endif
yosys$(EXE): $(OBJS)
$(P) $(LD) -o yosys$(EXE) $(LDFLAGS) $(OBJS) $(LDLIBS)
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
ifeq ($(OS), Darwin)
$(P) $(LD) -o libyosys.so -shared -Wl,-install_name,libyosys.so $(LDFLAGS) $^ $(LDLIBS)
else
$(P) $(LD) -o libyosys.so -shared -Wl,-soname,libyosys.so $(LDFLAGS) $^ $(LDLIBS)
endif
%.o: %.cc
$(Q) mkdir -p $(dir $@)
$(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $<
%.pyh: %.h
$(Q) mkdir -p $(dir $@)
$(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P -
ifeq ($(ENABLE_PYOSYS),1)
$(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES)
$(Q) mkdir -p $(dir $@)
$(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")"
endif
%.o: %.cpp
$(Q) mkdir -p $(dir $@)
$(P) $(CXX) -o $@ -c $(CPPFLAGS) $(CXXFLAGS) $<
YOSYS_VER_STR := Yosys $(YOSYS_VER) (git sha1 $(GIT_REV), $(notdir $(CXX)) $(shell \
$(CXX) --version | tr ' ()' '\n' | grep '^[0-9]' | head -n1) $(filter -f% -m% -O% -DNDEBUG,$(CXXFLAGS)))
kernel/version_$(GIT_REV).cc: $(YOSYS_SRC)/Makefile
$(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc
$(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"$(YOSYS_VER_STR)\"; }" > kernel/version_$(GIT_REV).cc
ifeq ($(ENABLE_VERIFIC),1)
CXXFLAGS_NOVERIFIC = $(foreach v,$(CXXFLAGS),$(if $(findstring $(VERIFIC_DIR),$(v)),,$(v)))
LDLIBS_NOVERIFIC = $(foreach v,$(LDLIBS),$(if $(findstring $(VERIFIC_DIR),$(v)),,$(v)))
else
CXXFLAGS_NOVERIFIC = $(CXXFLAGS)
LDLIBS_NOVERIFIC = $(LDLIBS)
endif
yosys-config: misc/yosys-config.in
$(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC)))#;' \
-e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC))#;' \
-e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > yosys-config
$(Q) chmod +x yosys-config
abc/abc-$(ABCREV)$(EXE) abc/libabc-$(ABCREV).a:
$(P)
ifneq ($(ABCREV),default)
$(Q) if test -d abc/.hg; then \
echo 'REEBE: NOP qverpgbel vf n ut jbexvat pbcl! Erzbir nop/ naq er-eha "znxr".' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \
fi
$(Q) if ( cd abc 2> /dev/null && ! git diff-index --quiet HEAD; ); then \
echo 'REEBE: NOP pbagnvaf ybpny zbqvsvpngvbaf! Frg NOPERI=qrsnhyg va Lbflf Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \
fi
$(Q) if test "`cd abc 2> /dev/null && git rev-parse --short HEAD`" != "$(ABCREV)"; then \
test $(ABCPULL) -ne 0 || { echo 'REEBE: NOP abg hc gb qngr naq NOPCHYY frg gb 0 va Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; exit 1; }; \
echo "Pulling ABC from $(ABCURL):"; set -x; \
test -d abc || git clone $(ABCURL) abc; \
cd abc && $(MAKE) DEP= clean && git fetch origin master && git checkout $(ABCREV); \
fi
endif
$(Q) rm -f abc/abc-[0-9a-f]*
$(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) $(if $(filter %.a,$@),PROG="abc-$(ABCREV)",PROG="abc-$(ABCREV)$(EXE)") MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " $(if $(filter %.a,$@),libabc-$(ABCREV).a)
ifeq ($(ABCREV),default)
.PHONY: abc/abc-$(ABCREV)$(EXE)
.PHONY: abc/libabc-$(ABCREV).a
endif
yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE)
$(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE)
yosys-libabc.a: abc/libabc-$(ABCREV).a
$(P) cp abc/libabc-$(ABCREV).a yosys-libabc.a
ifneq ($(SEED),)
SEEDOPT="-S $(SEED)"
else
SEEDOPT=""
endif
ifneq ($(ABCEXTERNAL),)
ABCOPT="-A $(ABCEXTERNAL)"
else
ABCOPT=""
endif
test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/simple && bash run-test.sh $(SEEDOPT)
+cd tests/hana && bash run-test.sh $(SEEDOPT)
+cd tests/asicworld && bash run-test.sh $(SEEDOPT)
# +cd tests/realmath && bash run-test.sh $(SEEDOPT)
+cd tests/share && bash run-test.sh $(SEEDOPT)
+cd tests/fsm && bash run-test.sh $(SEEDOPT)
+cd tests/techmap && bash run-test.sh
+cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT)
+cd tests/bram && bash run-test.sh $(SEEDOPT)
+cd tests/various && bash run-test.sh
+cd tests/sat && bash run-test.sh
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
+cd tests/opt && bash run-test.sh
+cd tests/aiger && bash run-test.sh $(ABCOPT)
+cd tests/arch && bash run-test.sh
@echo ""
@echo " Passed \"make test\"."
@echo ""
VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all
vgtest: $(TARGETS) $(EXTRA_TARGETS)
$(VALGRIND) ./yosys -p 'setattr -mod -unset top; synth' $$( ls tests/simple/*.v | grep -v repwhile.v )
@echo ""
@echo " Passed \"make vgtest\"."
@echo ""
vloghtb: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/vloghtb && bash run-test.sh
@echo ""
@echo " Passed \"make vloghtb\"."
@echo ""
ystests: $(TARGETS) $(EXTRA_TARGETS)
rm -rf tests/ystests
git clone -b yosys-0.9-rc https://github.com/YosysHQ/yosys-tests.git tests/ystests
+$(MAKE) PATH="$$PWD:$$PATH" -C tests/ystests
@echo ""
@echo " Finished \"make ystests\"."
@echo ""
# Unit test
unit-test: libyosys.so
@$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" \
CXXFLAGS="$(CXXFLAGS)" LDLIBS="$(LDLIBS)" ROOTPATH="$(CURDIR)"
clean-unit-test:
@$(MAKE) -C $(UNITESTPATH) clean
install: $(TARGETS) $(EXTRA_TARGETS)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
$(INSTALL_SUDO) cp $(TARGETS) $(DESTDIR)$(BINDIR)
ifneq ($(filter yosys,$(TARGETS)),)
$(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/yosys
endif
ifneq ($(filter yosys-abc,$(TARGETS)),)
$(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-abc
endif
ifneq ($(filter yosys-filterlib,$(TARGETS)),)
$(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-filterlib
endif
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR)
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/
$(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys
$(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys/
$(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/pyosys/
endif
endif
uninstall:
$(INSTALL_SUDO) rm -vf $(addprefix $(DESTDIR)$(BINDIR)/,$(notdir $(TARGETS)))
$(INSTALL_SUDO) rm -rvf $(DESTDIR)$(DATDIR)
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.so
ifeq ($(ENABLE_PYOSYS),1)
$(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/pyosys/libyosys.so
$(INSTALL_SUDO) rm -vf $(PYTHON_DESTDIR)/pyosys/__init__.py
$(INSTALL_SUDO) rmdir $(PYTHON_DESTDIR)/pyosys
endif
endif
update-manual: $(TARGETS) $(EXTRA_TARGETS)
cd manual && ../yosys -p 'help -write-tex-command-reference-manual'
manual: $(TARGETS) $(EXTRA_TARGETS)
cd manual && bash appnotes.sh
cd manual && bash presentation.sh
cd manual && bash manual.sh
clean:
rm -rf share
rm -rf kernel/*.pyh
if test -d manual; then cd manual && sh clean.sh; fi
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) $(PY_WRAP_INCLUDES) $(PY_WRAPPER_FILE).cc
rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
rm -rf tests/asicworld/*.out tests/asicworld/*.log
rm -rf tests/hana/*.out tests/hana/*.log
rm -rf tests/simple/*.out tests/simple/*.log
rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp
rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log
rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp
rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
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
clean-abc:
$(MAKE) -C abc DEP= clean
rm -f yosys-abc$(EXE) yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
mrproper: clean
git clean -xdf
coverage:
./yosys -qp 'help; help -all'
rm -rf coverage.info coverage_html
lcov --capture -d . --no-external -o coverage.info
genhtml coverage.info --output-directory coverage_html
qtcreator:
{ for file in $(basename $(OBJS)); do \
for prefix in cc y l; do if [ -f $${file}.$${prefix} ]; then echo $$file.$${prefix}; fi; done \
done; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \); } > qtcreator.files
{ echo .; find backends frontends kernel libs passes -type f \( -name '*.h' -o -name '*.hh' \) -printf '%h\n' | sort -u; } > qtcreator.includes
touch qtcreator.config qtcreator.creator
vcxsrc: $(GENFILES) $(EXTRA_TARGETS)
rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip}
set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \
echo "Analyse: $$f" >&2; cpp -std=c++11 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt
bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV)
echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc
zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc
zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/
rm -f srcfiles.txt kernel/version.cc
ifeq ($(CONFIG),mxe)
mxebin: $(TARGETS) $(EXTRA_TARGETS)
rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip}
mkdir -p yosys-win32-mxebin-$(YOSYS_VER)
cp -r yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/
ifeq ($(ENABLE_ABC),1)
cp -r yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/
endif
echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/
endif
config-clean: clean
rm -f Makefile.conf
config-clang: clean
echo 'CONFIG := clang' > Makefile.conf
config-gcc: clean
echo 'CONFIG := gcc' > Makefile.conf
config-gcc-static: clean
echo 'CONFIG := gcc-static' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
echo 'ENABLE_READLINE := 0' >> Makefile.conf
echo 'ENABLE_TCL := 0' >> Makefile.conf
config-gcc-4.8: clean
echo 'CONFIG := gcc-4.8' > Makefile.conf
config-afl-gcc: clean
echo 'CONFIG := afl-gcc' > Makefile.conf
config-emcc: clean
echo 'CONFIG := emcc' > Makefile.conf
echo 'ENABLE_TCL := 0' >> Makefile.conf
echo 'ENABLE_ABC := 0' >> Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
echo 'ENABLE_READLINE := 0' >> Makefile.conf
config-mxe: clean
echo 'CONFIG := mxe' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-msys2-64: clean
echo 'CONFIG := msys2-64' > Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
config-cygwin: clean
echo 'CONFIG := cygwin' > Makefile.conf
config-gcov: clean
echo 'CONFIG := gcc' > Makefile.conf
echo 'ENABLE_GCOV := 1' >> Makefile.conf
echo 'ENABLE_DEBUG := 1' >> Makefile.conf
config-gprof: clean
echo 'CONFIG := gcc' > Makefile.conf
echo 'ENABLE_GPROF := 1' >> Makefile.conf
config-sudo:
echo "INSTALL_SUDO := sudo" >> Makefile.conf
echo-yosys-ver:
@echo "$(YOSYS_VER)"
echo-git-rev:
@echo "$(GIT_REV)"
-include libs/*/*.d
-include frontends/*/*.d
-include passes/*/*.d
-include backends/*/*.d
-include kernel/*.d
-include techlibs/*/*.d
.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator coverage vcxsrc mxebin
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-afl-gcc config-gprof config-sudo

View File

@ -1,538 +0,0 @@
```
yosys -- Yosys Open SYnthesis Suite
Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
```
yosys Yosys Open SYnthesis Suite
===================================
This is a framework for RTL synthesis tools. It currently has
extensive Verilog-2005 support and provides a basic set of
synthesis algorithms for various application domains.
Yosys can be adapted to perform any synthesis job by combining
the existing passes (algorithms) using synthesis scripts and
adding additional passes as needed by extending the yosys C++
code base.
Yosys is free software licensed under the ISC license (a GPL
compatible license that is similar in terms to the MIT license
or the 2-clause BSD license).
Web Site and Other Resources
============================
More information and documentation can be found on the Yosys web site:
- http://www.clifford.at/yosys/
The "Documentation" page on the web site contains links to more resources,
including a manual that even describes some of the Yosys internals:
- http://www.clifford.at/yosys/documentation.html
The file `CodingReadme` in this directory contains additional information
for people interested in using the Yosys C++ APIs.
Users interested in formal verification might want to use the formal verification
front-end for Yosys, SymbiYosys:
- https://symbiyosys.readthedocs.io/en/latest/
- https://github.com/YosysHQ/SymbiYosys
Setup
======
You need a C++ compiler with C++11 support (up-to-date CLANG or GCC is
recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.
TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
Xdot (graphviz) is used by the ``show`` command in yosys to display schematics.
For example on Ubuntu Linux 16.04 LTS the following commands will install all
prerequisites for building yosys:
$ sudo apt-get install build-essential clang bison flex \
libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3 libboost-system-dev \
libboost-python-dev libboost-filesystem-dev
Similarily, on Mac OS X Homebrew can be used to install dependencies:
$ brew tap Homebrew/bundle && brew bundle
or MacPorts:
$ sudo port install bison flex readline gawk libffi \
git graphviz pkgconfig python36 boost tcl
On FreeBSD use the following command to install all prerequisites:
# pkg install bison flex readline gawk libffi\
git graphviz pkgconfig python3 python36 tcl-wrapper boost-libs
On FreeBSD system use gmake instead of make. To run tests use:
% MAKE=gmake CC=cc gmake test
For Cygwin use the following command to install all prerequisites, or select these additional packages:
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
There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
as a source distribution for Visual Studio. Visit the Yosys download page for
more information: http://www.clifford.at/yosys/download.html
To configure the build system to use a specific compiler, use one of
$ make config-clang
$ make config-gcc
For other compilers and build configurations it might be
necessary to make some changes to the config section of the
Makefile.
$ vi Makefile # ..or..
$ vi Makefile.conf
To build Yosys simply type 'make' in this directory.
$ make
$ sudo make install
Note that this also downloads, builds and installs ABC (using yosys-abc
as executable name).
Tests are located in the tests subdirectory and can be executed using the test target. Note that you need gawk as well as a recent version of iverilog (i.e. build from git). Then, execute tests via:
$ make test
Getting Started
===============
Yosys can be used with the interactive command shell, with
synthesis scripts or with command line arguments. Let's perform
a simple synthesis job using the interactive command shell:
$ ./yosys
yosys>
the command ``help`` can be used to print a list of all available
commands and ``help <command>`` to print details on the specified command:
yosys> help help
reading the design using the Verilog frontend:
yosys> read_verilog tests/simple/fiedler-cooley.v
writing the design to the console in Yosys's internal format:
yosys> write_ilang
elaborate design hierarchy:
yosys> hierarchy
convert processes (``always`` blocks) to netlist elements and perform
some simple optimizations:
yosys> proc; opt
display design netlist using ``xdot``:
yosys> show
the same thing using ``gv`` as postscript viewer:
yosys> show -format ps -viewer gv
translating netlist to gate logic and perform some simple optimizations:
yosys> techmap; opt
write design netlist to a new Verilog file:
yosys> write_verilog synth.v
a similar synthesis can be performed using yosys command line options only:
$ ./yosys -o synth.v -p hierarchy -p proc -p opt \
-p techmap -p opt tests/simple/fiedler-cooley.v
or using a simple synthesis script:
$ cat synth.ys
read_verilog tests/simple/fiedler-cooley.v
hierarchy; proc; opt; techmap; opt
write_verilog synth.v
$ ./yosys synth.ys
It is also possible to only have the synthesis commands but not the read/write
commands in the synthesis script:
$ cat synth.ys
hierarchy; proc; opt; techmap; opt
$ ./yosys -o synth.v tests/simple/fiedler-cooley.v synth.ys
The following very basic synthesis script should work well with all designs:
# check design hierarchy
hierarchy
# translate processes (always blocks)
proc; opt
# detect and optimize FSM encodings
fsm; opt
# implement memories (arrays)
memory; opt
# convert to gate logic
techmap; opt
If ABC is enabled in the Yosys build configuration and a cell library is given
in the liberty file ``mycells.lib``, the following synthesis script will
synthesize for the given cell library:
# the high-level stuff
hierarchy; proc; fsm; opt; memory; opt
# mapping to internal cell library
techmap; opt
# mapping flip-flops to mycells.lib
dfflibmap -liberty mycells.lib
# mapping logic to mycells.lib
abc -liberty mycells.lib
# cleanup
clean
If you do not have a liberty file but want to test this synthesis script,
you can use the file ``examples/cmos/cmos_cells.lib`` from the yosys sources.
Liberty file downloads for and information about free and open ASIC standard
cell libraries can be found here:
- http://www.vlsitechnology.org/html/libraries.html
- http://www.vlsitechnology.org/synopsys/vsclib013.lib
The command ``synth`` provides a good default synthesis script (see
``help synth``). If possible a synthesis script should borrow from ``synth``.
For example:
# the high-level stuff
hierarchy
synth -run coarse
# mapping to internal cells
techmap; opt -fast
dfflibmap -liberty mycells.lib
abc -liberty mycells.lib
clean
Yosys is under construction. A more detailed documentation will follow.
Unsupported Verilog-2005 Features
=================================
The following Verilog-2005 features are not supported by
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
- The ``tri``, ``triand`` and ``trior`` net types
- The ``config`` and ``disable`` keywords and library map files
Verilog Attributes and non-standard features
============================================
- The ``full_case`` attribute on case statements is supported
(also the non-standard ``// synopsys full_case`` directive)
- The ``parallel_case`` attribute on case statements is supported
(also the non-standard ``// synopsys parallel_case`` directive)
- The ``// synopsys translate_off`` and ``// synopsys translate_on``
directives are also supported (but the use of ``` `ifdef .. `endif ```
is strongly recommended instead).
- The ``nomem2reg`` attribute on modules or arrays prohibits the
automatic early conversion of arrays to separate registers. This
is potentially dangerous. Usually the front-end has good reasons
for converting an array to a list of registers. Prohibiting this
step will likely result in incorrect synthesis results.
- The ``mem2reg`` attribute on modules or arrays forces the early
conversion of arrays to separate registers.
- The ``nomeminit`` attribute on modules or arrays prohibits the
creation of initialized memories. This effectively puts ``mem2reg``
on all memories that are written to in an ``initial`` block and
are not ROMs.
- The ``nolatches`` attribute on modules or always-blocks
prohibits the generation of logic-loops for latches. Instead
all not explicitly assigned values default to x-bits. This does
not affect clocked storage elements such as flip-flops.
- The ``nosync`` attribute on registers prohibits the generation of a
storage element. The register itself will always have all bits set
to 'x' (undefined). The variable may only be used as blocking assigned
temporary variable within an always block. This is mostly used internally
by Yosys to synthesize Verilog functions and access arrays.
- The ``onehot`` attribute on wires mark them as one-hot state register. This
is used for example for memory port sharing and set by the fsm_map pass.
- The ``blackbox`` attribute on modules is used to mark empty stub modules
that have the same ports as the real thing but do not contain information
on the internal configuration. This modules are only used by the synthesis
passes to identify input and output ports of cells. The Verilog backend
also does not output blackbox modules on default. ``read_verilog``, unless
called with ``-noblackbox`` will automatically set the blackbox attribute
on any empty module it reads.
- The ``noblackbox`` attribute set on an empty module prevents ``read_verilog``
from automatically setting the blackbox attribute on the module.
- The ``whitebox`` attribute on modules triggers the same behavior as
``blackbox``, but is for whitebox modules, i.e. library modules that
contain a behavioral model of the cell type.
- The ``lib_whitebox`` attribute overwrites ``whitebox`` when ``read_verilog``
is run in `-lib` mode. Otherwise it's automatically removed.
- The ``dynports`` attribute is used by the Verilog front-end to mark modules
that have ports with a width that depends on a parameter.
- The ``hdlname`` attribute is used by some passes to document the original
(HDL) name of a module when renaming a module.
- The ``keep`` attribute on cells and wires is used to mark objects that should
never be removed by the optimizer. This is used for example for cells that
have hidden connections that are not part of the netlist, such as IO pads.
Setting the ``keep`` attribute on a module has the same effect as setting it
on all instances of the module.
- The ``keep_hierarchy`` attribute on cells and modules keeps the ``flatten``
command from flattening the indicated cells and modules.
- The ``init`` attribute on wires is set by the frontend when a register is
initialized "FPGA-style" with ``reg foo = val``. It can be used during
synthesis to add the necessary reset logic.
- The ``top`` attribute on a module marks this module as the top of the
design hierarchy. The ``hierarchy`` command sets this attribute when called
with ``-top``. Other commands, such as ``flatten`` and various backends
use this attribute to determine the top module.
- The ``src`` attribute is set on cells and wires created by to the string
``<hdl-file-name>:<line-number>`` by the HDL front-end and is then carried
through the synthesis. When entities are combined, a new |-separated
string is created that contains all the string from the original entities.
- The ``defaultvalue`` attribute is used to store default values for
module inputs. The attribute is attached to the input wire by the HDL
front-end when the input is declared with a default value.
- The ``parameter`` and ``localparam`` attributes are used to mark wires
that represent module parameters or localparams (when the HDL front-end
is run in -pwires mode).
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
the non-standard ``{* ... *}`` attribute syntax to set default attributes
for everything that comes after the ``{* ... *}`` statement. (Reset
by adding an empty ``{* *}`` statement.)
- In module parameter and port declarations, and cell port and parameter
lists, a trailing comma is ignored. This simplifies writing Verilog code
generators a bit in some cases.
- Modules can be declared with ``module mod_name(...);`` (with three dots
instead of a list of module ports). With this syntax it is sufficient
to simply declare a module port as 'input' or 'output' in the module
body.
- When defining a macro with `define, all text between triple double quotes
is interpreted as macro body, even if it contains unescaped newlines. The
triple double quotes are removed from the macro body. For example:
`define MY_MACRO(a, b) """
assign a = 23;
assign b = 42;
"""
- The attribute ``via_celltype`` can be used to implement a Verilog task or
function by instantiating the specified cell type. The value is the name
of the cell type to use. For functions the name of the output port can
be specified by appending it to the cell type separated by a whitespace.
The body of the task or function is unused in this case and can be used
to specify a behavioral model of the cell type for simulation. For example:
module my_add3(A, B, C, Y);
parameter WIDTH = 8;
input [WIDTH-1:0] A, B, C;
output [WIDTH-1:0] Y;
...
endmodule
module top;
...
(* via_celltype = "my_add3 Y" *)
(* via_celltype_defparam_WIDTH = 32 *)
function [31:0] add3;
input [31:0] A, B, C;
begin
add3 = A + B + C;
end
endfunction
...
endmodule
- A limited subset of DPI-C functions is supported. The plugin mechanism
(see ``help plugin``) can be used to load .so files with implementations
of DPI-C routines. As a non-standard extension it is possible to specify
a plugin alias using the ``<alias>:`` syntax. For example:
module dpitest;
import "DPI-C" function foo:round = real my_round (real);
parameter real r = my_round(12.345);
endmodule
$ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v'
- Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant
expressions as ``<size>``. If the expression is not a simple identifier, it
must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010``
- The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in
initial blocks in an unconditional context (only if/case statements on
expressions over parameters and constant values are allowed). The intended
use for this is synthesis-time DRC.
- There is limited support for converting specify .. endspecify statements to
special ``$specify2``, ``$specify3``, and ``$specrule`` cells, for use in
blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this
functionality. (By default specify .. endspecify blocks are ignored.)
Non-standard or SystemVerilog features for formal verification
==============================================================
- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
when ``read_verilog`` is called with ``-formal``.
- The system task ``$initstate`` evaluates to 1 in the initial state and
to 0 otherwise.
- The system function ``$anyconst`` evaluates to any constant value. This is
equivalent to declaring a reg as ``rand const``, but also works outside
of checkers. (Yosys also supports ``rand const`` outside checkers.)
- The system function ``$anyseq`` evaluates to any value, possibly a different
value in each cycle. This is equivalent to declaring a reg as ``rand``,
but also works outside of checkers. (Yosys also supports ``rand``
variables outside checkers.)
- The system functions ``$allconst`` and ``$allseq`` can be used to construct
formal exist-forall problems. Assumptions only hold if the trace satisfies
the assumption for all ``$allconst/$allseq`` values. For assertions and cover
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
the property (similar to ``$anyconst/$anyseq``).
- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq`` attribute
(for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven
by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
supported in any clocked block.
- The syntax ``@($global_clock)`` can be used to create FFs that have no
explicit clock input (``$ff`` cells). The same can be achieved by using
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
is marked with the ``(* gclk *)`` Verilog attribute.
Supported features from SystemVerilog
=====================================
When ``read_verilog`` is called with ``-sv``, it accepts some language features
from SystemVerilog:
- The ``assert`` statement from SystemVerilog is supported in its most basic
form. In module context: ``assert property (<expression>);`` and within an
always block: ``assert(<expression>);``. It is transformed to an ``$assert`` cell.
- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
also supported. The same limitations as with the ``assert`` statement apply.
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
and ``bit`` are supported.
- Declaring free variables with ``rand`` and ``rand const`` is supported.
- Checkers without a port list that do not need to be instantiated (but instead
behave like a named block) are supported.
- SystemVerilog packages are supported. Once a SystemVerilog file is read
into a design with ``read_verilog``, all its packages are available to
SystemVerilog files being read into the same design afterwards.
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
ports are inputs or outputs are supported.
Building the documentation
==========================
Note that there is no need to build the manual if you just want to read it.
Simply download the PDF from http://www.clifford.at/yosys/documentation.html
instead.
On Ubuntu, texlive needs these packages to be able to build the manual:
sudo apt-get install texlive-binaries
sudo apt-get install texlive-science # install algorithm2e.sty
sudo apt-get install texlive-bibtex-extra # gets multibib.sty
sudo apt-get install texlive-fonts-extra # gets skull.sty and dsfont.sty
sudo apt-get install texlive-publishers # IEEEtran.cls
Also the non-free font luximono should be installed, there is unfortunately
no Ubuntu package for this so it should be installed separately using
`getnonfreefonts`:
wget https://tug.org/fonts/getnonfreefonts/install-getnonfreefonts
sudo texlua install-getnonfreefonts # will install to /usr/local by default, can be changed by editing BINDIR at MANDIR at the top of the script
getnonfreefonts luximono # installs to /home/user/texmf
Then execute, from the root of the repository:
make manual
Notes:
- To run `make manual` you need to have installed Yosys with `make install`,
otherwise it will fail on finding `kernel/yosys.h` while building
`PRESENTATION_Prog`.

View File

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

View File

@ -1,790 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
void aiger_encode(std::ostream &f, int x)
{
log_assert(x >= 0);
while (x & ~0x7f) {
f.put((x & 0x7f) | 0x80);
x = x >> 7;
}
f.put(x);
}
struct AigerWriter
{
Module *module;
bool zinit_mode;
SigMap sigmap;
dict<SigBit, bool> init_map;
pool<SigBit> input_bits, output_bits;
dict<SigBit, SigBit> not_map, ff_map, alias_map;
dict<SigBit, pair<SigBit, SigBit>> and_map;
vector<pair<SigBit, SigBit>> asserts, assumes;
vector<pair<SigBit, SigBit>> liveness, fairness;
pool<SigBit> initstate_bits;
vector<pair<int, int>> aig_gates;
vector<int> aig_latchin, aig_latchinit, aig_outputs;
int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0;
int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0;
dict<SigBit, int> aig_map;
dict<SigBit, int> ordered_outputs;
dict<SigBit, int> ordered_latches;
dict<SigBit, int> init_inputs;
int initstate_ff = 0;
int mkgate(int a0, int a1)
{
aig_m++, aig_a++;
aig_gates.push_back(a0 > a1 ? make_pair(a0, a1) : make_pair(a1, a0));
return 2*aig_m;
}
int bit2aig(SigBit bit)
{
if (aig_map.count(bit) == 0)
{
aig_map[bit] = -1;
if (initstate_bits.count(bit)) {
log_assert(initstate_ff > 0);
aig_map[bit] = initstate_ff;
} else
if (not_map.count(bit)) {
int a = bit2aig(not_map.at(bit)) ^ 1;
aig_map[bit] = a;
} else
if (and_map.count(bit)) {
auto args = and_map.at(bit);
int a0 = bit2aig(args.first);
int a1 = bit2aig(args.second);
aig_map[bit] = mkgate(a0, a1);
} else
if (alias_map.count(bit)) {
int a = bit2aig(alias_map.at(bit));
aig_map[bit] = a;
}
if (bit == State::Sx || bit == State::Sz)
log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n");
}
log_assert(aig_map.at(bit) >= 0);
return aig_map.at(bit);
}
AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
{
pool<SigBit> undriven_bits;
pool<SigBit> unused_bits;
// promote public wires
for (auto wire : module->wires())
if (wire->name[0] == '\\')
sigmap.add(wire);
// promote input wires
for (auto wire : module->wires())
if (wire->port_input)
sigmap.add(wire);
// promote output wires
for (auto wire : module->wires())
if (wire->port_output)
sigmap.add(wire);
for (auto wire : module->wires())
{
if (wire->attributes.count("\\init")) {
SigSpec initsig = sigmap(wire);
Const initval = wire->attributes.at("\\init");
for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++)
if (initval[i] == State::S0 || initval[i] == State::S1)
init_map[initsig[i]] = initval[i] == State::S1;
}
for (int i = 0; i < GetSize(wire); i++)
{
SigBit wirebit(wire, i);
SigBit bit = sigmap(wirebit);
if (bit.wire == nullptr) {
if (wire->port_output) {
aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
output_bits.insert(wirebit);
}
continue;
}
undriven_bits.insert(bit);
unused_bits.insert(bit);
if (wire->port_input)
input_bits.insert(bit);
if (wire->port_output) {
if (bit != wirebit)
alias_map[wirebit] = bit;
output_bits.insert(wirebit);
}
}
}
for (auto bit : input_bits)
undriven_bits.erase(bit);
for (auto bit : output_bits)
unused_bits.erase(bit);
for (auto cell : module->cells())
{
if (cell->type == "$_NOT_")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
unused_bits.erase(A);
undriven_bits.erase(Y);
not_map[Y] = A;
continue;
}
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_"))
{
SigBit D = sigmap(cell->getPort("\\D").as_bit());
SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
unused_bits.erase(D);
undriven_bits.erase(Q);
ff_map[Q] = D;
continue;
}
if (cell->type == "$_AND_")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
SigBit B = sigmap(cell->getPort("\\B").as_bit());
SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
unused_bits.erase(A);
unused_bits.erase(B);
undriven_bits.erase(Y);
and_map[Y] = make_pair(A, B);
continue;
}
if (cell->type == "$initstate")
{
SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
undriven_bits.erase(Y);
initstate_bits.insert(Y);
continue;
}
if (cell->type == "$assert")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
unused_bits.erase(A);
unused_bits.erase(EN);
asserts.push_back(make_pair(A, EN));
continue;
}
if (cell->type == "$assume")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
unused_bits.erase(A);
unused_bits.erase(EN);
assumes.push_back(make_pair(A, EN));
continue;
}
if (cell->type == "$live")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
unused_bits.erase(A);
unused_bits.erase(EN);
liveness.push_back(make_pair(A, EN));
continue;
}
if (cell->type == "$fair")
{
SigBit A = sigmap(cell->getPort("\\A").as_bit());
SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
unused_bits.erase(A);
unused_bits.erase(EN);
fairness.push_back(make_pair(A, EN));
continue;
}
if (cell->type == "$anyconst")
{
for (auto bit : sigmap(cell->getPort("\\Y"))) {
undriven_bits.erase(bit);
ff_map[bit] = bit;
}
continue;
}
if (cell->type == "$anyseq")
{
for (auto bit : sigmap(cell->getPort("\\Y"))) {
undriven_bits.erase(bit);
input_bits.insert(bit);
}
continue;
}
log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
}
for (auto bit : unused_bits)
undriven_bits.erase(bit);
if (!undriven_bits.empty()) {
undriven_bits.sort();
for (auto bit : undriven_bits) {
log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
input_bits.insert(bit);
}
log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module));
}
init_map.sort();
input_bits.sort();
output_bits.sort();
not_map.sort();
ff_map.sort();
and_map.sort();
aig_map[State::S0] = 0;
aig_map[State::S1] = 1;
for (auto bit : input_bits) {
aig_m++, aig_i++;
aig_map[bit] = 2*aig_m;
}
if (imode && input_bits.empty()) {
aig_m++, aig_i++;
}
if (zinit_mode)
{
for (auto it : ff_map) {
if (init_map.count(it.first))
continue;
aig_m++, aig_i++;
init_inputs[it.first] = 2*aig_m;
}
}
int fair_live_inputs_cnt = GetSize(liveness);
int fair_live_inputs_m = aig_m;
aig_m += fair_live_inputs_cnt;
aig_i += fair_live_inputs_cnt;
for (auto it : ff_map) {
aig_m++, aig_l++;
aig_map[it.first] = 2*aig_m;
ordered_latches[it.first] = aig_l-1;
if (init_map.count(it.first) == 0)
aig_latchinit.push_back(2);
else
aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0);
}
if (!initstate_bits.empty() || !init_inputs.empty()) {
aig_m++, aig_l++;
initstate_ff = 2*aig_m+1;
aig_latchinit.push_back(0);
}
int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness);
int fair_live_latches_m = aig_m;
int fair_live_latches_l = aig_l;
aig_m += fair_live_latches_cnt;
aig_l += fair_live_latches_cnt;
for (int i = 0; i < fair_live_latches_cnt; i++)
aig_latchinit.push_back(0);
if (zinit_mode)
{
for (auto it : ff_map)
{
int l = ordered_latches[it.first];
if (aig_latchinit.at(l) == 1)
aig_map[it.first] ^= 1;
if (aig_latchinit.at(l) == 2)
{
int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
}
}
}
for (auto it : ff_map) {
int a = bit2aig(it.second);
int l = ordered_latches[it.first];
if (zinit_mode && aig_latchinit.at(l) == 1)
aig_latchin.push_back(a ^ 1);
else
aig_latchin.push_back(a);
}
if (!initstate_bits.empty() || !init_inputs.empty())
aig_latchin.push_back(1);
for (auto bit : output_bits) {
aig_o++;
ordered_outputs[bit] = aig_o-1;
aig_outputs.push_back(bit2aig(bit));
}
if (omode && output_bits.empty()) {
aig_o++;
aig_outputs.push_back(0);
}
for (auto it : asserts) {
aig_b++;
int bit_a = bit2aig(it.first);
int bit_en = bit2aig(it.second);
aig_outputs.push_back(mkgate(bit_a^1, bit_en));
}
if (bmode && asserts.empty()) {
aig_b++;
aig_outputs.push_back(0);
}
for (auto it : assumes) {
aig_c++;
int bit_a = bit2aig(it.first);
int bit_en = bit2aig(it.second);
aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1);
}
for (auto it : liveness)
{
int input_m = ++fair_live_inputs_m;
int latch_m1 = ++fair_live_latches_m;
int latch_m2 = ++fair_live_latches_m;
log_assert(GetSize(aig_latchin) == fair_live_latches_l);
fair_live_latches_l += 2;
int bit_a = bit2aig(it.first);
int bit_en = bit2aig(it.second);
int bit_s = 2*input_m;
int bit_q1 = 2*latch_m1;
int bit_q2 = 2*latch_m2;
int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1;
int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1;
aig_j++;
aig_latchin.push_back(bit_d1);
aig_latchin.push_back(bit_d2);
aig_outputs.push_back(mkgate(bit_q1, bit_q2^1));
}
for (auto it : fairness)
{
int latch_m = ++fair_live_latches_m;
log_assert(GetSize(aig_latchin) == fair_live_latches_l);
fair_live_latches_l += 1;
int bit_a = bit2aig(it.first);
int bit_en = bit2aig(it.second);
int bit_q = 2*latch_m;
aig_f++;
aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1));
aig_outputs.push_back(bit_q^1);
}
}
void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode)
{
int aig_obc = aig_o + aig_b + aig_c;
int aig_obcj = aig_obc + aig_j;
int aig_obcjf = aig_obcj + aig_f;
log_assert(aig_m == aig_i + aig_l + aig_a);
log_assert(aig_l == GetSize(aig_latchin));
log_assert(aig_l == GetSize(aig_latchinit));
log_assert(aig_obcjf == GetSize(aig_outputs));
if (miter_mode) {
if (aig_b || aig_c || aig_j || aig_f)
log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n");
f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o);
} else {
f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a);
if (aig_b || aig_c || aig_j || aig_f)
f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f);
f << stringf("\n");
}
if (ascii_mode)
{
for (int i = 0; i < aig_i; i++)
f << stringf("%d\n", 2*i+2);
for (int i = 0; i < aig_l; i++) {
if (zinit_mode || aig_latchinit.at(i) == 0)
f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i));
else if (aig_latchinit.at(i) == 1)
f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i));
else if (aig_latchinit.at(i) == 2)
f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2);
}
for (int i = 0; i < aig_obc; i++)
f << stringf("%d\n", aig_outputs.at(i));
for (int i = aig_obc; i < aig_obcj; i++)
f << stringf("1\n");
for (int i = aig_obc; i < aig_obcj; i++)
f << stringf("%d\n", aig_outputs.at(i));
for (int i = aig_obcj; i < aig_obcjf; i++)
f << stringf("%d\n", aig_outputs.at(i));
for (int i = 0; i < aig_a; i++)
f << stringf("%d %d %d\n", 2*(aig_i+aig_l+i)+2, aig_gates.at(i).first, aig_gates.at(i).second);
}
else
{
for (int i = 0; i < aig_l; i++) {
if (zinit_mode || aig_latchinit.at(i) == 0)
f << stringf("%d\n", aig_latchin.at(i));
else if (aig_latchinit.at(i) == 1)
f << stringf("%d 1\n", aig_latchin.at(i));
else if (aig_latchinit.at(i) == 2)
f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2);
}
for (int i = 0; i < aig_obc; i++)
f << stringf("%d\n", aig_outputs.at(i));
for (int i = aig_obc; i < aig_obcj; i++)
f << stringf("1\n");
for (int i = aig_obc; i < aig_obcj; i++)
f << stringf("%d\n", aig_outputs.at(i));
for (int i = aig_obcj; i < aig_obcjf; i++)
f << stringf("%d\n", aig_outputs.at(i));
for (int i = 0; i < aig_a; i++) {
int lhs = 2*(aig_i+aig_l+i)+2;
int rhs0 = aig_gates.at(i).first;
int rhs1 = aig_gates.at(i).second;
int delta0 = lhs - rhs0;
int delta1 = rhs0 - rhs1;
aiger_encode(f, delta0);
aiger_encode(f, delta1);
}
}
if (symbols_mode)
{
dict<string, vector<string>> symbols;
for (auto wire : module->wires())
{
if (wire->name[0] == '$')
continue;
SigSpec sig = sigmap(wire);
for (int i = 0; i < GetSize(wire); i++)
{
if (sig[i].wire == nullptr) {
if (wire->port_output)
sig[i] = SigBit(wire, i);
else
continue;
}
if (wire->port_input) {
int a = aig_map.at(sig[i]);
log_assert((a & 1) == 0);
if (GetSize(wire) != 1)
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i));
else
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire)));
}
if (wire->port_output) {
int o = ordered_outputs.at(SigSpec(wire, i));
if (GetSize(wire) != 1)
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i));
else
symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
}
if (init_inputs.count(sig[i])) {
int a = init_inputs.at(sig[i]);
log_assert((a & 1) == 0);
if (GetSize(wire) != 1)
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
else
symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
}
if (ordered_latches.count(sig[i])) {
int l = ordered_latches.at(sig[i]);
const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
if (GetSize(wire) != 1)
symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i));
else
symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire)));
}
}
}
symbols.sort();
for (auto &sym : symbols) {
f << sym.first;
std::sort(sym.second.begin(), sym.second.end());
for (auto &s : sym.second)
f << " " << s;
f << std::endl;
}
}
f << stringf("c\nGenerated by %s\n", yosys_version_str);
}
void write_map(std::ostream &f, bool verbose_map)
{
dict<int, string> input_lines;
dict<int, string> init_lines;
dict<int, string> output_lines;
dict<int, string> latch_lines;
dict<int, string> wire_lines;
for (auto wire : module->wires())
{
if (!verbose_map && wire->name[0] == '$')
continue;
SigSpec sig = sigmap(wire);
for (int i = 0; i < GetSize(wire); i++)
{
if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr)
continue;
int a = aig_map.at(sig[i]);
if (verbose_map)
wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire));
if (wire->port_input) {
log_assert((a & 1) == 0);
input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
}
if (wire->port_output) {
int o = ordered_outputs.at(sig[i]);
output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire));
}
if (init_inputs.count(sig[i])) {
int a = init_inputs.at(sig[i]);
log_assert((a & 1) == 0);
init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
}
if (ordered_latches.count(sig[i])) {
int l = ordered_latches.at(sig[i]);
if (zinit_mode && (aig_latchinit.at(l) == 1))
latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire));
else
latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire));
}
}
}
input_lines.sort();
for (auto &it : input_lines)
f << it.second;
init_lines.sort();
for (auto &it : init_lines)
f << it.second;
output_lines.sort();
for (auto &it : output_lines)
f << it.second;
latch_lines.sort();
for (auto &it : latch_lines)
f << it.second;
wire_lines.sort();
for (auto &it : wire_lines)
f << it.second;
}
};
struct AigerBackend : public Backend {
AigerBackend() : Backend("aiger", "write design to AIGER file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_aiger [options] [filename]\n");
log("\n");
log("Write the current design to an AIGER file. The design must be flattened and\n");
log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n");
log("$assert and $assume cells, and $initstate cells.\n");
log("\n");
log("$assert and $assume cells are converted to AIGER bad state properties and\n");
log("invariant constraints.\n");
log("\n");
log(" -ascii\n");
log(" write ASCII version of AGIER format\n");
log("\n");
log(" -zinit\n");
log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
log(" uninitialized FFs.\n");
log("\n");
log(" -miter\n");
log(" design outputs are AIGER bad state properties\n");
log("\n");
log(" -symbols\n");
log(" include a symbol table in the generated AIGER file\n");
log("\n");
log(" -map <filename>\n");
log(" write an extra file with port and latch symbols\n");
log("\n");
log(" -vmap <filename>\n");
log(" like -map, but more verbose\n");
log("\n");
log(" -I, -O, -B\n");
log(" If the design contains no input/output/assert then create one\n");
log(" dummy input/output/bad_state pin to make the tools reading the\n");
log(" AIGER file happy.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool ascii_mode = false;
bool zinit_mode = false;
bool miter_mode = false;
bool symbols_mode = false;
bool verbose_map = false;
bool imode = false;
bool omode = false;
bool bmode = false;
std::string map_filename;
log_header(design, "Executing AIGER backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-ascii") {
ascii_mode = true;
continue;
}
if (args[argidx] == "-zinit") {
zinit_mode = true;
continue;
}
if (args[argidx] == "-miter") {
miter_mode = true;
continue;
}
if (args[argidx] == "-symbols") {
symbols_mode = true;
continue;
}
if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) {
map_filename = args[++argidx];
continue;
}
if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) {
map_filename = args[++argidx];
verbose_map = true;
continue;
}
if (args[argidx] == "-I") {
imode = true;
continue;
}
if (args[argidx] == "-O") {
omode = true;
continue;
}
if (args[argidx] == "-B") {
bmode = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
Module *top_module = design->top_module();
if (top_module == nullptr)
log_error("Can't find top module in current design!\n");
AigerWriter writer(top_module, zinit_mode, imode, omode, bmode);
writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
if (!map_filename.empty()) {
rewrite_filename(filename);
std::ofstream mapf;
mapf.open(map_filename.c_str(), std::ofstream::trunc);
if (mapf.fail())
log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
writer.write_map(mapf, verbose_map);
}
}
} AigerBackend;
PRIVATE_NAMESPACE_END

View File

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

View File

@ -1,682 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
// [[CITE]] Berkeley Logic Interchange Format (BLIF)
// University of California. Berkeley. July 28, 1992
// http://www.ece.cmu.edu/~ee760/760docs/blif.pdf
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct BlifDumperConfig
{
bool icells_mode;
bool conn_mode;
bool impltf_mode;
bool gates_mode;
bool cname_mode;
bool iname_mode;
bool param_mode;
bool attr_mode;
bool iattr_mode;
bool blackbox_mode;
bool noalias_mode;
std::string buf_type, buf_in, buf_out;
std::map<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::IdString>> unbuf_types;
std::string true_type, true_out, false_type, false_out, undef_type, undef_out;
BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false),
cname_mode(false), iname_mode(false), param_mode(false), attr_mode(false), iattr_mode(false),
blackbox_mode(false), noalias_mode(false) { }
};
struct BlifDumper
{
std::ostream &f;
RTLIL::Module *module;
RTLIL::Design *design;
BlifDumperConfig *config;
CellTypes ct;
SigMap sigmap;
dict<SigBit, int> init_bits;
BlifDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig *config) :
f(f), module(module), design(design), config(config), ct(design), sigmap(module)
{
for (Wire *wire : module->wires())
if (wire->attributes.count("\\init")) {
SigSpec initsig = sigmap(wire);
Const initval = wire->attributes.at("\\init");
for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
switch (initval[i]) {
case State::S0:
init_bits[initsig[i]] = 0;
break;
case State::S1:
init_bits[initsig[i]] = 1;
break;
default:
break;
}
}
}
vector<shared_str> cstr_buf;
pool<SigBit> cstr_bits_seen;
const char *cstr(RTLIL::IdString id)
{
std::string str = RTLIL::unescape_id(id);
for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?';
cstr_buf.push_back(str);
return cstr_buf.back().c_str();
}
const char *cstr(RTLIL::SigBit sig)
{
cstr_bits_seen.insert(sig);
if (sig.wire == NULL) {
if (sig == RTLIL::State::S0) return config->false_type == "-" || config->false_type == "+" ? config->false_out.c_str() : "$false";
if (sig == RTLIL::State::S1) return config->true_type == "-" || config->true_type == "+" ? config->true_out.c_str() : "$true";
return config->undef_type == "-" || config->undef_type == "+" ? config->undef_out.c_str() : "$undef";
}
std::string str = RTLIL::unescape_id(sig.wire->name);
for (size_t i = 0; i < str.size(); i++)
if (str[i] == '#' || str[i] == '=' || str[i] == '<' || str[i] == '>')
str[i] = '?';
if (sig.wire->width != 1)
str += stringf("[%d]", sig.wire->upto ? sig.wire->start_offset+sig.wire->width-sig.offset-1 : sig.wire->start_offset+sig.offset);
cstr_buf.push_back(str);
return cstr_buf.back().c_str();
}
const char *cstr_init(RTLIL::SigBit sig)
{
sigmap.apply(sig);
if (init_bits.count(sig) == 0)
return " 2";
string str = stringf(" %d", init_bits.at(sig));
cstr_buf.push_back(str);
return cstr_buf.back().c_str();
}
const char *subckt_or_gate(std::string cell_type)
{
if (!config->gates_mode)
return "subckt";
if (!design->modules_.count(RTLIL::escape_id(cell_type)))
return "gate";
if (design->modules_.at(RTLIL::escape_id(cell_type))->get_blackbox_attribute())
return "gate";
return "subckt";
}
void dump_params(const char *command, dict<IdString, Const> &params)
{
for (auto &param : params) {
f << stringf("%s %s ", command, RTLIL::id2cstr(param.first));
if (param.second.flags & RTLIL::CONST_FLAG_STRING) {
std::string str = param.second.decode_string();
f << stringf("\"");
for (char ch : str)
if (ch == '"' || ch == '\\')
f << stringf("\\%c", ch);
else if (ch < 32 || ch >= 127)
f << stringf("\\%03o", ch);
else
f << stringf("%c", ch);
f << stringf("\"\n");
} else
f << stringf("%s\n", param.second.as_string().c_str());
}
}
void dump()
{
f << stringf("\n");
f << stringf(".model %s\n", cstr(module->name));
std::map<int, RTLIL::Wire*> inputs, outputs;
for (auto &wire_it : module->wires_) {
RTLIL::Wire *wire = wire_it.second;
if (wire->port_input)
inputs[wire->port_id] = wire;
if (wire->port_output)
outputs[wire->port_id] = wire;
}
f << stringf(".inputs");
for (auto &it : inputs) {
RTLIL::Wire *wire = it.second;
for (int i = 0; i < wire->width; i++)
f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i)));
}
f << stringf("\n");
f << stringf(".outputs");
for (auto &it : outputs) {
RTLIL::Wire *wire = it.second;
for (int i = 0; i < wire->width; i++)
f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i)));
}
f << stringf("\n");
if (module->get_blackbox_attribute()) {
f << stringf(".blackbox\n");
f << stringf(".end\n");
return;
}
if (!config->impltf_mode) {
if (!config->false_type.empty()) {
if (config->false_type == "+")
f << stringf(".names %s\n", config->false_out.c_str());
else if (config->false_type != "-")
f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type),
config->false_type.c_str(), config->false_out.c_str());
} else
f << stringf(".names $false\n");
if (!config->true_type.empty()) {
if (config->true_type == "+")
f << stringf(".names %s\n1\n", config->true_out.c_str());
else if (config->true_type != "-")
f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type),
config->true_type.c_str(), config->true_out.c_str());
} else
f << stringf(".names $true\n1\n");
if (!config->undef_type.empty()) {
if (config->undef_type == "+")
f << stringf(".names %s\n", config->undef_out.c_str());
else if (config->undef_type != "-")
f << stringf(".%s %s %s=$undef\n", subckt_or_gate(config->undef_type),
config->undef_type.c_str(), config->undef_out.c_str());
} else
f << stringf(".names $undef\n");
}
for (auto &cell_it : module->cells_)
{
RTLIL::Cell *cell = cell_it.second;
if (config->unbuf_types.count(cell->type)) {
auto portnames = config->unbuf_types.at(cell->type);
f << stringf(".names %s %s\n1 1\n",
cstr(cell->getPort(portnames.first)), cstr(cell->getPort(portnames.second)));
continue;
}
if (!config->icells_mode && cell->type == "$_NOT_") {
f << stringf(".names %s %s\n0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AND_") {
f << stringf(".names %s %s %s\n11 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OR_") {
f << stringf(".names %s %s %s\n1- 1\n-1 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_XOR_") {
f << stringf(".names %s %s %s\n10 1\n01 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NAND_") {
f << stringf(".names %s %s %s\n0- 1\n-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NOR_") {
f << stringf(".names %s %s %s\n00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_XNOR_") {
f << stringf(".names %s %s %s\n11 1\n00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_ANDNOT_") {
f << stringf(".names %s %s %s\n10 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_ORNOT_") {
f << stringf(".names %s %s %s\n1- 1\n-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AOI3_") {
f << stringf(".names %s %s %s %s\n-00 1\n0-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OAI3_") {
f << stringf(".names %s %s %s %s\n00- 1\n--0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AOI4_") {
f << stringf(".names %s %s %s %s %s\n-0-0 1\n-00- 1\n0--0 1\n0-0- 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OAI4_") {
f << stringf(".names %s %s %s %s %s\n00-- 1\n--00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_MUX_") {
f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DFF_N_") {
f << stringf(".latch %s %s fe %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DFF_P_") {
f << stringf(".latch %s %s re %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DLATCH_N_") {
f << stringf(".latch %s %s al %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\E")), cstr_init(cell->getPort("\\Q")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DLATCH_P_") {
f << stringf(".latch %s %s ah %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\E")), cstr_init(cell->getPort("\\Q")));
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$lut") {
f << stringf(".names");
auto &inputs = cell->getPort("\\A");
auto width = cell->parameters.at("\\WIDTH").as_int();
log_assert(inputs.size() == width);
for (int i = width-1; i >= 0; i--)
f << stringf(" %s", cstr(inputs.extract(i, 1)));
auto &output = cell->getPort("\\Y");
log_assert(output.size() == 1);
f << stringf(" %s", cstr(output));
f << stringf("\n");
RTLIL::SigSpec mask = cell->parameters.at("\\LUT");
for (int i = 0; i < (1 << width); i++)
if (mask[i] == RTLIL::S1) {
for (int j = width-1; j >= 0; j--) {
f << ((i>>j)&1 ? '1' : '0');
}
f << " 1\n";
}
goto internal_cell;
}
if (!config->icells_mode && cell->type == "$sop") {
f << stringf(".names");
auto &inputs = cell->getPort("\\A");
auto width = cell->parameters.at("\\WIDTH").as_int();
auto depth = cell->parameters.at("\\DEPTH").as_int();
vector<State> table = cell->parameters.at("\\TABLE").bits;
while (GetSize(table) < 2*width*depth)
table.push_back(State::S0);
log_assert(inputs.size() == width);
for (int i = 0; i < width; i++)
f << stringf(" %s", cstr(inputs.extract(i, 1)));
auto &output = cell->getPort("\\Y");
log_assert(output.size() == 1);
f << stringf(" %s", cstr(output));
f << stringf("\n");
for (int i = 0; i < depth; i++) {
for (int j = 0; j < width; j++) {
bool pat0 = table.at(2*width*i + 2*j + 0) == State::S1;
bool pat1 = table.at(2*width*i + 2*j + 1) == State::S1;
if (pat0 && !pat1) f << "0";
else if (!pat0 && pat1) f << "1";
else f << "-";
}
f << " 1\n";
}
goto internal_cell;
}
f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type));
for (auto &conn : cell->connections())
{
if (conn.second.size() == 1) {
f << stringf(" %s=%s", cstr(conn.first), cstr(conn.second[0]));
continue;
}
Module *m = design->module(cell->type);
Wire *w = m ? m->wire(conn.first) : nullptr;
if (w == nullptr) {
for (int i = 0; i < GetSize(conn.second); i++)
f << stringf(" %s[%d]=%s", cstr(conn.first), i, cstr(conn.second[i]));
} else {
for (int i = 0; i < std::min(GetSize(conn.second), GetSize(w)); i++) {
SigBit sig(w, i);
f << stringf(" %s[%d]=%s", cstr(conn.first), sig.wire->upto ?
sig.wire->start_offset+sig.wire->width-sig.offset-1 :
sig.wire->start_offset+sig.offset, cstr(conn.second[i]));
}
}
}
f << stringf("\n");
if (config->cname_mode)
f << stringf(".cname %s\n", cstr(cell->name));
if (config->attr_mode)
dump_params(".attr", cell->attributes);
if (config->param_mode)
dump_params(".param", cell->parameters);
if (0) {
internal_cell:
if (config->iname_mode)
f << stringf(".cname %s\n", cstr(cell->name));
if (config->iattr_mode)
dump_params(".attr", cell->attributes);
}
}
for (auto &conn : module->connections())
for (int i = 0; i < conn.first.size(); i++)
{
SigBit lhs_bit = conn.first[i];
SigBit rhs_bit = conn.second[i];
if (config->noalias_mode && cstr_bits_seen.count(lhs_bit) == 0)
continue;
if (config->conn_mode)
f << stringf(".conn %s %s\n", cstr(rhs_bit), cstr(lhs_bit));
else if (!config->buf_type.empty())
f << stringf(".%s %s %s=%s %s=%s\n", subckt_or_gate(config->buf_type), config->buf_type.c_str(),
config->buf_in.c_str(), cstr(rhs_bit), config->buf_out.c_str(), cstr(lhs_bit));
else
f << stringf(".names %s %s\n1 1\n", cstr(rhs_bit), cstr(lhs_bit));
}
f << stringf(".end\n");
}
static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig &config)
{
BlifDumper dumper(f, module, design, &config);
dumper.dump();
}
};
struct BlifBackend : public Backend {
BlifBackend() : Backend("blif", "write design to BLIF file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_blif [options] [filename]\n");
log("\n");
log("Write the current design to an BLIF file.\n");
log("\n");
log(" -top top_module\n");
log(" set the specified module as design top module\n");
log("\n");
log(" -buf <cell-type> <in-port> <out-port>\n");
log(" use cells of type <cell-type> with the specified port names for buffers\n");
log("\n");
log(" -unbuf <cell-type> <in-port> <out-port>\n");
log(" replace buffer cells with the specified name and port names with\n");
log(" a .names statement that models a buffer\n");
log("\n");
log(" -true <cell-type> <out-port>\n");
log(" -false <cell-type> <out-port>\n");
log(" -undef <cell-type> <out-port>\n");
log(" use the specified cell types to drive nets that are constant 1, 0, or\n");
log(" undefined. when '-' is used as <cell-type>, then <out-port> specifies\n");
log(" the wire name to be used for the constant signal and no cell driving\n");
log(" that wire is generated. when '+' is used as <cell-type>, then <out-port>\n");
log(" specifies the wire name to be used for the constant signal and a .names\n");
log(" statement is generated to drive the wire.\n");
log("\n");
log(" -noalias\n");
log(" if a net name is aliasing another net name, then by default a net\n");
log(" without fanout is created that is driven by the other net. This option\n");
log(" suppresses the generation of this nets without fanout.\n");
log("\n");
log("The following options can be useful when the generated file is not going to be\n");
log("read by a BLIF parser but a custom tool. It is recommended to not name the output\n");
log("file *.blif when any of this options is used.\n");
log("\n");
log(" -icells\n");
log(" do not translate Yosys's internal gates to generic BLIF logic\n");
log(" functions. Instead create .subckt or .gate lines for all cells.\n");
log("\n");
log(" -gates\n");
log(" print .gate instead of .subckt lines for all cells that are not\n");
log(" instantiations of other modules from this design.\n");
log("\n");
log(" -conn\n");
log(" do not generate buffers for connected wires. instead use the\n");
log(" non-standard .conn statement.\n");
log("\n");
log(" -attr\n");
log(" use the non-standard .attr statement to write cell attributes\n");
log("\n");
log(" -param\n");
log(" use the non-standard .param statement to write cell parameters\n");
log("\n");
log(" -cname\n");
log(" use the non-standard .cname statement to write cell names\n");
log("\n");
log(" -iname, -iattr\n");
log(" enable -cname and -attr functionality for .names statements\n");
log(" (the .cname and .attr statements will be included in the BLIF\n");
log(" output after the truth table for the .names statement)\n");
log("\n");
log(" -blackbox\n");
log(" write blackbox cells with .blackbox statement.\n");
log("\n");
log(" -impltf\n");
log(" do not write definitions for the $true, $false and $undef wires.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_module_name;
std::string buf_type, buf_in, buf_out;
std::string true_type, true_out;
std::string false_type, false_out;
BlifDumperConfig config;
log_header(design, "Executing BLIF backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-top" && argidx+1 < args.size()) {
top_module_name = args[++argidx];
continue;
}
if (args[argidx] == "-buf" && argidx+3 < args.size()) {
config.buf_type = args[++argidx];
config.buf_in = args[++argidx];
config.buf_out = args[++argidx];
continue;
}
if (args[argidx] == "-unbuf" && argidx+3 < args.size()) {
RTLIL::IdString unbuf_type = RTLIL::escape_id(args[++argidx]);
RTLIL::IdString unbuf_in = RTLIL::escape_id(args[++argidx]);
RTLIL::IdString unbuf_out = RTLIL::escape_id(args[++argidx]);
config.unbuf_types[unbuf_type] = std::pair<RTLIL::IdString, RTLIL::IdString>(unbuf_in, unbuf_out);
continue;
}
if (args[argidx] == "-true" && argidx+2 < args.size()) {
config.true_type = args[++argidx];
config.true_out = args[++argidx];
continue;
}
if (args[argidx] == "-false" && argidx+2 < args.size()) {
config.false_type = args[++argidx];
config.false_out = args[++argidx];
continue;
}
if (args[argidx] == "-undef" && argidx+2 < args.size()) {
config.undef_type = args[++argidx];
config.undef_out = args[++argidx];
continue;
}
if (args[argidx] == "-icells") {
config.icells_mode = true;
continue;
}
if (args[argidx] == "-gates") {
config.gates_mode = true;
continue;
}
if (args[argidx] == "-conn") {
config.conn_mode = true;
continue;
}
if (args[argidx] == "-cname") {
config.cname_mode = true;
continue;
}
if (args[argidx] == "-param") {
config.param_mode = true;
continue;
}
if (args[argidx] == "-attr") {
config.attr_mode = true;
continue;
}
if (args[argidx] == "-iname") {
config.iname_mode = true;
continue;
}
if (args[argidx] == "-iattr") {
config.iattr_mode = true;
continue;
}
if (args[argidx] == "-blackbox") {
config.blackbox_mode = true;
continue;
}
if (args[argidx] == "-impltf") {
config.impltf_mode = true;
continue;
}
if (args[argidx] == "-noalias") {
config.noalias_mode = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
if (top_module_name.empty())
for (auto & mod_it:design->modules_)
if (mod_it.second->get_bool_attribute("\\top"))
top_module_name = mod_it.first.str();
*f << stringf("# Generated by %s\n", yosys_version_str);
std::vector<RTLIL::Module*> mod_list;
design->sort();
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
if (module->get_blackbox_attribute() && !config.blackbox_mode)
continue;
if (module->processes.size() != 0)
log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name));
if (module->memories.size() != 0)
log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name));
if (module->name == RTLIL::escape_id(top_module_name)) {
BlifDumper::dump(*f, module, design, config);
top_module_name.clear();
continue;
}
mod_list.push_back(module);
}
if (!top_module_name.empty())
log_error("Can't find top module `%s'!\n", top_module_name.c_str());
for (auto module : mod_list)
BlifDumper::dump(*f, module, design, config);
}
} BlifBackend;
PRIVATE_NAMESPACE_END

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
#!/bin/bash
set -ex
rm -rf test_cells.tmp
mkdir -p test_cells.tmp
cd test_cells.tmp
../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod'
for fn in test_*.il; do
../../../yosys -p "
read_ilang $fn
rename gold gate
synth
read_ilang $fn
miter -equiv -make_assert -flatten gold gate main
hierarchy -top main
write_btor ${fn%.il}.btor
"
boolectormc -kmax 1 --trace-gen --stop-first -v ${fn%.il}.btor > ${fn%.il}.out
if grep " SATISFIABLE" ${fn%.il}.out; then
echo "Check failed for ${fn%.il}."
exit 1
fi
done
echo "OK."

View File

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

View File

@ -1,451 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
// [[CITE]] EDIF Version 2 0 0 Grammar
// http://web.archive.org/web/20050730021644/http://www.edif.org/documentation/BNF_GRAMMAR/index.html
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str()
#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br).c_str()
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str()
struct EdifNames
{
int counter;
char delim_left, delim_right;
std::set<std::string> generated_names, used_names;
std::map<std::string, std::string> name_map;
EdifNames() : counter(1), delim_left('['), delim_right(']') { }
std::string operator()(std::string id, bool define, bool port_rename = false, int range_left = 0, int range_right = 0)
{
if (define) {
std::string new_id = operator()(id, false);
if (port_rename)
return stringf("(rename %s \"%s%c%d:%d%c\")", new_id.c_str(), id.c_str(), delim_left, range_left, range_right, delim_right);
return new_id != id ? stringf("(rename %s \"%s\")", new_id.c_str(), id.c_str()) : id;
}
if (name_map.count(id) > 0)
return name_map.at(id);
if (generated_names.count(id) > 0)
goto do_rename;
if (id == "GND" || id == "VCC")
goto do_rename;
for (size_t i = 0; i < id.size(); i++) {
if ('A' <= id[i] && id[i] <= 'Z')
continue;
if ('a' <= id[i] && id[i] <= 'z')
continue;
if ('0' <= id[i] && id[i] <= '9' && i > 0)
continue;
if (id[i] == '_' && i > 0 && i != id.size()-1)
continue;
goto do_rename;
}
used_names.insert(id);
return id;
do_rename:;
std::string gen_name;
while (1) {
gen_name = stringf("id%05d", counter++);
if (generated_names.count(gen_name) == 0 &&
used_names.count(gen_name) == 0)
break;
}
generated_names.insert(gen_name);
name_map[id] = gen_name;
return gen_name;
}
};
struct EdifBackend : public Backend {
EdifBackend() : Backend("edif", "write design to EDIF netlist file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_edif [options] [filename]\n");
log("\n");
log("Write the current design to an EDIF netlist file.\n");
log("\n");
log(" -top top_module\n");
log(" set the specified module as design top module\n");
log("\n");
log(" -nogndvcc\n");
log(" do not create \"GND\" and \"VCC\" cells. (this will produce an error\n");
log(" if the design contains constant nets. use \"hilomap\" to map to custom\n");
log(" constant drivers first)\n");
log("\n");
log(" -gndvccy\n");
log(" create \"GND\" and \"VCC\" cells with \"Y\" outputs. (the default is \"G\"\n");
log(" for \"GND\" and \"P\" for \"VCC\".)\n");
log("\n");
log(" -attrprop\n");
log(" create EDIF properties for cell attributes\n");
log("\n");
log(" -pvector {par|bra|ang}\n");
log(" sets the delimiting character for module port rename clauses to\n");
log(" parentheses, square brackets, or angle brackets.\n");
log("\n");
log("Unfortunately there are different \"flavors\" of the EDIF file format. This\n");
log("command generates EDIF files for the Xilinx place&route tools. It might be\n");
log("necessary to make small modifications to this command when a different tool\n");
log("is targeted.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing EDIF backend.\n");
std::string top_module_name;
bool port_rename = false;
bool attr_properties = false;
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
bool nogndvcc = false, gndvccy = false;
CellTypes ct(design);
EdifNames edif_names;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-top" && argidx+1 < args.size()) {
top_module_name = args[++argidx];
continue;
}
if (args[argidx] == "-nogndvcc") {
nogndvcc = true;
continue;
}
if (args[argidx] == "-gndvccy") {
gndvccy = true;
continue;
}
if (args[argidx] == "-attrprop") {
attr_properties = true;
continue;
}
if (args[argidx] == "-pvector" && argidx+1 < args.size()) {
std::string parray;
port_rename = true;
parray = args[++argidx];
if (parray == "par") {
edif_names.delim_left = '(';edif_names.delim_right = ')';
} else if (parray == "ang") {
edif_names.delim_left = '<';edif_names.delim_right = '>';
} else {
edif_names.delim_left = '[';edif_names.delim_right = ']';
}
continue;
}
break;
}
extra_args(f, filename, args, argidx);
if (top_module_name.empty())
for (auto & mod_it:design->modules_)
if (mod_it.second->get_bool_attribute("\\top"))
top_module_name = mod_it.first.str();
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
if (module->get_blackbox_attribute())
continue;
if (top_module_name.empty())
top_module_name = module->name.str();
if (module->processes.size() != 0)
log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name));
if (module->memories.size() != 0)
log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name));
for (auto cell_it : module->cells_)
{
RTLIL::Cell *cell = cell_it.second;
if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_blackbox_attribute()) {
lib_cell_ports[cell->type];
for (auto p : cell->connections())
lib_cell_ports[cell->type][p.first] = GetSize(p.second);
}
}
}
if (top_module_name.empty())
log_error("No module found in design!\n");
*f << stringf("(edif %s\n", EDIF_DEF(top_module_name));
*f << stringf(" (edifVersion 2 0 0)\n");
*f << stringf(" (edifLevel 0)\n");
*f << stringf(" (keywordMap (keywordLevel 0))\n");
*f << stringf(" (comment \"Generated by %s\")\n", yosys_version_str);
*f << stringf(" (external LIB\n");
*f << stringf(" (edifLevel 0)\n");
*f << stringf(" (technology (numberDefinition))\n");
if (!nogndvcc)
{
*f << stringf(" (cell GND\n");
*f << stringf(" (cellType GENERIC)\n");
*f << stringf(" (view VIEW_NETLIST\n");
*f << stringf(" (viewType NETLIST)\n");
*f << stringf(" (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'G');
*f << stringf(" )\n");
*f << stringf(" )\n");
*f << stringf(" (cell VCC\n");
*f << stringf(" (cellType GENERIC)\n");
*f << stringf(" (view VIEW_NETLIST\n");
*f << stringf(" (viewType NETLIST)\n");
*f << stringf(" (interface (port %c (direction OUTPUT)))\n", gndvccy ? 'Y' : 'P');
*f << stringf(" )\n");
*f << stringf(" )\n");
}
for (auto &cell_it : lib_cell_ports) {
*f << stringf(" (cell %s\n", EDIF_DEF(cell_it.first));
*f << stringf(" (cellType GENERIC)\n");
*f << stringf(" (view VIEW_NETLIST\n");
*f << stringf(" (viewType NETLIST)\n");
*f << stringf(" (interface\n");
for (auto &port_it : cell_it.second) {
const char *dir = "INOUT";
if (ct.cell_known(cell_it.first)) {
if (!ct.cell_output(cell_it.first, port_it.first))
dir = "INPUT";
else if (!ct.cell_input(cell_it.first, port_it.first))
dir = "OUTPUT";
}
if (port_it.second == 1)
*f << stringf(" (port %s (direction %s))\n", EDIF_DEF(port_it.first), dir);
else {
int b[2] = {port_it.second-1, 0};
auto m = design->module(cell_it.first);
if (m) {
auto w = m->wire(port_it.first);
if (w) {
b[w->upto ? 0 : 1] = w->start_offset;
b[w->upto ? 1 : 0] = w->start_offset+GetSize(w)-1;
}
}
*f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(port_it.first, port_rename, b[0], b[1]), port_it.second, dir);
}
}
*f << stringf(" )\n");
*f << stringf(" )\n");
*f << stringf(" )\n");
}
*f << stringf(" )\n");
std::vector<RTLIL::Module*> sorted_modules;
// extract module dependencies
std::map<RTLIL::Module*, std::set<RTLIL::Module*>> module_deps;
for (auto &mod_it : design->modules_) {
module_deps[mod_it.second] = std::set<RTLIL::Module*>();
for (auto &cell_it : mod_it.second->cells_)
if (design->modules_.count(cell_it.second->type) > 0)
module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type));
}
// simple good-enough topological sort
// (O(n*m) on n elements and depth m)
while (module_deps.size() > 0) {
size_t sorted_modules_idx = sorted_modules.size();
for (auto &it : module_deps) {
for (auto &dep : it.second)
if (module_deps.count(dep) > 0)
goto not_ready_yet;
// log("Next in topological sort: %s\n", RTLIL::id2cstr(it.first->name));
sorted_modules.push_back(it.first);
not_ready_yet:;
}
if (sorted_modules_idx == sorted_modules.size())
log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", RTLIL::id2cstr(module_deps.begin()->first->name));
while (sorted_modules_idx < sorted_modules.size())
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
}
*f << stringf(" (library DESIGN\n");
*f << stringf(" (edifLevel 0)\n");
*f << stringf(" (technology (numberDefinition))\n");
for (auto module : sorted_modules)
{
if (module->get_blackbox_attribute())
continue;
SigMap sigmap(module);
std::map<RTLIL::SigSpec, std::set<std::string>> net_join_db;
*f << stringf(" (cell %s\n", EDIF_DEF(module->name));
*f << stringf(" (cellType GENERIC)\n");
*f << stringf(" (view VIEW_NETLIST\n");
*f << stringf(" (viewType NETLIST)\n");
*f << stringf(" (interface\n");
for (auto &wire_it : module->wires_) {
RTLIL::Wire *wire = wire_it.second;
if (wire->port_id == 0)
continue;
const char *dir = "INOUT";
if (!wire->port_output)
dir = "INPUT";
else if (!wire->port_input)
dir = "OUTPUT";
if (wire->width == 1) {
*f << stringf(" (port %s (direction %s))\n", EDIF_DEF(wire->name), dir);
RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire));
net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name)));
} else {
int b[2];
b[wire->upto ? 0 : 1] = wire->start_offset;
b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1;
*f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir);
for (int i = 0; i < wire->width; i++) {
RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i));
net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1));
}
}
}
*f << stringf(" )\n");
*f << stringf(" (contents\n");
if (!nogndvcc) {
*f << stringf(" (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n");
*f << stringf(" (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n");
}
for (auto &cell_it : module->cells_) {
RTLIL::Cell *cell = cell_it.second;
*f << stringf(" (instance %s\n", EDIF_DEF(cell->name));
*f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type),
lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : "");
auto add_prop = [&](IdString name, Const val) {
if ((val.flags & RTLIL::CONST_FLAG_STRING) != 0)
*f << stringf("\n (property %s (string \"%s\"))", EDIF_DEF(name), val.decode_string().c_str());
else if (val.bits.size() <= 32 && RTLIL::SigSpec(val).is_fully_def())
*f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
else {
std::string hex_string = "";
for (size_t i = 0; i < val.bits.size(); i += 4) {
int digit_value = 0;
if (i+0 < val.bits.size() && val.bits.at(i+0) == RTLIL::State::S1) digit_value |= 1;
if (i+1 < val.bits.size() && val.bits.at(i+1) == RTLIL::State::S1) digit_value |= 2;
if (i+2 < val.bits.size() && val.bits.at(i+2) == RTLIL::State::S1) digit_value |= 4;
if (i+3 < val.bits.size() && val.bits.at(i+3) == RTLIL::State::S1) digit_value |= 8;
char digit_str[2] = { "0123456789abcdef"[digit_value], 0 };
hex_string = std::string(digit_str) + hex_string;
}
*f << stringf("\n (property %s (string \"%d'h%s\"))", EDIF_DEF(name), GetSize(val.bits), hex_string.c_str());
}
};
for (auto &p : cell->parameters)
add_prop(p.first, p.second);
if (attr_properties)
for (auto &p : cell->attributes)
add_prop(p.first, p.second);
*f << stringf(")\n");
for (auto &p : cell->connections()) {
RTLIL::SigSpec sig = sigmap(p.second);
for (int i = 0; i < GetSize(sig); i++)
if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1)
log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n",
i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i]));
else if (sig.size() == 1)
net_join_db[sig[i]].insert(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name)));
else {
int member_idx = GetSize(sig)-i-1;
auto m = design->module(cell->type);
if (m) {
auto w = m->wire(p.first);
if (w)
member_idx = GetSize(w)-i-1;
}
net_join_db[sig[i]].insert(stringf("(portRef (member %s %d) (instanceRef %s))",
EDIF_REF(p.first), member_idx, EDIF_REF(cell->name)));
}
}
}
for (auto &it : net_join_db) {
RTLIL::SigBit sig = it.first;
if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) {
if (sig == RTLIL::State::Sx) {
for (auto &ref : it.second)
log_warning("Exporting x-bit on %s as zero bit.\n", ref.c_str());
sig = RTLIL::State::S0;
} else {
for (auto &ref : it.second)
log_error("Don't know how to handle %s on %s.\n", log_signal(sig), ref.c_str());
log_abort();
}
}
std::string netname;
if (sig == RTLIL::State::S0)
netname = "GND_NET";
else if (sig == RTLIL::State::S1)
netname = "VCC_NET";
else {
netname = log_signal(sig);
for (size_t i = 0; i < netname.size(); i++)
if (netname[i] == ' ' || netname[i] == '\\')
netname.erase(netname.begin() + i--);
}
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
for (auto &ref : it.second)
*f << stringf(" %s\n", ref.c_str());
if (sig.wire == NULL) {
if (nogndvcc)
log_error("Design contains constant nodes (map with \"hilomap\" first).\n");
if (sig == RTLIL::State::S0)
*f << stringf(" (portRef %c (instanceRef GND))\n", gndvccy ? 'Y' : 'G');
if (sig == RTLIL::State::S1)
*f << stringf(" (portRef %c (instanceRef VCC))\n", gndvccy ? 'Y' : 'P');
}
*f << stringf(" ))\n");
}
*f << stringf(" )\n");
*f << stringf(" )\n");
*f << stringf(" )\n");
}
*f << stringf(" )\n");
*f << stringf(" (design %s\n", EDIF_DEF(top_module_name));
*f << stringf(" (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name));
*f << stringf(" )\n");
*f << stringf(")\n");
}
} EdifBackend;
PRIVATE_NAMESPACE_END

View File

@ -1,121 +0,0 @@
#!/usr/bin/env python3
import os
import numpy as np
enable_upto = True
enable_offset = True
enable_hierarchy = True
enable_logic = True
def make_module(f, modname, width, subs):
print("module %s (A, B, C, X, Y, Z);" % modname, file=f)
inbits = list()
outbits = list()
for p in "ABC":
offset = np.random.randint(10) if enable_offset else 0
if enable_upto and np.random.randint(2):
print(" input [%d:%d] %s;" % (offset, offset+width-1, p), file=f)
else:
print(" input [%d:%d] %s;" % (offset+width-1, offset, p), file=f)
for i in range(offset, offset+width):
inbits.append("%s[%d]" % (p, i))
for p in "XYZ":
offset = np.random.randint(10) if enable_offset else 0
if enable_upto and np.random.randint(2):
print(" output [%d:%d] %s;" % (offset, offset+width-1, p), file=f)
else:
print(" output [%d:%d] %s;" % (offset+width-1, offset, p), file=f)
for i in range(offset, offset+width):
outbits.append("%s[%d]" % (p, i))
instidx = 0
subcandidates = list(subs.keys())
while len(outbits) > 0:
submod = None
if len(subcandidates):
submod = np.random.choice(subcandidates)
subcandidates.remove(submod)
if submod is None or 3*subs[submod] >= len(outbits):
for bit in outbits:
if enable_logic:
print(" assign %s = %s & ~%s;" % (bit, np.random.choice(inbits), np.random.choice(inbits)), file=f)
else:
print(" assign %s = %s;" % (bit, np.random.choice(inbits)), file=f)
break
instidx += 1
print(" %s inst%d (" % (submod, instidx), file=f)
for p in "ABC":
print(" .%s({%s})," % (p, ",".join(np.random.choice(inbits, subs[submod]))), file=f)
for p in "XYZ":
bits = list(np.random.choice(outbits, subs[submod], False))
for bit in bits:
outbits.remove(bit)
print(" .%s({%s})%s" % (p, ",".join(bits), "," if p != "Z" else ""), file=f)
print(" );", file=f);
print("endmodule", file=f)
with open("test_top.v", "w") as f:
if enable_hierarchy:
make_module(f, "sub1", 2, {})
make_module(f, "sub2", 3, {})
make_module(f, "sub3", 4, {})
make_module(f, "sub4", 8, {"sub1": 2, "sub2": 3, "sub3": 4})
make_module(f, "sub5", 8, {"sub1": 2, "sub2": 3, "sub3": 4})
make_module(f, "sub6", 8, {"sub1": 2, "sub2": 3, "sub3": 4})
make_module(f, "top", 32, {"sub4": 8, "sub5": 8, "sub6": 8})
else:
make_module(f, "top", 32, {})
os.system("set -x; ../../yosys -p 'synth_xilinx -top top; write_edif -pvector par test_syn.edif' test_top.v")
with open("test_syn.tcl", "w") as f:
print("read_edif test_syn.edif", file=f)
print("link_design", file=f)
print("write_verilog -force test_syn.v", file=f)
os.system("set -x; vivado -nojournal -nolog -mode batch -source test_syn.tcl")
with open("test_tb.v", "w") as f:
print("module tb;", file=f)
print(" reg [31:0] A, B, C;", file=f)
print(" wire [31:0] X, Y, Z;", file=f)
print("", file=f)
print(" top uut (", file=f)
print(" .A(A),", file=f)
print(" .B(B),", file=f)
print(" .C(C),", file=f)
print(" .X(X),", file=f)
print(" .Y(Y),", file=f)
print(" .Z(Z)", file=f)
print(" );", file=f)
print("", file=f)
print(" initial begin", file=f)
for i in range(100):
print(" A = 32'h%08x;" % np.random.randint(2**32), file=f)
print(" B = 32'h%08x;" % np.random.randint(2**32), file=f)
print(" C = 32'h%08x;" % np.random.randint(2**32), file=f)
print(" #10;", file=f)
print(" $display(\"%x %x %x\", X, Y, Z);", file=f)
print(" #10;", file=f)
print(" $finish;", file=f)
print(" end", file=f)
print("endmodule", file=f)
os.system("set -x; iverilog -o test_gold test_tb.v test_top.v")
os.system("set -x; iverilog -o test_gate test_tb.v test_syn.v ../../techlibs/xilinx/cells_sim.v")
os.system("set -x; ./test_gold > test_gold.out")
os.system("set -x; ./test_gate > test_gate.out")
os.system("set -x; md5sum test_gold.out test_gate.out")

View File

@ -1,2 +0,0 @@
test.fir
test_out.v

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
#!/bin/bash
set -ex
cd ../../
make
cd backends/firrtl
../../yosys -q -p 'prep -nordff; write_firrtl test.fir' $1
firrtl -i test.fir -o test_out.v -ll Info
../../yosys -p "
read_verilog $1
rename Top gold
read_verilog test_out.v
rename Top gate
prep
memory_map
miter -equiv -flatten gold gate miter
hierarchy -top miter
sat -verify -prove trigger 0 -set-init-zero -seq 10 miter
"

View File

@ -1,63 +0,0 @@
module test(
input clk, wen,
input [7:0] uns,
input signed [7:0] a, b,
input signed [23:0] c,
input signed [2:0] sel,
output [15:0] s, d, y, z, u, q, p, mul, div, mod, mux, And, Or, Xor, eq, neq, gt, lt, geq, leq, eqx, shr, sshr, shl, sshl, Land, Lor, Lnot, Not, Neg, pos, Andr, Orr, Xorr, Xnorr, Reduce_bool,
output [7:0] PMux
);
//initial begin
//$display("shr = %b", shr);
//end
assign s = a+{b[6:2], 2'b1};
assign d = a-b;
assign y = x;
assign z[7:0] = s+d;
assign z[15:8] = s-d;
assign p = a & b | x;
assign mul = a * b;
assign div = a / b;
assign mod = a % b;
assign mux = x[0] ? a : b;
assign And = a & b;
assign Or = a | b;
assign Xor = a ^ b;
assign Not = ~a;
assign Neg = -a;
assign eq = a == b;
assign neq = a != b;
assign gt = a > b;
assign lt = a < b;
assign geq = a >= b;
assign leq = a <= b;
assign eqx = a === b;
assign shr = a >> b; //0111111111000000
assign sshr = a >>> b;
assign shl = a << b;
assign sshl = a <<< b;
assign Land = a && b;
assign Lor = a || b;
assign Lnot = !a;
assign pos = $signed(uns);
assign Andr = &a;
assign Orr = |a;
assign Xorr = ^a;
assign Xnorr = ~^a;
always @*
if(!a) begin
Reduce_bool = a;
end else begin
Reduce_bool = b;
end
//always @(sel or c or a)
// begin
// case (sel)
// 3'b000: PMux = a;
// 3'b001: PMux = c[7:0];
// 3'b010: PMux = c[15:8];
// 3'b100: PMux = c[23:16];
// endcase
// end
endmodule

View File

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

View File

@ -1,513 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
* A very simple and straightforward backend for the RTLIL text
* representation (as understood by the 'ilang' frontend).
*
*/
#include "ilang_backend.h"
#include "kernel/yosys.h"
#include <errno.h>
USING_YOSYS_NAMESPACE
using namespace ILANG_BACKEND;
YOSYS_NAMESPACE_BEGIN
void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint)
{
if (width < 0)
width = data.bits.size() - offset;
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
if (width == 32 && autoint) {
int32_t val = 0;
for (int i = 0; i < width; i++) {
log_assert(offset+i < (int)data.bits.size());
switch (data.bits[offset+i]) {
case RTLIL::S0: break;
case RTLIL::S1: val |= 1 << i; break;
default: val = -1; break;
}
}
if (val >= 0) {
f << stringf("%d", val);
return;
}
}
f << stringf("%d'", width);
for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size());
switch (data.bits[i]) {
case RTLIL::S0: f << stringf("0"); break;
case RTLIL::S1: f << stringf("1"); break;
case RTLIL::Sx: f << stringf("x"); break;
case RTLIL::Sz: f << stringf("z"); break;
case RTLIL::Sa: f << stringf("-"); break;
case RTLIL::Sm: f << stringf("m"); break;
}
}
} else {
f << stringf("\"");
std::string str = data.decode_string();
for (size_t i = 0; i < str.size(); i++) {
if (str[i] == '\n')
f << stringf("\\n");
else if (str[i] == '\t')
f << stringf("\\t");
else if (str[i] < 32)
f << stringf("\\%03o", str[i]);
else if (str[i] == '"')
f << stringf("\\\"");
else if (str[i] == '\\')
f << stringf("\\\\");
else
f << str[i];
}
f << stringf("\"");
}
}
void ILANG_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint)
{
if (chunk.wire == NULL) {
dump_const(f, chunk.data, chunk.width, chunk.offset, autoint);
} else {
if (chunk.width == chunk.wire->width && chunk.offset == 0)
f << stringf("%s", chunk.wire->name.c_str());
else if (chunk.width == 1)
f << stringf("%s [%d]", chunk.wire->name.c_str(), chunk.offset);
else
f << stringf("%s [%d:%d]", chunk.wire->name.c_str(), chunk.offset+chunk.width-1, chunk.offset);
}
}
void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint)
{
if (sig.is_chunk()) {
dump_sigchunk(f, sig.as_chunk(), autoint);
} else {
f << stringf("{ ");
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) {
dump_sigchunk(f, *it, false);
f << stringf(" ");
}
f << stringf("}");
}
}
void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
{
for (auto &it : wire->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
dump_const(f, it.second);
f << stringf("\n");
}
f << stringf("%s" "wire ", indent.c_str());
if (wire->width != 1)
f << stringf("width %d ", wire->width);
if (wire->upto)
f << stringf("upto ");
if (wire->start_offset != 0)
f << stringf("offset %d ", wire->start_offset);
if (wire->port_input && !wire->port_output)
f << stringf("input %d ", wire->port_id);
if (!wire->port_input && wire->port_output)
f << stringf("output %d ", wire->port_id);
if (wire->port_input && wire->port_output)
f << stringf("inout %d ", wire->port_id);
f << stringf("%s\n", wire->name.c_str());
}
void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory)
{
for (auto &it : memory->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
dump_const(f, it.second);
f << stringf("\n");
}
f << stringf("%s" "memory ", indent.c_str());
if (memory->width != 1)
f << stringf("width %d ", memory->width);
if (memory->size != 0)
f << stringf("size %d ", memory->size);
if (memory->start_offset != 0)
f << stringf("offset %d ", memory->start_offset);
f << stringf("%s\n", memory->name.c_str());
}
void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell)
{
for (auto &it : cell->attributes) {
f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
dump_const(f, it.second);
f << stringf("\n");
}
f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str());
for (auto &it : cell->parameters) {
f << stringf("%s parameter%s%s %s ", indent.c_str(),
(it.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "",
(it.second.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
it.first.c_str());
dump_const(f, it.second);
f << stringf("\n");
}
for (auto &it : cell->connections()) {
f << stringf("%s connect %s ", indent.c_str(), it.first.c_str());
dump_sigspec(f, it.second);
f << stringf("\n");
}
f << stringf("%s" "end\n", indent.c_str());
}
void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs)
{
for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it)
{
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, it->first);
f << stringf(" ");
dump_sigspec(f, it->second);
f << stringf("\n");
}
for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it)
dump_proc_switch(f, indent, *it);
}
void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw)
{
for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
dump_const(f, it->second);
f << stringf("\n");
}
f << stringf("%s" "switch ", indent.c_str());
dump_sigspec(f, sw->signal);
f << stringf("\n");
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it)
{
for (auto ait = (*it)->attributes.begin(); ait != (*it)->attributes.end(); ++ait) {
f << stringf("%s attribute %s ", indent.c_str(), ait->first.c_str());
dump_const(f, ait->second);
f << stringf("\n");
}
f << stringf("%s case ", indent.c_str());
for (size_t i = 0; i < (*it)->compare.size(); i++) {
if (i > 0)
f << stringf(" , ");
dump_sigspec(f, (*it)->compare[i]);
}
f << stringf("\n");
dump_proc_case_body(f, indent + " ", *it);
}
f << stringf("%s" "end\n", indent.c_str());
}
void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy)
{
f << stringf("%s" "sync ", indent.c_str());
switch (sy->type) {
case RTLIL::ST0: f << stringf("low ");
if (0) case RTLIL::ST1: f << stringf("high ");
if (0) case RTLIL::STp: f << stringf("posedge ");
if (0) case RTLIL::STn: f << stringf("negedge ");
if (0) case RTLIL::STe: f << stringf("edge ");
dump_sigspec(f, sy->signal);
f << stringf("\n");
break;
case RTLIL::STa: f << stringf("always\n"); break;
case RTLIL::STg: f << stringf("global\n"); break;
case RTLIL::STi: f << stringf("init\n"); break;
}
for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) {
f << stringf("%s update ", indent.c_str());
dump_sigspec(f, it->first);
f << stringf(" ");
dump_sigspec(f, it->second);
f << stringf("\n");
}
}
void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc)
{
for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
dump_const(f, it->second);
f << stringf("\n");
}
f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str());
dump_proc_case_body(f, indent + " ", &proc->root_case);
for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it)
dump_proc_sync(f, indent + " ", *it);
f << stringf("%s" "end\n", indent.c_str());
}
void ILANG_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
f << stringf("%s" "connect ", indent.c_str());
dump_sigspec(f, left);
f << stringf(" ");
dump_sigspec(f, right);
f << stringf("\n");
}
void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
{
bool print_header = flag_m || design->selected_whole_module(module->name);
bool print_body = !flag_n || !design->selected_whole_module(module->name);
if (print_header)
{
for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) {
f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str());
dump_const(f, it->second);
f << stringf("\n");
}
f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str());
if (!module->avail_parameters.empty()) {
if (only_selected)
f << stringf("\n");
for (auto &p : module->avail_parameters)
f << stringf("%s" " parameter %s\n", indent.c_str(), p.c_str());
}
}
if (print_body)
{
for (auto it : module->wires())
if (!only_selected || design->selected(module, it)) {
if (only_selected)
f << stringf("\n");
dump_wire(f, indent + " ", it);
}
for (auto it : module->memories)
if (!only_selected || design->selected(module, it.second)) {
if (only_selected)
f << stringf("\n");
dump_memory(f, indent + " ", it.second);
}
for (auto it : module->cells())
if (!only_selected || design->selected(module, it)) {
if (only_selected)
f << stringf("\n");
dump_cell(f, indent + " ", it);
}
for (auto it : module->processes)
if (!only_selected || design->selected(module, it.second)) {
if (only_selected)
f << stringf("\n");
dump_proc(f, indent + " ", it.second);
}
bool first_conn_line = true;
for (auto it = module->connections().begin(); it != module->connections().end(); ++it) {
bool show_conn = !only_selected;
if (only_selected) {
RTLIL::SigSpec sigs = it->first;
sigs.append(it->second);
for (auto &c : sigs.chunks()) {
if (c.wire == NULL || !design->selected(module, c.wire))
continue;
show_conn = true;
}
}
if (show_conn) {
if (only_selected && first_conn_line)
f << stringf("\n");
dump_conn(f, indent + " ", it->first, it->second);
first_conn_line = false;
}
}
}
if (print_header)
f << stringf("%s" "end\n", indent.c_str());
}
void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
{
#ifndef NDEBUG
int init_autoidx = autoidx;
#endif
if (!flag_m) {
int count_selected_mods = 0;
for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) {
if (design->selected_whole_module(it->first))
flag_m = true;
if (design->selected(it->second))
count_selected_mods++;
}
if (count_selected_mods > 1)
flag_m = true;
}
if (!only_selected || flag_m) {
if (only_selected)
f << stringf("\n");
f << stringf("autoidx %d\n", autoidx);
}
for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) {
if (!only_selected || design->selected(it->second)) {
if (only_selected)
f << stringf("\n");
dump_module(f, "", it->second, design, only_selected, flag_m, flag_n);
}
}
log_assert(init_autoidx == autoidx);
}
YOSYS_NAMESPACE_END
PRIVATE_NAMESPACE_BEGIN
struct IlangBackend : public Backend {
IlangBackend() : Backend("ilang", "write design to ilang file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_ilang [filename]\n");
log("\n");
log("Write the current design to an 'ilang' file. (ilang is a text representation\n");
log("of a design in yosys's internal format.)\n");
log("\n");
log(" -selected\n");
log(" only write selected parts of the design.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool selected = false;
log_header(design, "Executing ILANG backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-selected") {
selected = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
design->sort();
log("Output filename: %s\n", filename.c_str());
*f << stringf("# Generated by %s\n", yosys_version_str);
ILANG_BACKEND::dump_design(*f, design, selected, true, false);
}
} IlangBackend;
struct DumpPass : public Pass {
DumpPass() : Pass("dump", "print parts of the design in ilang format") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" dump [options] [selection]\n");
log("\n");
log("Write the selected parts of the design to the console or specified file in\n");
log("ilang format.\n");
log("\n");
log(" -m\n");
log(" also dump the module headers, even if only parts of a single\n");
log(" module is selected\n");
log("\n");
log(" -n\n");
log(" only dump the module headers if the entire module is selected\n");
log("\n");
log(" -o <filename>\n");
log(" write to the specified file.\n");
log("\n");
log(" -a <filename>\n");
log(" like -outfile but append instead of overwrite\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string filename;
bool flag_m = false, flag_n = false, append = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
std::string arg = args[argidx];
if ((arg == "-o" || arg == "-outfile") && argidx+1 < args.size()) {
filename = args[++argidx];
append = false;
continue;
}
if ((arg == "-a" || arg == "-append") && argidx+1 < args.size()) {
filename = args[++argidx];
append = true;
continue;
}
if (arg == "-m") {
flag_m = true;
continue;
}
if (arg == "-n") {
flag_n = true;
continue;
}
break;
}
extra_args(args, argidx, design);
std::ostream *f;
std::stringstream buf;
if (!filename.empty()) {
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
f = ff;
} else {
f = &buf;
}
ILANG_BACKEND::dump_design(*f, design, true, flag_m, flag_n);
if (!filename.empty()) {
delete f;
} else {
log("%s", buf.str().c_str());
}
}
} DumpPass;
PRIVATE_NAMESPACE_END

View File

@ -1,51 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
* A very simple and straightforward backend for the RTLIL text
* representation (as understood by the 'ilang' frontend).
*
*/
#ifndef ILANG_BACKEND_H
#define ILANG_BACKEND_H
#include "kernel/yosys.h"
#include <stdio.h>
YOSYS_NAMESPACE_BEGIN
namespace ILANG_BACKEND {
void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true);
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);
void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory);
void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell);
void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs);
void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw);
void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy);
void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc);
void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right);
void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false);
void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false);
}
YOSYS_NAMESPACE_END
#endif

View File

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

View File

@ -1,220 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static std::string netname(std::set<std::string> &conntypes_code, std::set<std::string> &celltypes_code, std::set<std::string> &constcells_code, RTLIL::SigSpec sig)
{
if (!sig.is_fully_const() && !sig.is_wire())
log_error("Can't export composite or non-word-wide signal %s.\n", log_signal(sig));
conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size()));
if (sig.is_fully_const()) {
celltypes_code.insert(stringf("celltype CONST_%d b%d *CONST cfg:%d VALUE\n", sig.size(), sig.size(), sig.size()));
constcells_code.insert(stringf("node CONST_%d_0x%x CONST_%d CONST CONST_%d_0x%x VALUE 0x%x\n",
sig.size(), sig.as_int(), sig.size(), sig.size(), sig.as_int(), sig.as_int()));
return stringf("CONST_%d_0x%x", sig.size(), sig.as_int());
}
return RTLIL::unescape_id(sig.as_wire()->name);
}
struct IntersynthBackend : public Backend {
IntersynthBackend() : Backend("intersynth", "write design to InterSynth netlist file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_intersynth [options] [filename]\n");
log("\n");
log("Write the current design to an 'intersynth' netlist file. InterSynth is\n");
log("a tool for Coarse-Grain Example-Driven Interconnect Synthesis.\n");
log("\n");
log(" -notypes\n");
log(" do not generate celltypes and conntypes commands. i.e. just output\n");
log(" the netlists. this is used for postsilicon synthesis.\n");
log("\n");
log(" -lib <verilog_or_ilang_file>\n");
log(" Use the specified library file for determining whether cell ports are\n");
log(" inputs or outputs. This option can be used multiple times to specify\n");
log(" more than one library.\n");
log("\n");
log(" -selected\n");
log(" only write selected modules. modules must be selected entirely or\n");
log(" not at all.\n");
log("\n");
log("http://www.clifford.at/intersynth/\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing INTERSYNTH backend.\n");
log_push();
std::vector<std::string> libfiles;
std::vector<RTLIL::Design*> libs;
bool flag_notypes = false;
bool selected = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-notypes") {
flag_notypes = true;
continue;
}
if (args[argidx] == "-lib" && argidx+1 < args.size()) {
libfiles.push_back(args[++argidx]);
continue;
}
if (args[argidx] == "-selected") {
selected = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
log("Output filename: %s\n", filename.c_str());
for (auto filename : libfiles) {
std::ifstream f;
f.open(filename.c_str());
if (f.fail())
log_error("Can't open lib file `%s'.\n", filename.c_str());
RTLIL::Design *lib = new RTLIL::Design;
Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
libs.push_back(lib);
}
if (libs.size() > 0)
log_header(design, "Continuing INTERSYNTH backend.\n");
std::set<std::string> conntypes_code, celltypes_code;
std::string netlists_code;
CellTypes ct(design);
for (auto lib : libs)
ct.setup_design(lib);
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
SigMap sigmap(module);
if (module->get_blackbox_attribute())
continue;
if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0)
continue;
if (selected && !design->selected_whole_module(module->name)) {
if (design->selected_module(module->name))
log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(module->name));
continue;
}
log("Generating netlist %s.\n", RTLIL::id2cstr(module->name));
if (module->memories.size() != 0 || module->processes.size() != 0)
log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n");
std::set<std::string> constcells_code;
netlists_code += stringf("# Netlist of module %s\n", RTLIL::id2cstr(module->name));
netlists_code += stringf("netlist %s\n", RTLIL::id2cstr(module->name));
// Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports
for (auto wire_it : module->wires_) {
RTLIL::Wire *wire = wire_it.second;
if (wire->port_input || wire->port_output) {
celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n",
RTLIL::id2cstr(wire->name), wire->width, wire->port_input ? "*" : "",
wire->port_input ? "input" : "output", RTLIL::id2cstr(wire->name), wire->width, RTLIL::id2cstr(wire->name)));
netlists_code += stringf("node %s %s PORT %s\n", RTLIL::id2cstr(wire->name), RTLIL::id2cstr(wire->name),
netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str());
}
}
// Submodules: "std::set<string> celltypes_code" prevents duplicate cell types
for (auto cell_it : module->cells_)
{
RTLIL::Cell *cell = cell_it.second;
std::string celltype_code, node_code;
if (!ct.cell_known(cell->type))
log_error("Found unknown cell type %s in module!\n", RTLIL::id2cstr(cell->type));
celltype_code = stringf("celltype %s", RTLIL::id2cstr(cell->type));
node_code = stringf("node %s %s", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
for (auto &port : cell->connections()) {
RTLIL::SigSpec sig = sigmap(port.second);
if (sig.size() != 0) {
conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size()));
celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first));
node_code += stringf(" %s %s", RTLIL::id2cstr(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str());
}
}
for (auto &param : cell->parameters) {
celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), RTLIL::id2cstr(param.first));
if (param.second.bits.size() != 32) {
node_code += stringf(" %s '", RTLIL::id2cstr(param.first));
for (int i = param.second.bits.size()-1; i >= 0; i--)
node_code += param.second.bits[i] == RTLIL::S1 ? "1" : "0";
} else
node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int());
}
celltypes_code.insert(celltype_code + "\n");
netlists_code += node_code + "\n";
}
if (constcells_code.size() > 0)
netlists_code += "# constant cells\n";
for (auto code : constcells_code)
netlists_code += code;
netlists_code += "\n";
}
if (!flag_notypes) {
*f << stringf("### Connection Types\n");
for (auto code : conntypes_code)
*f << stringf("%s", code.c_str());
*f << stringf("\n### Cell Types\n");
for (auto code : celltypes_code)
*f << stringf("%s", code.c_str());
}
*f << stringf("\n### Netlists\n");
*f << stringf("%s", netlists_code.c_str());
for (auto lib : libs)
delete lib;
log_pop();
}
} IntersynthBackend;
PRIVATE_NAMESPACE_END

View File

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

View File

@ -1,559 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/cellaigs.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct JsonWriter
{
std::ostream &f;
bool use_selection;
bool aig_mode;
Design *design;
Module *module;
SigMap sigmap;
int sigidcounter;
dict<SigBit, string> sigids;
pool<Aig> aig_models;
JsonWriter(std::ostream &f, bool use_selection, bool aig_mode) :
f(f), use_selection(use_selection), aig_mode(aig_mode) { }
string get_string(string str)
{
string newstr = "\"";
for (char c : str) {
if (c == '\\')
newstr += c;
newstr += c;
}
return newstr + "\"";
}
string get_name(IdString name)
{
return get_string(RTLIL::unescape_id(name));
}
string get_bits(SigSpec sig)
{
bool first = true;
string str = "[";
for (auto bit : sigmap(sig)) {
str += first ? " " : ", ";
first = false;
if (sigids.count(bit) == 0) {
string &s = sigids[bit];
if (bit.wire == nullptr) {
if (bit == State::S0) s = "\"0\"";
else if (bit == State::S1) s = "\"1\"";
else if (bit == State::Sz) s = "\"z\"";
else s = "\"x\"";
} else
s = stringf("%d", sigidcounter++);
}
str += sigids[bit];
}
return str + " ]";
}
void write_parameters(const dict<IdString, Const> &parameters, bool for_module=false)
{
bool first = true;
for (auto &param : parameters) {
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str());
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0)
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
else
f << stringf("%u", param.second.as_int());
first = false;
}
}
void write_module(Module *module_)
{
module = module_;
log_assert(module->design == design);
sigmap.set(module);
sigids.clear();
// reserve 0 and 1 to avoid confusion with "0" and "1"
sigidcounter = 2;
f << stringf(" %s: {\n", get_name(module->name).c_str());
f << stringf(" \"attributes\": {");
write_parameters(module->attributes, /*for_module=*/true);
f << stringf("\n },\n");
f << stringf(" \"ports\": {");
bool first = true;
for (auto n : module->ports) {
Wire *w = module->wire(n);
if (use_selection && !module->selected(w))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(n).c_str());
f << stringf(" \"direction\": \"%s\",\n", w->port_input ? w->port_output ? "inout" : "input" : "output");
if (w->start_offset)
f << stringf(" \"offset\": %d,\n", w->start_offset);
if (w->upto)
f << stringf(" \"upto\": 1,\n");
f << stringf(" \"bits\": %s\n", get_bits(w).c_str());
f << stringf(" }");
first = false;
}
f << stringf("\n },\n");
f << stringf(" \"cells\": {");
first = true;
for (auto c : module->cells()) {
if (use_selection && !module->selected(c))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(c->name).c_str());
f << stringf(" \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
f << stringf(" \"type\": %s,\n", get_name(c->type).c_str());
if (aig_mode) {
Aig aig(c);
if (!aig.name.empty()) {
f << stringf(" \"model\": \"%s\",\n", aig.name.c_str());
aig_models.insert(aig);
}
}
f << stringf(" \"parameters\": {");
write_parameters(c->parameters);
f << stringf("\n },\n");
f << stringf(" \"attributes\": {");
write_parameters(c->attributes);
f << stringf("\n },\n");
if (c->known()) {
f << stringf(" \"port_directions\": {");
bool first2 = true;
for (auto &conn : c->connections()) {
string direction = "output";
if (c->input(conn.first))
direction = c->output(conn.first) ? "inout" : "input";
f << stringf("%s\n", first2 ? "" : ",");
f << stringf(" %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
first2 = false;
}
f << stringf("\n },\n");
}
f << stringf(" \"connections\": {");
bool first2 = true;
for (auto &conn : c->connections()) {
f << stringf("%s\n", first2 ? "" : ",");
f << stringf(" %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
first2 = false;
}
f << stringf("\n }\n");
f << stringf(" }");
first = false;
}
f << stringf("\n },\n");
f << stringf(" \"netnames\": {");
first = true;
for (auto w : module->wires()) {
if (use_selection && !module->selected(w))
continue;
f << stringf("%s\n", first ? "" : ",");
f << stringf(" %s: {\n", get_name(w->name).c_str());
f << stringf(" \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
f << stringf(" \"bits\": %s,\n", get_bits(w).c_str());
if (w->start_offset)
f << stringf(" \"offset\": %d,\n", w->start_offset);
if (w->upto)
f << stringf(" \"upto\": 1,\n");
f << stringf(" \"attributes\": {");
write_parameters(w->attributes);
f << stringf("\n }\n");
f << stringf(" }");
first = false;
}
f << stringf("\n }\n");
f << stringf(" }");
}
void write_design(Design *design_)
{
design = design_;
design->sort();
f << stringf("{\n");
f << stringf(" \"creator\": %s,\n", get_string(yosys_version_str).c_str());
f << stringf(" \"modules\": {\n");
vector<Module*> modules = use_selection ? design->selected_modules() : design->modules();
bool first_module = true;
for (auto mod : modules) {
if (!first_module)
f << stringf(",\n");
write_module(mod);
first_module = false;
}
f << stringf("\n }");
if (!aig_models.empty()) {
f << stringf(",\n \"models\": {\n");
bool first_model = true;
for (auto &aig : aig_models) {
if (!first_model)
f << stringf(",\n");
f << stringf(" \"%s\": [\n", aig.name.c_str());
int node_idx = 0;
for (auto &node : aig.nodes) {
if (node_idx != 0)
f << stringf(",\n");
f << stringf(" /* %3d */ [ ", node_idx);
if (node.portbit >= 0)
f << stringf("\"%sport\", \"%s\", %d", node.inverter ? "n" : "",
log_id(node.portname), node.portbit);
else if (node.left_parent < 0 && node.right_parent < 0)
f << stringf("\"%s\"", node.inverter ? "true" : "false");
else
f << stringf("\"%s\", %d, %d", node.inverter ? "nand" : "and", node.left_parent, node.right_parent);
for (auto &op : node.outports)
f << stringf(", \"%s\", %d", log_id(op.first), op.second);
f << stringf(" ]");
node_idx++;
}
f << stringf("\n ]");
first_model = false;
}
f << stringf("\n }");
}
f << stringf("\n}\n");
}
};
struct JsonBackend : public Backend {
JsonBackend() : Backend("json", "write design to a JSON file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_json [options] [filename]\n");
log("\n");
log("Write a JSON netlist of the current design.\n");
log("\n");
log(" -aig\n");
log(" include AIG models for the different gate types\n");
log("\n");
log("\n");
log("The general syntax of the JSON output created by this command is as follows:\n");
log("\n");
log(" {\n");
log(" \"modules\": {\n");
log(" <module_name>: {\n");
log(" \"ports\": {\n");
log(" <port_name>: <port_details>,\n");
log(" ...\n");
log(" },\n");
log(" \"cells\": {\n");
log(" <cell_name>: <cell_details>,\n");
log(" ...\n");
log(" },\n");
log(" \"netnames\": {\n");
log(" <net_name>: <net_details>,\n");
log(" ...\n");
log(" }\n");
log(" }\n");
log(" },\n");
log(" \"models\": {\n");
log(" ...\n");
log(" },\n");
log(" }\n");
log("\n");
log("Where <port_details> is:\n");
log("\n");
log(" {\n");
log(" \"direction\": <\"input\" | \"output\" | \"inout\">,\n");
log(" \"bits\": <bit_vector>\n");
log(" }\n");
log("\n");
log("And <cell_details> is:\n");
log("\n");
log(" {\n");
log(" \"hide_name\": <1 | 0>,\n");
log(" \"type\": <cell_type>,\n");
log(" \"parameters\": {\n");
log(" <parameter_name>: <parameter_value>,\n");
log(" ...\n");
log(" },\n");
log(" \"attributes\": {\n");
log(" <attribute_name>: <attribute_value>,\n");
log(" ...\n");
log(" },\n");
log(" \"port_directions\": {\n");
log(" <port_name>: <\"input\" | \"output\" | \"inout\">,\n");
log(" ...\n");
log(" },\n");
log(" \"connections\": {\n");
log(" <port_name>: <bit_vector>,\n");
log(" ...\n");
log(" },\n");
log(" }\n");
log("\n");
log("And <net_details> is:\n");
log("\n");
log(" {\n");
log(" \"hide_name\": <1 | 0>,\n");
log(" \"bits\": <bit_vector>\n");
log(" }\n");
log("\n");
log("The \"hide_name\" fields are set to 1 when the name of this cell or net is\n");
log("automatically created and is likely not of interest for a regular user.\n");
log("\n");
log("The \"port_directions\" section is only included for cells for which the\n");
log("interface is known.\n");
log("\n");
log("Module and cell ports and nets can be single bit wide or vectors of multiple\n");
log("bits. Each individual signal bit is assigned a unique integer. The <bit_vector>\n");
log("values referenced above are vectors of this integers. Signal bits that are\n");
log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n");
log("a number.\n");
log("\n");
log("Numeric parameter and attribute values up to 32 bits are written as decimal\n");
log("values. Numbers larger than that are written as string holding the binary\n");
log("representation of the value.\n");
log("\n");
log("For example the following Verilog code:\n");
log("\n");
log(" module test(input x, y);\n");
log(" (* keep *) foo #(.P(42), .Q(1337))\n");
log(" foo_inst (.A({x, y}), .B({y, x}), .C({4'd10, {4{x}}}));\n");
log(" endmodule\n");
log("\n");
log("Translates to the following JSON output:\n");
log("\n");
log(" {\n");
log(" \"modules\": {\n");
log(" \"test\": {\n");
log(" \"ports\": {\n");
log(" \"x\": {\n");
log(" \"direction\": \"input\",\n");
log(" \"bits\": [ 2 ]\n");
log(" },\n");
log(" \"y\": {\n");
log(" \"direction\": \"input\",\n");
log(" \"bits\": [ 3 ]\n");
log(" }\n");
log(" },\n");
log(" \"cells\": {\n");
log(" \"foo_inst\": {\n");
log(" \"hide_name\": 0,\n");
log(" \"type\": \"foo\",\n");
log(" \"parameters\": {\n");
log(" \"Q\": 1337,\n");
log(" \"P\": 42\n");
log(" },\n");
log(" \"attributes\": {\n");
log(" \"keep\": 1,\n");
log(" \"src\": \"test.v:2\"\n");
log(" },\n");
log(" \"connections\": {\n");
log(" \"C\": [ 2, 2, 2, 2, \"0\", \"1\", \"0\", \"1\" ],\n");
log(" \"B\": [ 2, 3 ],\n");
log(" \"A\": [ 3, 2 ]\n");
log(" }\n");
log(" }\n");
log(" },\n");
log(" \"netnames\": {\n");
log(" \"y\": {\n");
log(" \"hide_name\": 0,\n");
log(" \"bits\": [ 3 ],\n");
log(" \"attributes\": {\n");
log(" \"src\": \"test.v:1\"\n");
log(" }\n");
log(" },\n");
log(" \"x\": {\n");
log(" \"hide_name\": 0,\n");
log(" \"bits\": [ 2 ],\n");
log(" \"attributes\": {\n");
log(" \"src\": \"test.v:1\"\n");
log(" }\n");
log(" }\n");
log(" }\n");
log(" }\n");
log(" }\n");
log(" }\n");
log("\n");
log("The models are given as And-Inverter-Graphs (AIGs) in the following form:\n");
log("\n");
log(" \"models\": {\n");
log(" <model_name>: [\n");
log(" /* 0 */ [ <node-spec> ],\n");
log(" /* 1 */ [ <node-spec> ],\n");
log(" /* 2 */ [ <node-spec> ],\n");
log(" ...\n");
log(" ],\n");
log(" ...\n");
log(" },\n");
log("\n");
log("The following node-types may be used:\n");
log("\n");
log(" [ \"port\", <portname>, <bitindex>, <out-list> ]\n");
log(" - the value of the specified input port bit\n");
log("\n");
log(" [ \"nport\", <portname>, <bitindex>, <out-list> ]\n");
log(" - the inverted value of the specified input port bit\n");
log("\n");
log(" [ \"and\", <node-index>, <node-index>, <out-list> ]\n");
log(" - the ANDed value of the specified nodes\n");
log("\n");
log(" [ \"nand\", <node-index>, <node-index>, <out-list> ]\n");
log(" - the inverted ANDed value of the specified nodes\n");
log("\n");
log(" [ \"true\", <out-list> ]\n");
log(" - the constant value 1\n");
log("\n");
log(" [ \"false\", <out-list> ]\n");
log(" - the constant value 0\n");
log("\n");
log("All nodes appear in topological order. I.e. only nodes with smaller indices\n");
log("are referenced by \"and\" and \"nand\" nodes.\n");
log("\n");
log("The optional <out-list> at the end of a node specification is a list of\n");
log("output portname and bitindex pairs, specifying the outputs driven by this node.\n");
log("\n");
log("For example, the following is the model for a 3-input 3-output $reduce_and cell\n");
log("inferred by the following code:\n");
log("\n");
log(" module test(input [2:0] in, output [2:0] out);\n");
log(" assign in = &out;\n");
log(" endmodule\n");
log("\n");
log(" \"$reduce_and:3U:3\": [\n");
log(" /* 0 */ [ \"port\", \"A\", 0 ],\n");
log(" /* 1 */ [ \"port\", \"A\", 1 ],\n");
log(" /* 2 */ [ \"and\", 0, 1 ],\n");
log(" /* 3 */ [ \"port\", \"A\", 2 ],\n");
log(" /* 4 */ [ \"and\", 2, 3, \"Y\", 0 ],\n");
log(" /* 5 */ [ \"false\", \"Y\", 1, \"Y\", 2 ]\n");
log(" ]\n");
log("\n");
log("Future version of Yosys might add support for additional fields in the JSON\n");
log("format. A program processing this format must ignore all unknown fields.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool aig_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-aig") {
aig_mode = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
log_header(design, "Executing JSON backend.\n");
JsonWriter json_writer(*f, false, aig_mode);
json_writer.write_design(design);
}
} JsonBackend;
struct JsonPass : public Pass {
JsonPass() : Pass("json", "write design in JSON format") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" json [options] [selection]\n");
log("\n");
log("Write a JSON netlist of all selected objects.\n");
log("\n");
log(" -o <filename>\n");
log(" write to the specified file.\n");
log("\n");
log(" -aig\n");
log(" also include AIG models for the different gate types\n");
log("\n");
log("See 'help write_json' for a description of the JSON format used.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string filename;
bool aig_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-o" && argidx+1 < args.size()) {
filename = args[++argidx];
continue;
}
if (args[argidx] == "-aig") {
aig_mode = true;
continue;
}
break;
}
extra_args(args, argidx, design);
std::ostream *f;
std::stringstream buf;
if (!filename.empty()) {
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
f = ff;
} else {
f = &buf;
}
JsonWriter json_writer(*f, true, aig_mode);
json_writer.write_design(design);
if (!filename.empty()) {
delete f;
} else {
log("%s", buf.str().c_str());
}
}
} JsonPass;
PRIVATE_NAMESPACE_END

View File

@ -1,2 +0,0 @@
yosys.pb.cc
yosys.pb.h

View File

@ -1,8 +0,0 @@
ifeq ($(ENABLE_PROTOBUF),1)
backends/protobuf/yosys.pb.cc backends/protobuf/yosys.pb.h: misc/yosys.proto
$(Q) cd misc && protoc --cpp_out "../backends/protobuf" yosys.proto
OBJS += backends/protobuf/protobuf.o backends/protobuf/yosys.pb.o
endif

View File

@ -1,371 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <google/protobuf/text_format.h>
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/cellaigs.h"
#include "kernel/log.h"
#include "yosys.pb.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct ProtobufDesignSerializer
{
bool aig_mode_;
bool use_selection_;
yosys::pb::Design *pb_;
Design *design_;
Module *module_;
SigMap sigmap_;
int sigidcounter_;
dict<SigBit, uint64_t> sigids_;
pool<Aig> aig_models_;
ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
aig_mode_(aig_mode), use_selection_(use_selection) { }
string get_name(IdString name)
{
return RTLIL::unescape_id(name);
}
void serialize_parameters(google::protobuf::Map<std::string, yosys::pb::Parameter> *out,
const dict<IdString, Const> &parameters)
{
for (auto &param : parameters) {
std::string key = get_name(param.first);
yosys::pb::Parameter pb_param;
if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
pb_param.set_str(param.second.decode_string());
} else if (GetSize(param.second.bits) > 64) {
pb_param.set_str(param.second.as_string());
} else {
pb_param.set_int_(param.second.as_int());
}
(*out)[key] = pb_param;
}
}
void get_bits(yosys::pb::BitVector *out, SigSpec sig)
{
for (auto bit : sigmap_(sig)) {
auto sig = out->add_signal();
// Constant driver.
if (bit.wire == nullptr) {
if (bit == State::S0) sig->set_constant(sig->CONSTANT_DRIVER_LOW);
else if (bit == State::S1) sig->set_constant(sig->CONSTANT_DRIVER_HIGH);
else if (bit == State::Sz) sig->set_constant(sig->CONSTANT_DRIVER_Z);
else sig->set_constant(sig->CONSTANT_DRIVER_X);
continue;
}
// Signal - give it a unique identifier.
if (sigids_.count(bit) == 0) {
sigids_[bit] = sigidcounter_++;
}
sig->set_id(sigids_[bit]);
}
}
void serialize_module(yosys::pb::Module* out, Module *module)
{
module_ = module;
log_assert(module_->design == design_);
sigmap_.set(module_);
sigids_.clear();
sigidcounter_ = 0;
serialize_parameters(out->mutable_attribute(), module_->attributes);
for (auto n : module_->ports) {
Wire *w = module->wire(n);
if (use_selection_ && !module_->selected(w))
continue;
yosys::pb::Module::Port pb_port;
pb_port.set_direction(w->port_input ? w->port_output ?
yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT : yosys::pb::DIRECTION_OUTPUT);
get_bits(pb_port.mutable_bits(), w);
(*out->mutable_port())[get_name(n)] = pb_port;
}
for (auto c : module_->cells()) {
if (use_selection_ && !module_->selected(c))
continue;
yosys::pb::Module::Cell pb_cell;
pb_cell.set_hide_name(c->name[0] == '$');
pb_cell.set_type(get_name(c->type));
if (aig_mode_) {
Aig aig(c);
if (aig.name.empty())
continue;
pb_cell.set_model(aig.name);
aig_models_.insert(aig);
}
serialize_parameters(pb_cell.mutable_parameter(), c->parameters);
serialize_parameters(pb_cell.mutable_attribute(), c->attributes);
if (c->known()) {
for (auto &conn : c->connections()) {
yosys::pb::Direction direction = yosys::pb::DIRECTION_OUTPUT;
if (c->input(conn.first))
direction = c->output(conn.first) ? yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT;
(*pb_cell.mutable_port_direction())[get_name(conn.first)] = direction;
}
}
for (auto &conn : c->connections()) {
yosys::pb::BitVector vec;
get_bits(&vec, conn.second);
(*pb_cell.mutable_connection())[get_name(conn.first)] = vec;
}
(*out->mutable_cell())[get_name(c->name)] = pb_cell;
}
for (auto w : module_->wires()) {
if (use_selection_ && !module_->selected(w))
continue;
auto netname = out->add_netname();
netname->set_hide_name(w->name[0] == '$');
get_bits(netname->mutable_bits(), w);
serialize_parameters(netname->mutable_attributes(), w->attributes);
}
}
void serialize_models(google::protobuf::Map<string, yosys::pb::Model> *models)
{
for (auto &aig : aig_models_) {
yosys::pb::Model pb_model;
for (auto &node : aig.nodes) {
auto pb_node = pb_model.add_node();
if (node.portbit >= 0) {
if (node.inverter) {
pb_node->set_type(pb_node->TYPE_NPORT);
} else {
pb_node->set_type(pb_node->TYPE_PORT);
}
auto port = pb_node->mutable_port();
port->set_portname(log_id(node.portname));
port->set_bitindex(node.portbit);
} else if (node.left_parent < 0 && node.right_parent < 0) {
if (node.inverter) {
pb_node->set_type(pb_node->TYPE_TRUE);
} else {
pb_node->set_type(pb_node->TYPE_FALSE);
}
} else {
if (node.inverter) {
pb_node->set_type(pb_node->TYPE_NAND);
} else {
pb_node->set_type(pb_node->TYPE_AND);
}
auto gate = pb_node->mutable_gate();
gate->set_left(node.left_parent);
gate->set_right(node.right_parent);
}
for (auto &op : node.outports) {
auto pb_op = pb_node->add_out_port();
pb_op->set_name(log_id(op.first));
pb_op->set_bit_index(op.second);
}
}
(*models)[aig.name] = pb_model;
}
}
void serialize_design(yosys::pb::Design *pb, Design *design)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
pb_ = pb;
pb_->Clear();
pb_->set_creator(yosys_version_str);
design_ = design;
design_->sort();
auto modules = use_selection_ ? design_->selected_modules() : design_->modules();
for (auto mod : modules) {
yosys::pb::Module pb_mod;
serialize_module(&pb_mod, mod);
(*pb->mutable_modules())[mod->name.str()] = pb_mod;
}
serialize_models(pb_->mutable_models());
}
};
struct ProtobufBackend : public Backend {
ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_protobuf [options] [filename]\n");
log("\n");
log("Write a JSON netlist of the current design.\n");
log("\n");
log(" -aig\n");
log(" include AIG models for the different gate types\n");
log("\n");
log(" -text\n");
log(" output protobuf in Text/ASCII representation\n");
log("\n");
log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
log("Yosys source code distribution.\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool aig_mode = false;
bool text_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-aig") {
aig_mode = true;
continue;
}
if (args[argidx] == "-text") {
text_mode = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
log_header(design, "Executing Protobuf backend.\n");
yosys::pb::Design pb;
ProtobufDesignSerializer serializer(false, aig_mode);
serializer.serialize_design(&pb, design);
if (text_mode) {
string out;
google::protobuf::TextFormat::PrintToString(pb, &out);
*f << out;
} else {
pb.SerializeToOstream(f);
}
}
} ProtobufBackend;
struct ProtobufPass : public Pass {
ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" protobuf [options] [selection]\n");
log("\n");
log("Write a JSON netlist of all selected objects.\n");
log("\n");
log(" -o <filename>\n");
log(" write to the specified file.\n");
log("\n");
log(" -aig\n");
log(" include AIG models for the different gate types\n");
log("\n");
log(" -text\n");
log(" output protobuf in Text/ASCII representation\n");
log("\n");
log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
log("Yosys source code distribution.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string filename;
bool aig_mode = false;
bool text_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-o" && argidx+1 < args.size()) {
filename = args[++argidx];
continue;
}
if (args[argidx] == "-aig") {
aig_mode = true;
continue;
}
if (args[argidx] == "-text") {
text_mode = true;
continue;
}
break;
}
extra_args(args, argidx, design);
std::ostream *f;
std::stringstream buf;
if (!filename.empty()) {
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), std::ofstream::trunc);
if (ff->fail()) {
delete ff;
log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
}
f = ff;
} else {
f = &buf;
}
yosys::pb::Design pb;
ProtobufDesignSerializer serializer(true, aig_mode);
serializer.serialize_design(&pb, design);
if (text_mode) {
string out;
google::protobuf::TextFormat::PrintToString(pb, &out);
*f << out;
} else {
pb.SerializeToOstream(f);
}
if (!filename.empty()) {
delete f;
} else {
log("%s", buf.str().c_str());
}
}
} ProtobufPass;
PRIVATE_NAMESPACE_END;

View File

@ -1,2 +0,0 @@
test00_tb
test00_uut.c

View File

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

View File

@ -1,810 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/utils.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct HierDirtyFlags;
static pool<string> reserved_cids;
static dict<IdString, string> id2cid;
static string cid(IdString id)
{
if (id2cid.count(id) == 0)
{
string s = id.str();
if (GetSize(s) < 2) log_abort();
if (s[0] == '\\')
s = s.substr(1);
if ('0' <= s[0] && s[0] <= '9') {
s = "_" + s;
}
for (int i = 0; i < GetSize(s); i++) {
if ('0' <= s[i] && s[i] <= '9') continue;
if ('A' <= s[i] && s[i] <= 'Z') continue;
if ('a' <= s[i] && s[i] <= 'z') continue;
s[i] = '_';
}
while (reserved_cids.count(s))
s += "_";
reserved_cids.insert(s);
id2cid[id] = s;
}
return id2cid.at(id);
}
struct HierDirtyFlags
{
int dirty;
Module *module;
IdString hiername;
HierDirtyFlags *parent;
pool<SigBit> dirty_bits;
pool<Cell*> dirty_cells;
pool<SigBit> sticky_dirty_bits;
dict<IdString, HierDirtyFlags*> children;
string prefix, log_prefix;
HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent, const string &prefix, const string &log_prefix) :
dirty(0), module(module), hiername(hiername), parent(parent), prefix(prefix), log_prefix(log_prefix)
{
for (Cell *cell : module->cells()) {
Module *mod = module->design->module(cell->type);
if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this,
prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name));
}
}
~HierDirtyFlags()
{
for (auto &child : children)
delete child.second;
}
void set_dirty(SigBit bit)
{
if (dirty_bits.count(bit))
return;
dirty_bits.insert(bit);
sticky_dirty_bits.insert(bit);
HierDirtyFlags *p = this;
while (p != nullptr) {
p->dirty++;
p = p->parent;
}
}
void unset_dirty(SigBit bit)
{
if (dirty_bits.count(bit) == 0)
return;
dirty_bits.erase(bit);
HierDirtyFlags *p = this;
while (p != nullptr) {
p->dirty--;
log_assert(p->dirty >= 0);
p = p->parent;
}
}
void set_dirty(Cell *cell)
{
if (dirty_cells.count(cell))
return;
dirty_cells.insert(cell);
HierDirtyFlags *p = this;
while (p != nullptr) {
p->dirty++;
p = p->parent;
}
}
void unset_dirty(Cell *cell)
{
if (dirty_cells.count(cell) == 0)
return;
dirty_cells.erase(cell);
HierDirtyFlags *p = this;
while (p != nullptr) {
p->dirty--;
log_assert(p->dirty >= 0);
p = p->parent;
}
}
};
struct SimplecWorker
{
bool verbose = false;
int max_uintsize = 32;
Design *design;
dict<Module*, SigMap> sigmaps;
vector<string> signal_declarations;
pool<int> generated_sigtypes;
vector<string> util_declarations;
pool<string> generated_utils;
vector<string> struct_declarations;
pool<IdString> generated_structs;
vector<string> funct_declarations;
dict<Module*, dict<SigBit, pool<tuple<Cell*, IdString, int>>>> bit2cell;
dict<Module*, dict<SigBit, pool<SigBit>>> bit2output;
dict<Module*, pool<SigBit>> driven_bits;
dict<Cell*, int> topoidx;
pool<string> activated_cells;
pool<string> reactivated_cells;
SimplecWorker(Design *design) : design(design)
{
}
string sigtype(int n)
{
string struct_name = stringf("signal%d_t", n);
if (generated_sigtypes.count(n) == 0)
{
signal_declarations.push_back("");
signal_declarations.push_back(stringf("#ifndef YOSYS_SIMPLEC_SIGNAL%d_T", n));
signal_declarations.push_back(stringf("#define YOSYS_SIMPLEC_SIGNAL%d_T", n));
signal_declarations.push_back(stringf("typedef struct {"));
for (int k = 8; k <= max_uintsize; k = 2*k)
if (n <= k && k <= max_uintsize) {
signal_declarations.push_back(stringf(" uint%d_t value_%d_0 : %d;", k, n-1, n));
goto end_struct;
}
for (int k = 0; k < n; k += max_uintsize) {
int bits = std::min(max_uintsize, n-k);
signal_declarations.push_back(stringf(" uint%d_t value_%d_%d : %d;", max_uintsize, k+bits-1, k, bits));
}
end_struct:
signal_declarations.push_back(stringf("} signal%d_t;", n));
signal_declarations.push_back(stringf("#endif"));
generated_sigtypes.insert(n);
}
return struct_name;
}
void util_ifdef_guard(string s)
{
for (int i = 0; i < GetSize(s); i++)
if ('a' <= s[i] && s[i] <= 'z')
s[i] -= 'a' - 'A';
util_declarations.push_back("");
util_declarations.push_back(stringf("#ifndef %s", s.c_str()));
util_declarations.push_back(stringf("#define %s", s.c_str()));
}
string util_get_bit(const string &signame, int n, int idx)
{
if (n == 1 && idx == 0)
return signame + ".value_0_0";
string util_name = stringf("yosys_simplec_get_bit_%d_of_%d", idx, n);
if (generated_utils.count(util_name) == 0)
{
util_ifdef_guard(util_name);
util_declarations.push_back(stringf("static inline bool %s(const %s *sig)", util_name.c_str(), sigtype(n).c_str()));
util_declarations.push_back(stringf("{"));
int word_idx = idx / max_uintsize, word_offset = idx % max_uintsize;
string value_name = stringf("value_%d_%d", std::min(n-1, (word_idx+1)*max_uintsize-1), word_idx*max_uintsize);
util_declarations.push_back(stringf(" return (sig->%s >> %d) & 1;", value_name.c_str(), word_offset));
util_declarations.push_back(stringf("}"));
util_declarations.push_back(stringf("#endif"));
generated_utils.insert(util_name);
}
return stringf("%s(&%s)", util_name.c_str(), signame.c_str());
}
string util_set_bit(const string &signame, int n, int idx, const string &expr)
{
if (n == 1 && idx == 0)
return stringf(" %s.value_0_0 = %s;", signame.c_str(), expr.c_str());
string util_name = stringf("yosys_simplec_set_bit_%d_of_%d", idx, n);
if (generated_utils.count(util_name) == 0)
{
util_ifdef_guard(util_name);
util_declarations.push_back(stringf("static inline void %s(%s *sig, bool value)", util_name.c_str(), sigtype(n).c_str()));
util_declarations.push_back(stringf("{"));
int word_idx = idx / max_uintsize, word_offset = idx % max_uintsize;
string value_name = stringf("value_%d_%d", std::min(n-1, (word_idx+1)*max_uintsize-1), word_idx*max_uintsize);
#if 0
util_declarations.push_back(stringf(" if (value)"));
util_declarations.push_back(stringf(" sig->%s |= 1UL << %d;", value_name.c_str(), word_offset));
util_declarations.push_back(stringf(" else"));
util_declarations.push_back(stringf(" sig->%s &= ~(1UL << %d);", value_name.c_str(), word_offset));
#else
util_declarations.push_back(stringf(" sig->%s = (sig->%s & ~((uint%d_t)1 << %d)) | ((uint%d_t)value << %d);",
value_name.c_str(), value_name.c_str(), max_uintsize, word_offset, max_uintsize, word_offset));
#endif
util_declarations.push_back(stringf("}"));
util_declarations.push_back(stringf("#endif"));
generated_utils.insert(util_name);
}
return stringf(" %s(&%s, %s);", util_name.c_str(), signame.c_str(), expr.c_str());
}
void create_module_struct(Module *mod)
{
if (generated_structs.count(mod->name))
return;
generated_structs.insert(mod->name);
sigmaps[mod].set(mod);
for (Wire *w : mod->wires())
{
if (w->port_output)
for (auto bit : SigSpec(w))
bit2output[mod][sigmaps.at(mod)(bit)].insert(bit);
}
for (Cell *c : mod->cells())
{
for (auto &conn : c->connections())
{
if (!c->input(conn.first)) {
for (auto bit : sigmaps.at(mod)(conn.second))
driven_bits[mod].insert(bit);
continue;
}
int idx = 0;
for (auto bit : sigmaps.at(mod)(conn.second))
bit2cell[mod][bit].insert(tuple<Cell*, IdString, int>(c, conn.first, idx++));
}
if (design->module(c->type))
create_module_struct(design->module(c->type));
}
TopoSort<IdString> topo;
for (Cell *c : mod->cells())
{
topo.node(c->name);
for (auto &conn : c->connections())
{
if (!c->input(conn.first))
continue;
for (auto bit : sigmaps.at(mod)(conn.second))
for (auto &it : bit2cell[mod][bit])
topo.edge(c->name, std::get<0>(it)->name);
}
}
topo.analyze_loops = false;
topo.sort();
for (int i = 0; i < GetSize(topo.sorted); i++)
topoidx[mod->cell(topo.sorted[i])] = i;
string ifdef_name = stringf("yosys_simplec_%s_state_t", cid(mod->name).c_str());
for (int i = 0; i < GetSize(ifdef_name); i++)
if ('a' <= ifdef_name[i] && ifdef_name[i] <= 'z')
ifdef_name[i] -= 'a' - 'A';
struct_declarations.push_back("");
struct_declarations.push_back(stringf("#ifndef %s", ifdef_name.c_str()));
struct_declarations.push_back(stringf("#define %s", ifdef_name.c_str()));
struct_declarations.push_back(stringf("struct %s_state_t", cid(mod->name).c_str()));
struct_declarations.push_back("{");
struct_declarations.push_back(" // Input Ports");
for (Wire *w : mod->wires())
if (w->port_input)
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
struct_declarations.push_back("");
struct_declarations.push_back(" // Output Ports");
for (Wire *w : mod->wires())
if (!w->port_input && w->port_output)
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
struct_declarations.push_back("");
struct_declarations.push_back(" // Internal Wires");
for (Wire *w : mod->wires())
if (!w->port_input && !w->port_output)
struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
for (Cell *c : mod->cells())
if (design->module(c->type))
struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type).c_str(), cid(c->name).c_str(), log_id(c)));
struct_declarations.push_back(stringf("};"));
struct_declarations.push_back("#endif");
}
void eval_cell(HierDirtyFlags *work, Cell *cell)
{
if (cell->type.in("$_BUF_", "$_NOT_"))
{
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
string expr;
if (cell->type == "$_BUF_") expr = a_expr;
if (cell->type == "$_NOT_") expr = "!" + a_expr;
log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
work->set_dirty(y);
return;
}
if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
{
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
string expr;
if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_NAND_") expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_OR_") expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_NOR_") expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_XOR_") expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_ANDNOT_") expr = stringf("%s & (!%s)", a_expr.c_str(), b_expr.c_str());
if (cell->type == "$_ORNOT_") expr = stringf("%s | (!%s)", a_expr.c_str(), b_expr.c_str());
log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
work->set_dirty(y);
return;
}
if (cell->type.in("$_AOI3_", "$_OAI3_"))
{
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
string expr;
if (cell->type == "$_AOI3_") expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
if (cell->type == "$_OAI3_") expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
work->set_dirty(y);
return;
}
if (cell->type.in("$_AOI4_", "$_OAI4_"))
{
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
SigBit d = sigmaps.at(work->module)(cell->getPort("\\D"));
SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
string d_expr = d.wire ? util_get_bit(work->prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0";
string expr;
if (cell->type == "$_AOI4_") expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
if (cell->type == "$_OAI4_") expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
work->set_dirty(y);
return;
}
if (cell->type == "$_MUX_")
{
SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
SigBit s = sigmaps.at(work->module)(cell->getPort("\\S"));
SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
// casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
log_assert(y.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
work->set_dirty(y);
return;
}
log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type));
}
void eval_dirty(HierDirtyFlags *work)
{
while (work->dirty)
{
if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty()))
log(" In %s:\n", work->log_prefix.c_str());
while (!work->dirty_bits.empty() || !work->dirty_cells.empty())
{
if (!work->dirty_bits.empty())
{
SigSpec dirtysig(work->dirty_bits);
dirtysig.sort_and_unify();
for (SigChunk chunk : dirtysig.chunks()) {
if (chunk.wire == nullptr)
continue;
if (verbose)
log(" Propagating %s.%s[%d:%d].\n", work->log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix.c_str(), log_signal(chunk)));
}
for (SigBit bit : dirtysig)
{
if (bit2output[work->module].count(bit) && work->parent)
for (auto outbit : bit2output[work->module][bit])
{
Module *parent_mod = work->parent->module;
Cell *parent_cell = parent_mod->cell(work->hiername);
IdString port_name = outbit.wire->name;
int port_offset = outbit.offset;
SigBit parent_bit = sigmaps.at(parent_mod)(parent_cell->getPort(port_name)[port_offset]);
log_assert(bit.wire && parent_bit.wire);
funct_declarations.push_back(util_set_bit(work->parent->prefix + cid(parent_bit.wire->name), parent_bit.wire->width, parent_bit.offset,
util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
work->parent->set_dirty(parent_bit);
if (verbose)
log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset);
}
for (auto &port : bit2cell[work->module][bit])
{
if (work->children.count(std::get<0>(port)->name))
{
HierDirtyFlags *child = work->children.at(std::get<0>(port)->name);
SigBit child_bit = sigmaps.at(child->module)(SigBit(child->module->wire(std::get<1>(port)), std::get<2>(port)));
log_assert(bit.wire && child_bit.wire);
funct_declarations.push_back(util_set_bit(work->prefix + cid(child->hiername) + "." + cid(child_bit.wire->name),
child_bit.wire->width, child_bit.offset, util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
child->set_dirty(child_bit);
if (verbose)
log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset);
} else {
if (verbose)
log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix.c_str(), log_id(std::get<0>(port)),
work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
work->set_dirty(std::get<0>(port));
}
}
work->unset_dirty(bit);
}
}
if (!work->dirty_cells.empty())
{
Cell *cell = nullptr;
for (auto c : work->dirty_cells)
if (cell == nullptr || topoidx.at(cell) < topoidx.at(c))
cell = c;
string hiername = work->log_prefix + "." + log_id(cell);
if (verbose)
log(" Evaluating %s (%s, best of %d).\n", hiername.c_str(), log_id(cell->type), GetSize(work->dirty_cells));
if (activated_cells.count(hiername))
reactivated_cells.insert(hiername);
activated_cells.insert(hiername);
eval_cell(work, cell);
work->unset_dirty(cell);
}
}
for (auto &child : work->children)
eval_dirty(child.second);
}
}
void eval_sticky_dirty(HierDirtyFlags *work)
{
Module *mod = work->module;
for (Wire *w : mod->wires())
for (SigBit bit : SigSpec(w))
{
SigBit canonical_bit = sigmaps.at(mod)(bit);
if (canonical_bit == bit)
continue;
if (work->sticky_dirty_bits.count(canonical_bit) == 0)
continue;
if (bit.wire == nullptr || canonical_bit.wire == nullptr)
continue;
funct_declarations.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset,
util_get_bit(work->prefix + cid(canonical_bit.wire->name), canonical_bit.wire->width, canonical_bit.offset).c_str()));
if (verbose)
log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset,
work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
}
work->sticky_dirty_bits.clear();
for (auto &child : work->children)
eval_sticky_dirty(child.second);
}
void make_func(HierDirtyFlags *work, const string &func_name, const vector<string> &preamble)
{
log("Generating function %s():\n", func_name.c_str());
activated_cells.clear();
reactivated_cells.clear();
funct_declarations.push_back("");
funct_declarations.push_back(stringf("static void %s(struct %s_state_t *state)", func_name.c_str(), cid(work->module->name).c_str()));
funct_declarations.push_back("{");
for (auto &line : preamble)
funct_declarations.push_back(line);
eval_dirty(work);
eval_sticky_dirty(work);
funct_declarations.push_back("}");
log(" Activated %d cells (%d activated more than once).\n", GetSize(activated_cells), GetSize(reactivated_cells));
}
void eval_init(HierDirtyFlags *work, vector<string> &preamble)
{
Module *module = work->module;
for (Wire *w : module->wires())
{
if (w->attributes.count("\\init"))
{
SigSpec sig = sigmaps.at(module)(w);
Const val = w->attributes.at("\\init");
val.bits.resize(GetSize(sig), State::Sx);
for (int i = 0; i < GetSize(sig); i++)
if (val[i] == State::S0 || val[i] == State::S1) {
SigBit bit = sig[i];
preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false"));
work->set_dirty(bit);
}
}
for (SigBit bit : SigSpec(w))
{
SigBit val = sigmaps.at(module)(bit);
if (val == State::S0 || val == State::S1)
preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false"));
if (driven_bits.at(module).count(val) == 0)
work->set_dirty(val);
}
}
work->set_dirty(State::S0);
work->set_dirty(State::S1);
for (auto &child : work->children)
eval_init(child.second, preamble);
}
void make_init_func(HierDirtyFlags *work)
{
vector<string> preamble;
eval_init(work, preamble);
make_func(work, cid(work->module->name) + "_init", preamble);
}
void make_eval_func(HierDirtyFlags *work)
{
Module *mod = work->module;
vector<string> preamble;
for (Wire *w : mod->wires()) {
if (w->port_input)
for (SigBit bit : sigmaps.at(mod)(w))
work->set_dirty(bit);
}
make_func(work, cid(work->module->name) + "_eval", preamble);
}
void make_tick_func(HierDirtyFlags* /* work */)
{
// FIXME
}
void run(Module *mod)
{
create_module_struct(mod);
HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name));
make_init_func(&work);
make_eval_func(&work);
make_tick_func(&work);
}
void write(std::ostream &f)
{
f << "#include <stdint.h>" << std::endl;
f << "#include <stdbool.h>" << std::endl;
for (auto &line : signal_declarations)
f << line << std::endl;
for (auto &line : util_declarations)
f << line << std::endl;
for (auto &line : struct_declarations)
f << line << std::endl;
for (auto &line : funct_declarations)
f << line << std::endl;
}
};
struct SimplecBackend : public Backend {
SimplecBackend() : Backend("simplec", "convert design to simple C code") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_simplec [options] [filename]\n");
log("\n");
log("Write simple C code for simulating the design. The C code written can be used to\n");
log("simulate the design in a C environment, but the purpose of this command is to\n");
log("generate code that works well with C-based formal verification.\n");
log("\n");
log(" -verbose\n");
log(" this will print the recursive walk used to export the modules.\n");
log("\n");
log(" -i8, -i16, -i32, -i64\n");
log(" set the maximum integer bit width to use in the generated code.\n");
log("\n");
log("THIS COMMAND IS UNDER CONSTRUCTION\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
reserved_cids.clear();
id2cid.clear();
SimplecWorker worker(design);
log_header(design, "Executing SIMPLEC backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-verbose") {
worker.verbose = true;
continue;
}
if (args[argidx] == "-i8") {
worker.max_uintsize = 8;
continue;
}
if (args[argidx] == "-i16") {
worker.max_uintsize = 16;
continue;
}
if (args[argidx] == "-i32") {
worker.max_uintsize = 32;
continue;
}
if (args[argidx] == "-i64") {
worker.max_uintsize = 64;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
Module *topmod = design->top_module();
if (topmod == nullptr)
log_error("Current design has no top module.\n");
worker.run(topmod);
worker.write(*f);
}
} SimplecBackend;
PRIVATE_NAMESPACE_END

View File

@ -1,5 +0,0 @@
#!/bin/bash
set -ex
../../yosys -p 'synth -top test; write_simplec -verbose -i8 test00_uut.c' test00_uut.v
clang -o test00_tb test00_tb.c
./test00_tb

View File

@ -1,93 +0,0 @@
#include <stdio.h>
#include <assert.h>
#include "test00_uut.c"
uint32_t xorshift32()
{
static uint32_t x32 = 314159265;
x32 ^= x32 << 13;
x32 ^= x32 >> 17;
x32 ^= x32 << 5;
return x32;
}
int main()
{
struct test_state_t state;
uint32_t a, b, c, x, y, z, w;
bool first_eval = true;
for (int i = 0; i < 10; i++)
{
a = xorshift32();
b = xorshift32();
c = xorshift32();
x = (a & b) | c;
y = a & (b | c);
z = a ^ b ^ c;
w = z;
state.a.value_7_0 = a;
state.a.value_15_8 = a >> 8;
state.a.value_23_16 = a >> 16;
state.a.value_31_24 = a >> 24;
state.b.value_7_0 = b;
state.b.value_15_8 = b >> 8;
state.b.value_23_16 = b >> 16;
state.b.value_31_24 = b >> 24;
state.c.value_7_0 = c;
state.c.value_15_8 = c >> 8;
state.c.value_23_16 = c >> 16;
state.c.value_31_24 = c >> 24;
if (first_eval) {
first_eval = false;
test_init(&state);
} else {
test_eval(&state);
}
uint32_t uut_x = 0;
uut_x |= (uint32_t)state.x.value_7_0;
uut_x |= (uint32_t)state.x.value_15_8 << 8;
uut_x |= (uint32_t)state.x.value_23_16 << 16;
uut_x |= (uint32_t)state.x.value_31_24 << 24;
uint32_t uut_y = 0;
uut_y |= (uint32_t)state.y.value_7_0;
uut_y |= (uint32_t)state.y.value_15_8 << 8;
uut_y |= (uint32_t)state.y.value_23_16 << 16;
uut_y |= (uint32_t)state.y.value_31_24 << 24;
uint32_t uut_z = 0;
uut_z |= (uint32_t)state.z.value_7_0;
uut_z |= (uint32_t)state.z.value_15_8 << 8;
uut_z |= (uint32_t)state.z.value_23_16 << 16;
uut_z |= (uint32_t)state.z.value_31_24 << 24;
uint32_t uut_w = 0;
uut_w |= (uint32_t)state.w.value_7_0;
uut_w |= (uint32_t)state.w.value_15_8 << 8;
uut_w |= (uint32_t)state.w.value_23_16 << 16;
uut_w |= (uint32_t)state.w.value_31_24 << 24;
printf("---\n");
printf("A: 0x%08x\n", a);
printf("B: 0x%08x\n", b);
printf("C: 0x%08x\n", c);
printf("X: 0x%08x 0x%08x\n", x, uut_x);
printf("Y: 0x%08x 0x%08x\n", y, uut_y);
printf("Z: 0x%08x 0x%08x\n", z, uut_z);
printf("W: 0x%08x 0x%08x\n", w, uut_w);
assert(x == uut_x);
assert(y == uut_y);
assert(z == uut_z);
assert(w == uut_w);
}
return 0;
}

View File

@ -1,14 +0,0 @@
module test(input [31:0] a, b, c, output [31:0] x, y, z, w);
unit_x unit_x_inst (.a(a), .b(b), .c(c), .x(x));
unit_y unit_y_inst (.a(a), .b(b), .c(c), .y(y));
assign z = a ^ b ^ c, w = z;
endmodule
module unit_x(input [31:0] a, b, c, output [31:0] x);
assign x = (a & b) | c;
endmodule
module unit_y(input [31:0] a, b, c, output [31:0] y);
assign y = a & (b | c);
endmodule

View File

@ -1 +0,0 @@
test_cells

View File

@ -1,32 +0,0 @@
OBJS += backends/smt2/smt2.o
ifneq ($(CONFIG),mxe)
ifneq ($(CONFIG),emcc)
# MSYS targets support yosys-smtbmc, but require a launcher script
ifeq ($(CONFIG),$(filter $(CONFIG),msys2 msys2-64))
TARGETS += yosys-smtbmc.exe yosys-smtbmc-script.py
# Needed to find the Python interpreter for yosys-smtbmc scripts.
# Override if necessary, it is only used for msys2 targets.
PYTHON := $(shell cygpath -w -m $(PREFIX)/bin/python3)
yosys-smtbmc-script.py: backends/smt2/smtbmc.py
$(P) sed -e 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' \
-e "s|#!/usr/bin/env python3|#!$(PYTHON)|" < $< > $@
yosys-smtbmc.exe: misc/launcher.c yosys-smtbmc-script.py
$(P) gcc -DGUI=0 -O -s -o $@ $<
# Other targets
else
TARGETS += yosys-smtbmc
yosys-smtbmc: backends/smt2/smtbmc.py
$(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
$(Q) chmod +x $@.new
$(Q) mv $@.new $@
endif
$(eval $(call add_share_file,share/python3,backends/smt2/smtio.py))
endif
endif

View File

@ -1,11 +0,0 @@
module main(input clk);
reg [3:0] counter = 0;
always @(posedge clk) begin
if (counter == 10)
counter <= 0;
else
counter <= counter + 1;
end
assert property (counter != 15);
// assert property (counter <= 10);
endmodule

View File

@ -1,3 +0,0 @@
read_verilog -formal example.v
hierarchy; proc; opt; memory -nordff -nomap; opt -fast
write_smt2 -bv -mem -wires example.smt2

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
#!/bin/bash
set -ex
rm -rf test_cells
mkdir test_cells
cd test_cells
../../../yosys -p 'test_cell -muxdiv -w test all /$alu /$macc /$fa /$lcu /$lut /$shift /$shiftx'
cat > miter.tpl <<- EOT
; #model# (set-option :produce-models true)
(set-logic QF_UFBV)
%%
(declare-fun s () miter_s)
(assert (|miter_n trigger| s))
(check-sat)
; #model# (get-value ((|miter_n in_A| s) (|miter_n in_B| s) (|miter_n gold_Y| s) (|miter_n gate_Y| s) (|miter_n trigger| s)))
EOT
for x in $(set +x; ls test_*.il | sort -R); do
x=${x%.il}
cat > $x.ys <<- EOT
read_ilang $x.il
copy gold gate
cd gate
techmap; opt; abc;;
cd ..
miter -equiv -flatten -make_outputs gold gate miter
hierarchy -check -top miter
dump
write_smt2 -bv -tpl miter.tpl $x.smt2
EOT
../../../yosys -q $x.ys
if ! cvc4 $x.smt2 > $x.result; then
cat $x.result
exit 1
fi
if ! grep unsat $x.result; then
echo "Proof failed! Extracting model..."
sed -i 's/^; #model# //' $x.smt2
cvc4 $x.smt2
exit 1
fi
done
set +x
echo ""
echo " All tests passed."
echo ""
exit 0

View File

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

View File

@ -1,807 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SmvWorker
{
CellTypes ct;
SigMap sigmap;
RTLIL::Module *module;
std::ostream &f;
bool verbose;
int idcounter;
dict<IdString, shared_str> idcache;
pool<shared_str> used_names;
vector<shared_str> strbuf;
pool<Wire*> partial_assignment_wires;
dict<SigBit, std::pair<const char*, int>> partial_assignment_bits;
vector<string> inputvars, vars, definitions, assignments, invarspecs;
const char *cid()
{
while (true) {
shared_str s(stringf("_%d", idcounter++));
if (!used_names.count(s)) {
used_names.insert(s);
return s.c_str();
}
}
}
const char *cid(IdString id, bool precache = false)
{
if (!idcache.count(id))
{
string name = stringf("_%s", id.c_str());
if (name.substr(0, 2) == "_\\")
name = "_" + name.substr(2);
for (auto &c : name) {
if (c == '|' || c == '$' || c == '_') continue;
if (c >= 'a' && c <='z') continue;
if (c >= 'A' && c <='Z') continue;
if (c >= '0' && c <='9') continue;
if (precache) return nullptr;
c = '#';
}
if (name == "_main")
name = "main";
while (used_names.count(name))
name += "_";
shared_str s(name);
used_names.insert(s);
idcache[id] = s;
}
return idcache.at(id).c_str();
}
SmvWorker(RTLIL::Module *module, bool verbose, std::ostream &f) :
ct(module->design), sigmap(module), module(module), f(f), verbose(verbose), idcounter(0)
{
for (auto mod : module->design->modules())
cid(mod->name, true);
for (auto wire : module->wires())
cid(wire->name, true);
for (auto cell : module->cells()) {
cid(cell->name, true);
cid(cell->type, true);
for (auto &conn : cell->connections())
cid(conn.first, true);
}
}
const char *rvalue(SigSpec sig, int width = -1, bool is_signed = false)
{
string s;
int count_chunks = 0;
sigmap.apply(sig);
for (int i = 0; i < GetSize(sig); i++)
if (partial_assignment_bits.count(sig[i]))
{
int width = 1;
const auto &bit_a = partial_assignment_bits.at(sig[i]);
while (i+width < GetSize(sig))
{
if (!partial_assignment_bits.count(sig[i+width]))
break;
const auto &bit_b = partial_assignment_bits.at(sig[i+width]);
if (strcmp(bit_a.first, bit_b.first))
break;
if (bit_a.second+width != bit_b.second)
break;
width++;
}
if (i+width < GetSize(sig))
s = stringf("%s :: ", rvalue(sig.extract(i+width, GetSize(sig)-(width+i))));
s += stringf("%s[%d:%d]", bit_a.first, bit_a.second+width-1, bit_a.second);
if (i > 0)
s += stringf(" :: %s", rvalue(sig.extract(0, i)));
count_chunks = 3;
goto continue_with_resize;
}
for (auto &c : sig.chunks()) {
count_chunks++;
if (!s.empty())
s = " :: " + s;
if (c.wire) {
if (c.offset != 0 || c.width != c.wire->width)
s = stringf("%s[%d:%d]", cid(c.wire->name), c.offset+c.width-1, c.offset) + s;
else
s = cid(c.wire->name) + s;
} else {
string v = stringf("0ub%d_", c.width);
for (int i = c.width-1; i >= 0; i--)
v += c.data.at(i) == State::S1 ? '1' : '0';
s = v + s;
}
}
continue_with_resize:;
if (width >= 0) {
if (is_signed) {
if (GetSize(sig) > width)
s = stringf("signed(resize(%s, %d))", s.c_str(), width);
else
s = stringf("resize(signed(%s), %d)", s.c_str(), width);
} else
s = stringf("resize(%s, %d)", s.c_str(), width);
} else if (is_signed)
s = stringf("signed(%s)", s.c_str());
else if (count_chunks > 1)
s = stringf("(%s)", s.c_str());
strbuf.push_back(s);
return strbuf.back().c_str();
}
const char *rvalue_u(SigSpec sig, int width = -1)
{
return rvalue(sig, width, false);
}
const char *rvalue_s(SigSpec sig, int width = -1, bool is_signed = true)
{
return rvalue(sig, width, is_signed);
}
const char *lvalue(SigSpec sig)
{
sigmap.apply(sig);
if (sig.is_wire())
return rvalue(sig);
const char *temp_id = cid();
// f << stringf(" %s : unsigned word[%d]; -- %s\n", temp_id, GetSize(sig), log_signal(sig));
int offset = 0;
for (auto bit : sig) {
log_assert(bit.wire != nullptr);
partial_assignment_wires.insert(bit.wire);
partial_assignment_bits[bit] = std::pair<const char*, int>(temp_id, offset++);
}
return temp_id;
}
void run()
{
f << stringf("MODULE %s\n", cid(module->name));
for (auto wire : module->wires())
{
if (SigSpec(wire) != sigmap(wire))
partial_assignment_wires.insert(wire);
if (wire->port_input)
inputvars.push_back(stringf("%s : unsigned word[%d]; -- %s", cid(wire->name), wire->width, log_id(wire)));
if (wire->attributes.count("\\init"))
assignments.push_back(stringf("init(%s) := %s;", lvalue(wire), rvalue(wire->attributes.at("\\init"))));
}
for (auto cell : module->cells())
{
// FIXME: $slice, $concat, $mem
if (cell->type.in("$assert"))
{
SigSpec sig_a = cell->getPort("\\A");
SigSpec sig_en = cell->getPort("\\EN");
invarspecs.push_back(stringf("!bool(%s) | bool(%s);", rvalue(sig_en), rvalue(sig_a)));
continue;
}
if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx"))
{
SigSpec sig_a = cell->getPort("\\A");
SigSpec sig_b = cell->getPort("\\B");
int width_y = GetSize(cell->getPort("\\Y"));
int shift_b_width = GetSize(sig_b);
int width_ay = max(GetSize(sig_a), width_y);
int width = width_ay;
for (int i = 1, j = 0;; i <<= 1, j++)
if (width_ay < i) {
width = i-1;
shift_b_width = min(shift_b_width, j);
break;
}
bool signed_a = cell->getParam("\\A_SIGNED").as_bool();
bool signed_b = cell->getParam("\\B_SIGNED").as_bool();
string op = cell->type.in("$shl", "$sshl") ? "<<" : ">>";
string expr, expr_a;
if (cell->type == "$sshr" && signed_a)
{
expr_a = rvalue_s(sig_a, width);
expr = stringf("resize(unsigned(%s %s %s), %d)", expr_a.c_str(), op.c_str(), rvalue(sig_b.extract(0, shift_b_width)), width_y);
if (shift_b_width < GetSize(sig_b))
expr = stringf("%s != 0ud%d_0 ? (bool(%s) ? !0ud%d_0 : 0ud%d_0) : %s",
rvalue(sig_b.extract(shift_b_width, GetSize(sig_b) - shift_b_width)), GetSize(sig_b) - shift_b_width,
rvalue(sig_a[GetSize(sig_a)-1]), width_y, width_y, expr.c_str());
}
else if (cell->type.in("$shift", "$shiftx") && signed_b)
{
expr_a = rvalue_u(sig_a, width);
const char *b_shr = rvalue_u(sig_b);
const char *b_shl = cid();
// f << stringf(" %s : unsigned word[%d]; -- neg(%s)\n", b_shl, GetSize(sig_b), log_signal(sig_b));
definitions.push_back(stringf("%s := unsigned(-%s);", b_shl, rvalue_s(sig_b)));
string expr_shl = stringf("resize(%s << %s[%d:0], %d)", expr_a.c_str(), b_shl, shift_b_width-1, width_y);
string expr_shr = stringf("resize(%s >> %s[%d:0], %d)", expr_a.c_str(), b_shr, shift_b_width-1, width_y);
if (shift_b_width < GetSize(sig_b)) {
expr_shl = stringf("%s[%d:%d] != 0ud%d_0 ? 0ud%d_0 : %s", b_shl, GetSize(sig_b)-1, shift_b_width,
GetSize(sig_b)-shift_b_width, width_y, expr_shl.c_str());
expr_shr = stringf("%s[%d:%d] != 0ud%d_0 ? 0ud%d_0 : %s", b_shr, GetSize(sig_b)-1, shift_b_width,
GetSize(sig_b)-shift_b_width, width_y, expr_shr.c_str());
}
expr = stringf("bool(%s) ? %s : %s", rvalue(sig_b[GetSize(sig_b)-1]), expr_shl.c_str(), expr_shr.c_str());
}
else
{
if (cell->type.in("$shift", "$shiftx") || !signed_a)
expr_a = rvalue_u(sig_a, width);
else
expr_a = stringf("resize(unsigned(%s), %d)", rvalue_s(sig_a, width_ay), width);
expr = stringf("resize(%s %s %s[%d:0], %d)", expr_a.c_str(), op.c_str(), rvalue_u(sig_b), shift_b_width-1, width_y);
if (shift_b_width < GetSize(sig_b))
expr = stringf("%s[%d:%d] != 0ud%d_0 ? 0ud%d_0 : %s", rvalue_u(sig_b), GetSize(sig_b)-1, shift_b_width,
GetSize(sig_b)-shift_b_width, width_y, expr.c_str());
}
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str()));
continue;
}
if (cell->type.in("$not", "$pos", "$neg"))
{
int width = GetSize(cell->getPort("\\Y"));
string expr_a, op;
if (cell->type == "$not") op = "!";
if (cell->type == "$pos") op = "";
if (cell->type == "$neg") op = "-";
if (cell->getParam("\\A_SIGNED").as_bool())
{
definitions.push_back(stringf("%s := unsigned(%s%s);", lvalue(cell->getPort("\\Y")),
op.c_str(), rvalue_s(cell->getPort("\\A"), width)));
}
else
{
definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")),
op.c_str(), rvalue_u(cell->getPort("\\A"), width)));
}
continue;
}
if (cell->type.in("$add", "$sub", "$mul", "$and", "$or", "$xor", "$xnor"))
{
int width = GetSize(cell->getPort("\\Y"));
string expr_a, expr_b, op;
if (cell->type == "$add") op = "+";
if (cell->type == "$sub") op = "-";
if (cell->type == "$mul") op = "*";
if (cell->type == "$and") op = "&";
if (cell->type == "$or") op = "|";
if (cell->type == "$xor") op = "xor";
if (cell->type == "$xnor") op = "xnor";
if (cell->getParam("\\A_SIGNED").as_bool())
{
definitions.push_back(stringf("%s := unsigned(%s %s %s);", lvalue(cell->getPort("\\Y")),
rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width)));
}
else
{
definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")),
rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width)));
}
continue;
}
if (cell->type.in("$div", "$mod"))
{
int width_y = GetSize(cell->getPort("\\Y"));
int width = max(width_y, GetSize(cell->getPort("\\A")));
width = max(width, GetSize(cell->getPort("\\B")));
string expr_a, expr_b, op;
if (cell->type == "$div") op = "/";
if (cell->type == "$mod") op = "mod";
if (cell->getParam("\\A_SIGNED").as_bool())
{
definitions.push_back(stringf("%s := resize(unsigned(%s %s %s), %d);", lvalue(cell->getPort("\\Y")),
rvalue_s(cell->getPort("\\A"), width), op.c_str(), rvalue_s(cell->getPort("\\B"), width), width_y));
}
else
{
definitions.push_back(stringf("%s := resize(%s %s %s, %d);", lvalue(cell->getPort("\\Y")),
rvalue_u(cell->getPort("\\A"), width), op.c_str(), rvalue_u(cell->getPort("\\B"), width), width_y));
}
continue;
}
if (cell->type.in("$eq", "$ne", "$eqx", "$nex", "$lt", "$le", "$ge", "$gt"))
{
int width = max(GetSize(cell->getPort("\\A")), GetSize(cell->getPort("\\B")));
string expr_a, expr_b, op;
if (cell->type == "$eq") op = "=";
if (cell->type == "$ne") op = "!=";
if (cell->type == "$eqx") op = "=";
if (cell->type == "$nex") op = "!=";
if (cell->type == "$lt") op = "<";
if (cell->type == "$le") op = "<=";
if (cell->type == "$ge") op = ">=";
if (cell->type == "$gt") op = ">";
if (cell->getParam("\\A_SIGNED").as_bool())
{
expr_a = stringf("resize(signed(%s), %d)", rvalue(cell->getPort("\\A")), width);
expr_b = stringf("resize(signed(%s), %d)", rvalue(cell->getPort("\\B")), width);
}
else
{
expr_a = stringf("resize(%s, %d)", rvalue(cell->getPort("\\A")), width);
expr_b = stringf("resize(%s, %d)", rvalue(cell->getPort("\\B")), width);
}
definitions.push_back(stringf("%s := resize(word1(%s %s %s), %d);", lvalue(cell->getPort("\\Y")),
expr_a.c_str(), op.c_str(), expr_b.c_str(), GetSize(cell->getPort("\\Y"))));
continue;
}
if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool"))
{
int width_a = GetSize(cell->getPort("\\A"));
int width_y = GetSize(cell->getPort("\\Y"));
const char *expr_a = rvalue(cell->getPort("\\A"));
const char *expr_y = lvalue(cell->getPort("\\Y"));
string expr;
if (cell->type == "$reduce_and") expr = stringf("%s = !0ub%d_0", expr_a, width_a);
if (cell->type == "$reduce_or") expr = stringf("%s != 0ub%d_0", expr_a, width_a);
if (cell->type == "$reduce_bool") expr = stringf("%s != 0ub%d_0", expr_a, width_a);
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
continue;
}
if (cell->type.in("$reduce_xor", "$reduce_xnor"))
{
int width_y = GetSize(cell->getPort("\\Y"));
const char *expr_y = lvalue(cell->getPort("\\Y"));
string expr;
for (auto bit : cell->getPort("\\A")) {
if (!expr.empty())
expr += " xor ";
expr += rvalue(bit);
}
if (cell->type == "$reduce_xnor")
expr = "!(" + expr + ")";
definitions.push_back(stringf("%s := resize(%s, %d);", expr_y, expr.c_str(), width_y));
continue;
}
if (cell->type.in("$logic_and", "$logic_or"))
{
int width_a = GetSize(cell->getPort("\\A"));
int width_b = GetSize(cell->getPort("\\B"));
int width_y = GetSize(cell->getPort("\\Y"));
string expr_a = stringf("(%s != 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a);
string expr_b = stringf("(%s != 0ub%d_0)", rvalue(cell->getPort("\\B")), width_b);
const char *expr_y = lvalue(cell->getPort("\\Y"));
string expr;
if (cell->type == "$logic_and") expr = expr_a + " & " + expr_b;
if (cell->type == "$logic_or") expr = expr_a + " | " + expr_b;
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr.c_str(), width_y));
continue;
}
if (cell->type.in("$logic_not"))
{
int width_a = GetSize(cell->getPort("\\A"));
int width_y = GetSize(cell->getPort("\\Y"));
string expr_a = stringf("(%s = 0ub%d_0)", rvalue(cell->getPort("\\A")), width_a);
const char *expr_y = lvalue(cell->getPort("\\Y"));
definitions.push_back(stringf("%s := resize(word1(%s), %d);", expr_y, expr_a.c_str(), width_y));
continue;
}
if (cell->type.in("$mux", "$pmux"))
{
int width = GetSize(cell->getPort("\\Y"));
SigSpec sig_a = cell->getPort("\\A");
SigSpec sig_b = cell->getPort("\\B");
SigSpec sig_s = cell->getPort("\\S");
string expr;
for (int i = 0; i < GetSize(sig_s); i++)
expr += stringf("bool(%s) ? %s : ", rvalue(sig_s[i]), rvalue(sig_b.extract(i*width, width)));
expr += rvalue(sig_a);
definitions.push_back(stringf("%s := %s;", lvalue(cell->getPort("\\Y")), expr.c_str()));
continue;
}
if (cell->type == "$dff")
{
vars.push_back(stringf("%s : unsigned word[%d]; -- %s", lvalue(cell->getPort("\\Q")), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q"))));
assignments.push_back(stringf("next(%s) := %s;", lvalue(cell->getPort("\\Q")), rvalue(cell->getPort("\\D"))));
continue;
}
if (cell->type.in("$_BUF_", "$_NOT_"))
{
string op = cell->type == "$_NOT_" ? "!" : "";
definitions.push_back(stringf("%s := %s%s;", lvalue(cell->getPort("\\Y")), op.c_str(), rvalue(cell->getPort("\\A"))));
continue;
}
if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
{
string op;
if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_")) op = "&";
if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_")) op = "|";
if (cell->type.in("$_XOR_")) op = "xor";
if (cell->type.in("$_XNOR_")) op = "xnor";
if (cell->type.in("$_ANDNOT_", "$_ORNOT_"))
definitions.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
else
if (cell->type.in("$_NAND_", "$_NOR_"))
definitions.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
else
definitions.push_back(stringf("%s := %s %s %s;", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
continue;
}
if (cell->type == "$_MUX_")
{
definitions.push_back(stringf("%s := bool(%s) ? %s : %s;", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\S")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\A"))));
continue;
}
if (cell->type == "$_AOI3_")
{
definitions.push_back(stringf("%s := !((%s & %s) | %s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C"))));
continue;
}
if (cell->type == "$_OAI3_")
{
definitions.push_back(stringf("%s := !((%s | %s) & %s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C"))));
continue;
}
if (cell->type == "$_AOI4_")
{
definitions.push_back(stringf("%s := !((%s & %s) | (%s & %s));", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D"))));
continue;
}
if (cell->type == "$_OAI4_")
{
definitions.push_back(stringf("%s := !((%s | %s) & (%s | %s));", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), rvalue(cell->getPort("\\B")), rvalue(cell->getPort("\\C")), rvalue(cell->getPort("\\D"))));
continue;
}
if (cell->type[0] == '$')
log_error("Found currently unsupported cell type %s (%s.%s).\n", log_id(cell->type), log_id(module), log_id(cell));
// f << stringf(" %s : %s;\n", cid(cell->name), cid(cell->type));
for (auto &conn : cell->connections())
if (cell->output(conn.first))
definitions.push_back(stringf("%s := %s.%s;", lvalue(conn.second), cid(cell->name), cid(conn.first)));
else
definitions.push_back(stringf("%s.%s := %s;", cid(cell->name), cid(conn.first), rvalue(conn.second)));
}
for (Wire *wire : partial_assignment_wires)
{
string expr;
for (int i = 0; i < wire->width; i++)
{
if (!expr.empty())
expr = " :: " + expr;
if (partial_assignment_bits.count(sigmap(SigBit(wire, i))))
{
int width = 1;
const auto &bit_a = partial_assignment_bits.at(sigmap(SigBit(wire, i)));
while (i+1 < wire->width)
{
SigBit next_bit = sigmap(SigBit(wire, i+1));
if (!partial_assignment_bits.count(next_bit))
break;
const auto &bit_b = partial_assignment_bits.at(next_bit);
if (strcmp(bit_a.first, bit_b.first))
break;
if (bit_a.second+width != bit_b.second)
break;
width++, i++;
}
expr = stringf("%s[%d:%d]", bit_a.first, bit_a.second+width-1, bit_a.second) + expr;
}
else if (sigmap(SigBit(wire, i)).wire == nullptr)
{
string bits;
SigSpec sig = sigmap(SigSpec(wire, i));
while (i+1 < wire->width) {
SigBit next_bit = sigmap(SigBit(wire, i+1));
if (next_bit.wire != nullptr)
break;
sig.append(next_bit);
i++;
}
for (int k = GetSize(sig)-1; k >= 0; k--)
bits += sig[k] == State::S1 ? '1' : '0';
expr = stringf("0ub%d_%s", GetSize(bits), bits.c_str()) + expr;
}
else if (sigmap(SigBit(wire, i)) == SigBit(wire, i))
{
int length = 1;
while (i+1 < wire->width) {
if (partial_assignment_bits.count(sigmap(SigBit(wire, i+1))))
break;
if (sigmap(SigBit(wire, i+1)) != SigBit(wire, i+1))
break;
i++, length++;
}
expr = stringf("0ub%d_0", length) + expr;
}
else
{
string bits;
SigSpec sig = sigmap(SigSpec(wire, i));
while (i+1 < wire->width) {
SigBit next_bit = sigmap(SigBit(wire, i+1));
if (next_bit.wire == nullptr || partial_assignment_bits.count(next_bit))
break;
sig.append(next_bit);
i++;
}
expr = rvalue(sig) + expr;
}
}
definitions.push_back(stringf("%s := %s;", cid(wire->name), expr.c_str()));
}
if (!inputvars.empty()) {
f << stringf(" IVAR\n");
for (const string &line : inputvars)
f << stringf(" %s\n", line.c_str());
}
if (!vars.empty()) {
f << stringf(" VAR\n");
for (const string &line : vars)
f << stringf(" %s\n", line.c_str());
}
if (!definitions.empty()) {
f << stringf(" DEFINE\n");
for (const string &line : definitions)
f << stringf(" %s\n", line.c_str());
}
if (!assignments.empty()) {
f << stringf(" ASSIGN\n");
for (const string &line : assignments)
f << stringf(" %s\n", line.c_str());
}
if (!invarspecs.empty()) {
for (const string &line : invarspecs)
f << stringf(" INVARSPEC %s\n", line.c_str());
}
}
};
struct SmvBackend : public Backend {
SmvBackend() : Backend("smv", "write design to SMV file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_smv [options] [filename]\n");
log("\n");
log("Write an SMV description of the current design.\n");
log("\n");
log(" -verbose\n");
log(" this will print the recursive walk used to export the modules.\n");
log("\n");
log(" -tpl <template_file>\n");
log(" use the given template file. the line containing only the token '%%%%'\n");
log(" is replaced with the regular output of this command.\n");
log("\n");
log("THIS COMMAND IS UNDER CONSTRUCTION\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::ifstream template_f;
bool verbose = false;
log_header(design, "Executing SMV backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-tpl" && argidx+1 < args.size()) {
template_f.open(args[++argidx]);
if (template_f.fail())
log_error("Can't open template file `%s'.\n", args[argidx].c_str());
continue;
}
if (args[argidx] == "-verbose") {
verbose = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);
pool<Module*> modules;
for (auto module : design->modules())
if (!module->get_blackbox_attribute() && !module->has_memories_warn() && !module->has_processes_warn())
modules.insert(module);
if (template_f.is_open())
{
std::string line;
while (std::getline(template_f, line))
{
int indent = 0;
while (indent < GetSize(line) && (line[indent] == ' ' || line[indent] == '\t'))
indent++;
if (line[indent] == '%')
{
vector<string> stmt = split_tokens(line);
if (GetSize(stmt) == 1 && stmt[0] == "%%")
break;
if (GetSize(stmt) == 2 && stmt[0] == "%module")
{
Module *module = design->module(RTLIL::escape_id(stmt[1]));
modules.erase(module);
if (module == nullptr)
log_error("Module '%s' not found.\n", stmt[1].c_str());
*f << stringf("-- SMV description generated by %s\n", yosys_version_str);
log("Creating SMV representation of module %s.\n", log_id(module));
SmvWorker worker(module, verbose, *f);
worker.run();
*f << stringf("-- end of yosys output\n");
continue;
}
log_error("Unknown template statement: '%s'", line.c_str() + indent);
}
*f << line << std::endl;
}
}
if (!modules.empty())
{
*f << stringf("-- SMV description generated by %s\n", yosys_version_str);
for (auto module : modules) {
log("Creating SMV representation of module %s.\n", log_id(module));
SmvWorker worker(module, verbose, *f);
worker.run();
}
*f << stringf("-- end of yosys output\n");
}
if (template_f.is_open()) {
std::string line;
while (std::getline(template_f, line))
*f << line << std::endl;
}
}
} SmvBackend;
PRIVATE_NAMESPACE_END

View File

@ -1,33 +0,0 @@
#!/bin/bash
set -ex
rm -rf test_cells.tmp
mkdir -p test_cells.tmp
cd test_cells.tmp
# don't test $mul to reduce runtime
# don't test $div and $mod to reduce runtime and avoid "div by zero" message
../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$macc /$mul /$div /$mod'
cat > template.txt << "EOT"
%module main
INVARSPEC ! bool(_trigger);
EOT
for fn in test_*.il; do
../../../yosys -p "
read_ilang $fn
rename gold gate
synth
read_ilang $fn
miter -equiv -flatten gold gate main
hierarchy -top main
write_smv -tpl template.txt ${fn#.il}.smv
"
nuXmv -dynamic ${fn#.il}.smv > ${fn#.il}.out
done
grep '^-- invariant .* is false' *.out || echo 'All OK.'

View File

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

View File

@ -1,266 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static string spice_id2str(IdString id)
{
static const char *escape_chars = "$\\[]()<>=";
string s = RTLIL::unescape_id(id);
for (auto &ch : s)
if (strchr(escape_chars, ch) != nullptr) ch = '_';
return s;
}
static string spice_id2str(IdString id, bool use_inames, idict<IdString, 1> &inums)
{
if (!use_inames && *id.c_str() == '$')
return stringf("%d", inums(id));
return spice_id2str(id);
}
static void print_spice_net(std::ostream &f, RTLIL::SigBit s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter, bool use_inames, idict<IdString, 1> &inums)
{
if (s.wire) {
if (s.wire->port_id)
use_inames = true;
if (s.wire->width > 1)
f << stringf(" %s.%d", spice_id2str(s.wire->name, use_inames, inums).c_str(), s.offset);
else
f << stringf(" %s", spice_id2str(s.wire->name, use_inames, inums).c_str());
} else {
if (s == RTLIL::State::S0)
f << stringf(" %s", neg.c_str());
else if (s == RTLIL::State::S1)
f << stringf(" %s", pos.c_str());
else
f << stringf(" %s%d", ncpf.c_str(), nc_counter++);
}
}
static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &ncpf, bool big_endian, bool use_inames)
{
SigMap sigmap(module);
idict<IdString, 1> inums;
int cell_counter = 0, conn_counter = 0, nc_counter = 0;
for (auto &cell_it : module->cells_)
{
RTLIL::Cell *cell = cell_it.second;
f << stringf("X%d", cell_counter++);
std::vector<RTLIL::SigSpec> port_sigs;
if (design->modules_.count(cell->type) == 0)
{
log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n",
log_id(cell->type), log_id(module), log_id(cell));
for (auto &conn : cell->connections()) {
RTLIL::SigSpec sig = sigmap(conn.second);
port_sigs.push_back(sig);
}
}
else
{
RTLIL::Module *mod = design->modules_.at(cell->type);
std::vector<RTLIL::Wire*> ports;
for (auto wire_it : mod->wires_) {
RTLIL::Wire *wire = wire_it.second;
if (wire->port_id == 0)
continue;
while (int(ports.size()) < wire->port_id)
ports.push_back(NULL);
ports.at(wire->port_id-1) = wire;
}
for (RTLIL::Wire *wire : ports) {
log_assert(wire != NULL);
RTLIL::SigSpec sig(RTLIL::State::Sz, wire->width);
if (cell->hasPort(wire->name)) {
sig = sigmap(cell->getPort(wire->name));
sig.extend_u0(wire->width, false);
}
port_sigs.push_back(sig);
}
}
for (auto &sig : port_sigs) {
for (int i = 0; i < sig.size(); i++) {
RTLIL::SigSpec s = sig.extract(big_endian ? sig.size() - 1 - i : i, 1);
print_spice_net(f, s, neg, pos, ncpf, nc_counter, use_inames, inums);
}
}
f << stringf(" %s\n", spice_id2str(cell->type).c_str());
}
for (auto &conn : module->connections())
for (int i = 0; i < conn.first.size(); i++) {
f << stringf("V%d", conn_counter++);
print_spice_net(f, conn.first.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
print_spice_net(f, conn.second.extract(i, 1), neg, pos, ncpf, nc_counter, use_inames, inums);
f << stringf(" DC 0\n");
}
}
struct SpiceBackend : public Backend {
SpiceBackend() : Backend("spice", "write design to SPICE netlist file") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_spice [options] [filename]\n");
log("\n");
log("Write the current design to an SPICE netlist file.\n");
log("\n");
log(" -big_endian\n");
log(" generate multi-bit ports in MSB first order\n");
log(" (default is LSB first)\n");
log("\n");
log(" -neg net_name\n");
log(" set the net name for constant 0 (default: Vss)\n");
log("\n");
log(" -pos net_name\n");
log(" set the net name for constant 1 (default: Vdd)\n");
log("\n");
log(" -nc_prefix\n");
log(" prefix for not-connected nets (default: _NC)\n");
log("\n");
log(" -inames\n");
log(" include names of internal ($-prefixed) nets in outputs\n");
log(" (default is to use net numbers instead)\n");
log("\n");
log(" -top top_module\n");
log(" set the specified module as design top module\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_module_name;
RTLIL::Module *top_module = NULL;
bool big_endian = false, use_inames = false;
std::string neg = "Vss", pos = "Vdd", ncpf = "_NC";
log_header(design, "Executing SPICE backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-big_endian") {
big_endian = true;
continue;
}
if (args[argidx] == "-inames") {
use_inames = true;
continue;
}
if (args[argidx] == "-neg" && argidx+1 < args.size()) {
neg = args[++argidx];
continue;
}
if (args[argidx] == "-pos" && argidx+1 < args.size()) {
pos = args[++argidx];
continue;
}
if (args[argidx] == "-nc_prefix" && argidx+1 < args.size()) {
ncpf = args[++argidx];
continue;
}
if (args[argidx] == "-top" && argidx+1 < args.size()) {
top_module_name = args[++argidx];
continue;
}
break;
}
extra_args(f, filename, args, argidx);
if (top_module_name.empty())
for (auto & mod_it:design->modules_)
if (mod_it.second->get_bool_attribute("\\top"))
top_module_name = mod_it.first.str();
*f << stringf("* SPICE netlist generated by %s\n", yosys_version_str);
*f << stringf("\n");
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
if (module->get_blackbox_attribute())
continue;
if (module->processes.size() != 0)
log_error("Found unmapped processes in module %s: unmapped processes are not supported in SPICE backend!\n", log_id(module));
if (module->memories.size() != 0)
log_error("Found unmapped memories in module %s: unmapped memories are not supported in SPICE backend!\n", log_id(module));
if (module->name == RTLIL::escape_id(top_module_name)) {
top_module = module;
continue;
}
std::vector<RTLIL::Wire*> ports;
for (auto wire_it : module->wires_) {
RTLIL::Wire *wire = wire_it.second;
if (wire->port_id == 0)
continue;
while (int(ports.size()) < wire->port_id)
ports.push_back(NULL);
ports.at(wire->port_id-1) = wire;
}
*f << stringf(".SUBCKT %s", spice_id2str(module->name).c_str());
for (RTLIL::Wire *wire : ports) {
log_assert(wire != NULL);
if (wire->width > 1) {
for (int i = 0; i < wire->width; i++)
*f << stringf(" %s.%d", spice_id2str(wire->name).c_str(), big_endian ? wire->width - 1 - i : i);
} else
*f << stringf(" %s", spice_id2str(wire->name).c_str());
}
*f << stringf("\n");
print_spice_module(*f, module, design, neg, pos, ncpf, big_endian, use_inames);
*f << stringf(".ENDS %s\n\n", spice_id2str(module->name).c_str());
}
if (!top_module_name.empty()) {
if (top_module == NULL)
log_error("Can't find top module `%s'!\n", top_module_name.c_str());
print_spice_module(*f, top_module, design, neg, pos, ncpf, big_endian, use_inames);
*f << stringf("\n");
}
*f << stringf("************************\n");
*f << stringf("* end of SPICE netlist *\n");
*f << stringf("************************\n");
*f << stringf("\n");
}
} SpiceBackend;
PRIVATE_NAMESPACE_END

View File

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

View File

@ -1,120 +0,0 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct TableBackend : public Backend {
TableBackend() : Backend("table", "write design as connectivity table") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_table [options] [filename]\n");
log("\n");
log("Write the current design as connectivity table. The output is a tab-separated\n");
log("ASCII table with the following columns:\n");
log("\n");
log(" module name\n");
log(" cell name\n");
log(" cell type\n");
log(" cell port\n");
log(" direction\n");
log(" signal\n");
log("\n");
log("module inputs and outputs are output using cell type and port '-' and with\n");
log("'pi' (primary input) or 'po' (primary output) or 'pio' as direction.\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing TABLE backend.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
// if (args[argidx] == "-top" && argidx+1 < args.size()) {
// top_module_name = args[++argidx];
// continue;
// }
break;
}
extra_args(f, filename, args, argidx);
design->sort();
for (auto module : design->modules())
{
if (module->get_blackbox_attribute())
continue;
SigMap sigmap(module);
for (auto wire : module->wires())
{
if (wire->port_id == 0)
continue;
*f << log_id(module) << "\t";
*f << log_id(wire) << "\t";
*f << "-" << "\t";
*f << "-" << "\t";
if (wire->port_input && wire->port_output)
*f << "pio" << "\t";
else if (wire->port_input)
*f << "pi" << "\t";
else if (wire->port_output)
*f << "po" << "\t";
else
log_abort();
*f << log_signal(sigmap(wire)) << "\n";
}
for (auto cell : module->cells())
for (auto conn : cell->connections())
{
*f << log_id(module) << "\t";
*f << log_id(cell) << "\t";
*f << log_id(cell->type) << "\t";
*f << log_id(conn.first) << "\t";
if (cell->input(conn.first) && cell->output(conn.first))
*f << "inout" << "\t";
else if (cell->input(conn.first))
*f << "in" << "\t";
else if (cell->output(conn.first))
*f << "out" << "\t";
else
*f << "unknown" << "\t";
*f << log_signal(sigmap(conn.second)) << "\n";
}
}
}
} TableBackend;
PRIVATE_NAMESPACE_END

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
demo.aig
demo.aim
demo.aiw
demo.smt2
demo.vcd

View File

@ -1,22 +0,0 @@
AIGER is a format for And-Inverter Graphs (AIGs).
See http://fmv.jku.at/aiger/ for details.
AIGER is used in the Hardware Model Checking Competition (HWMCC),
therefore all solvers competing in the competition have to support
the format.
The example in this directory is using super_prove as solver. Check
http://downloads.bvsrc.org/super_prove/ for the lates release. (See
https://bitbucket.org/sterin/super_prove_build for sources.)
The "demo.sh" script in this directory expects a "super_prove" executable
in the PATH. E.g. extract the release to /usr/local/libexec/super_prove
and then create a /usr/local/bin/super_prove file with the following
contents (and "chmod +x" that file):
#!/bin/bash
exec /usr/local/libexec/super_prove/bin/super_prove.sh "$@"
The "demo.sh" script also expects the "z3" SMT2 solver in the PATH for
converting the witness file generated by super_prove to VCD using
yosys-smtbmc. See https://github.com/Z3Prover/z3 for install notes.

View File

@ -1,14 +0,0 @@
#!/bin/bash
set -ex
yosys -p '
read_verilog -formal demo.v
prep -flatten -nordff -top demo
write_smt2 -wires demo.smt2
flatten demo; delete -output
memory_map; opt -full
techmap; opt -fast
abc -fast -g AND; opt_clean
write_aiger -map demo.aim demo.aig
'
super_prove demo.aig > demo.aiw
yosys-smtbmc --dump-vcd demo.vcd --aig demo demo.smt2

View File

@ -1,12 +0,0 @@
module demo(input clk, reset, ctrl);
localparam NBITS = 10;
reg [NBITS-1:0] counter;
initial counter[NBITS-2] = 0;
initial counter[0] = 1;
always @(posedge clk) begin
counter <= reset ? 1 : ctrl ? counter + 1 : counter - 1;
assume(counter != 0);
assume(counter != 1 << (NBITS-1));
assert(counter != (1 << NBITS)-1);
end
endmodule

View File

@ -1,7 +0,0 @@
demo.bit
demo_phy.area
full.v
*.log
*.h
*.tde
*.svf

View File

@ -1,12 +0,0 @@
LED Blink project for Anlogic Lichee Tang board.
Follow the install instructions for the Tang Dynasty IDE from given link below.
https://tang.sipeed.com/en/getting-started/installing-td-ide/linux/
set TD_HOME env variable to the full path to the TD <TD Install Directory> as follow.
export TD_HOME=<TD Install Directory>
then run "bash build.sh" in this directory.

View File

@ -1,4 +0,0 @@
#!/bin/bash
set -ex
yosys demo.ys
$TD_HOME/bin/td build.tcl

View File

@ -1,11 +0,0 @@
import_device eagle_s20.db -package BG256
read_verilog full.v -top demo
read_adc demo.adc
optimize_rtl
map_macro
map
pack
place
route
report_area -io_info -file demo_phy.area
bitgen -bit demo.bit -version 0X0000 -svf demo.svf -svf_comment_on -g ucode:00000000000000000000000000000000

View File

@ -1,2 +0,0 @@
set_pin_assignment {CLK_IN} { LOCATION = K14; } ##24MHZ
set_pin_assignment {R_LED} { LOCATION = R3; } ##R_LED

View File

@ -1,18 +0,0 @@
module demo (
input wire CLK_IN,
output wire R_LED
);
parameter time1 = 30'd12_000_000;
reg led_state;
reg [29:0] count;
always @(posedge CLK_IN)begin
if(count == time1)begin
count<= 30'd0;
led_state <= ~led_state;
end
else
count <= count + 1'b1;
end
assign R_LED = led_state;
endmodule

View File

@ -1,3 +0,0 @@
read_verilog demo.v
synth_anlogic -top demo
write_verilog full.v

View File

@ -1,19 +0,0 @@
A simple example design, based on the Digilent BASYS3 board
===========================================================
This example uses Yosys for synthesis and Xilinx Vivado
for place&route and bit-stream creation.
Running Yosys:
yosys run_yosys.ys
Running Vivado:
vivado -nolog -nojournal -mode batch -source run_vivado.tcl
Programming board:
vivado -nolog -nojournal -mode batch -source run_prog.tcl
All of the above:
bash run.sh

View File

@ -1,21 +0,0 @@
module example(CLK, LD);
input CLK;
output [15:0] LD;
wire clock;
reg [15:0] leds;
BUFG CLK_BUF (.I(CLK), .O(clock));
OBUF LD_BUF[15:0] (.I(leds), .O(LD));
parameter COUNTBITS = 26;
reg [COUNTBITS-1:0] counter;
always @(posedge CLK) begin
counter <= counter + 1;
if (counter[COUNTBITS-1])
leds <= 16'h8000 >> counter[COUNTBITS-2:COUNTBITS-5];
else
leds <= 16'h0001 << counter[COUNTBITS-2:COUNTBITS-5];
end
endmodule

View File

@ -1,24 +0,0 @@
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN W5 } [get_ports CLK]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U16 } [get_ports {LD[0]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN E19 } [get_ports {LD[1]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U19 } [get_ports {LD[2]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V19 } [get_ports {LD[3]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN W18 } [get_ports {LD[4]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U15 } [get_ports {LD[5]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U14 } [get_ports {LD[6]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V14 } [get_ports {LD[7]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V13 } [get_ports {LD[8]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN V3 } [get_ports {LD[9]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN W3 } [get_ports {LD[10]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN U3 } [get_ports {LD[11]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN P3 } [get_ports {LD[12]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN N3 } [get_ports {LD[13]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN P1 } [get_ports {LD[14]}]
set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN L1 } [get_ports {LD[15]}]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports CLK]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

View File

@ -1,4 +0,0 @@
#!/bin/bash
yosys run_yosys.ys
vivado -nolog -nojournal -mode batch -source run_vivado.tcl
vivado -nolog -nojournal -mode batch -source run_prog.tcl

View File

@ -1,5 +0,0 @@
open_hw
connect_hw_server
open_hw_target [lindex [get_hw_targets] 0]
set_property PROGRAM.FILE example.bit [lindex [get_hw_devices] 0]
program_hw_devices [lindex [get_hw_devices] 0]

View File

@ -1,9 +0,0 @@
read_xdc example.xdc
read_edif example.edif
link_design -part xc7a35tcpg236-1 -top example
opt_design
place_design
route_design
report_utilization
report_timing
write_bitstream -force example.bit

View File

@ -1,2 +0,0 @@
read_verilog example.v
synth_xilinx -edif example.edif -top example

View File

@ -1,4 +0,0 @@
counter_tb
counter_tb.vcd
synth.sp
synth.v

View File

@ -1,13 +0,0 @@
In this directory contains an example for generating a spice output using two
different spice modes, normal analog transient simulation and event-driven
digital simulation as supported by ngspice xspice sub-module.
Each test bench can be run separately by either running:
- testbench.sh, to start analog simulation or
- testbench_digital.sh for mixed-signal digital simulation.
The later case also includes pure verilog simulation using the iverilog
and gtkwave for comparison.

Some files were not shown because too many files have changed in this diff Show More