deleting yosys local folder to replace it with corresponding yosys sub-module
This commit is contained in:
parent
c5d9bac126
commit
9cee60ddbf
|
@ -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
|
|
@ -1,13 +0,0 @@
|
|||
.editorconfig
|
||||
.gitignore
|
||||
.gitmodules
|
||||
.github
|
||||
.git
|
||||
Dockerfile
|
||||
README.md
|
||||
manual
|
||||
CodingReadme
|
||||
CodeOfConduct
|
||||
.travis
|
||||
.travis.yml
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = tab
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
|
@ -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.*
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
##########################################################################
|
|
@ -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"
|
|
@ -1,6 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
# FIXME: Upload the build results somewhere...
|
|
@ -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
|
||||
)
|
||||
|
||||
##########################################################################
|
|
@ -1,9 +0,0 @@
|
|||
brew "bison"
|
||||
brew "flex"
|
||||
brew "gawk"
|
||||
brew "libffi"
|
||||
brew "git"
|
||||
brew "graphviz"
|
||||
brew "pkg-config"
|
||||
brew "python3"
|
||||
brew "tcl-tk"
|
729
yosys/CHANGELOG
729
yosys/CHANGELOG
|
@ -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
|
||||
|
|
@ -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"
|
||||
)
|
|
@ -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.
|
|
@ -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/
|
|
@ -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
|
||||
```
|
|
@ -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"]
|
903
yosys/Makefile
903
yosys/Makefile
|
@ -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
|
||||
|
538
yosys/README.md
538
yosys/README.md
|
@ -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`.
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/aiger/aiger.o
|
||||
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/blif/blif.o
|
||||
|
|
@ -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> ¶ms)
|
||||
{
|
||||
for (auto ¶m : 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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/btor/btor.o
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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."
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/edif/edif.o
|
||||
|
|
@ -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
|
|
@ -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")
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
test.fir
|
||||
test_out.v
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/firrtl/firrtl.o
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
"
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/ilang/ilang_backend.o
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/intersynth/intersynth.o
|
||||
|
|
@ -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 ¶m : 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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/json/json.o
|
||||
|
|
@ -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> ¶meters, bool for_module=false)
|
||||
{
|
||||
bool first = true;
|
||||
for (auto ¶m : 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
|
|
@ -1,2 +0,0 @@
|
|||
yosys.pb.cc
|
||||
yosys.pb.h
|
|
@ -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
|
|
@ -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> ¶meters)
|
||||
{
|
||||
for (auto ¶m : 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;
|
|
@ -1,2 +0,0 @@
|
|||
test00_tb
|
||||
test00_uut.c
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/simplec/simplec.o
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -1 +0,0 @@
|
|||
test_cells
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/smv/smv.o
|
||||
|
|
@ -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
|
|
@ -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.'
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/spice/spice.o
|
||||
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/table/table.o
|
||||
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
OBJS += backends/verilog/verilog_backend.o
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +0,0 @@
|
|||
demo.aig
|
||||
demo.aim
|
||||
demo.aiw
|
||||
demo.smt2
|
||||
demo.vcd
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -1,7 +0,0 @@
|
|||
demo.bit
|
||||
demo_phy.area
|
||||
full.v
|
||||
*.log
|
||||
*.h
|
||||
*.tde
|
||||
*.svf
|
|
@ -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.
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
yosys demo.ys
|
||||
$TD_HOME/bin/td build.tcl
|
|
@ -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
|
|
@ -1,2 +0,0 @@
|
|||
set_pin_assignment {CLK_IN} { LOCATION = K14; } ##24MHZ
|
||||
set_pin_assignment {R_LED} { LOCATION = R3; } ##R_LED
|
|
@ -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
|
|
@ -1,3 +0,0 @@
|
|||
read_verilog demo.v
|
||||
synth_anlogic -top demo
|
||||
write_verilog full.v
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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]
|
||||
|
|
@ -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
|
|
@ -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]
|
|
@ -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
|
|
@ -1,2 +0,0 @@
|
|||
read_verilog example.v
|
||||
synth_xilinx -edif example.edif -top example
|
|
@ -1,4 +0,0 @@
|
|||
counter_tb
|
||||
counter_tb.vcd
|
||||
synth.sp
|
||||
synth.v
|
|
@ -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.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// test comment
|
||||
/* test comment */
|
||||
library(demo) {
|
||||
cell(BUF) {
|
||||
area: 6;
|
||||
pin(A) { direction: input; }
|
||||
pin(Y) { direction: output;
|
||||
function: "A"; }
|
||||
}
|
||||
cell(NOT) {
|
||||
area: 3;
|
||||
pin(A) { direction: input; }
|
||||
pin(Y) { direction: output;
|
||||
function: "A'"; }
|
||||
}
|
||||
cell(NAND) {
|
||||
area: 4;
|
||||
pin(A) { direction: input; }
|
||||
pin(B) { direction: input; }
|
||||
pin(Y) { direction: output;
|
||||
function: "(A*B)'"; }
|
||||
}
|
||||
cell(NOR) {
|
||||
area: 4;
|
||||
pin(A) { direction: input; }
|
||||
pin(B) { direction: input; }
|
||||
pin(Y) { direction: output;
|
||||
function: "(A+B)'"; }
|
||||
}
|
||||
cell(DFF) {
|
||||
area: 18;
|
||||
ff(IQ, IQN) { clocked_on: C;
|
||||
next_state: D; }
|
||||
pin(C) { direction: input;
|
||||
clock: true; }
|
||||
pin(D) { direction: input; }
|
||||
pin(Q) { direction: output;
|
||||
function: "IQ"; }
|
||||
}
|
||||
cell(DFFSR) {
|
||||
area: 18;
|
||||
ff("IQ", "IQN") { clocked_on: C;
|
||||
next_state: D;
|
||||
preset: S;
|
||||
clear: R; }
|
||||
pin(C) { direction: input;
|
||||
clock: true; }
|
||||
pin(D) { direction: input; }
|
||||
pin(Q) { direction: output;
|
||||
function: "IQ"; }
|
||||
pin(S) { direction: input; }
|
||||
pin(R) { direction: input; }
|
||||
; // empty statement
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
.SUBCKT BUF A Y
|
||||
X1 A B NOT
|
||||
X2 B Y NOT
|
||||
.ENDS NOT
|
||||
|
||||
.SUBCKT NOT A Y
|
||||
M1 Y A Vdd Vdd cmosp L=1u W=10u
|
||||
M2 Y A Vss Vss cmosn L=1u W=10u
|
||||
.ENDS NOT
|
||||
|
||||
.SUBCKT NAND A B Y
|
||||
M1 Y A Vdd Vdd cmosp L=1u W=10u
|
||||
M2 Y B Vdd Vdd cmosp L=1u W=10u
|
||||
M3 Y A M34 Vss cmosn L=1u W=10u
|
||||
M4 M34 B Vss Vss cmosn L=1u W=10u
|
||||
.ENDS NAND
|
||||
|
||||
.SUBCKT NOR A B Y
|
||||
M1 Y A M12 Vdd cmosp L=1u W=10u
|
||||
M2 M12 B Vdd Vdd cmosp L=1u W=10u
|
||||
M3 Y A Vss Vss cmosn L=1u W=10u
|
||||
M4 Y B Vss Vss cmosn L=1u W=10u
|
||||
.ENDS NOR
|
||||
|
||||
.SUBCKT DLATCH E D Q
|
||||
X1 D E S NAND
|
||||
X2 nD E R NAND
|
||||
X3 S nQ Q NAND
|
||||
X4 Q R nQ NAND
|
||||
X5 D nD NOT
|
||||
.ENDS DLATCH
|
||||
|
||||
.SUBCKT DFF C D Q
|
||||
X1 nC D t DLATCH
|
||||
X2 C t Q DLATCH
|
||||
X3 C nC NOT
|
||||
.ENDS DFF
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
|
||||
module BUF(A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = A;
|
||||
endmodule
|
||||
|
||||
module NOT(A, Y);
|
||||
input A;
|
||||
output Y;
|
||||
assign Y = ~A;
|
||||
endmodule
|
||||
|
||||
module NAND(A, B, Y);
|
||||
input A, B;
|
||||
output Y;
|
||||
assign Y = ~(A & B);
|
||||
endmodule
|
||||
|
||||
module NOR(A, B, Y);
|
||||
input A, B;
|
||||
output Y;
|
||||
assign Y = ~(A | B);
|
||||
endmodule
|
||||
|
||||
module DFF(C, D, Q);
|
||||
input C, D;
|
||||
output reg Q;
|
||||
always @(posedge C)
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
||||
module DFFSR(C, D, Q, S, R);
|
||||
input C, D, S, R;
|
||||
output reg Q;
|
||||
always @(posedge C, posedge S, posedge R)
|
||||
if (S)
|
||||
Q <= 1'b1;
|
||||
else if (R)
|
||||
Q <= 1'b0;
|
||||
else
|
||||
Q <= D;
|
||||
endmodule
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
.SUBCKT BUF A Y
|
||||
.model buffer1 d_buffer
|
||||
Abuf A Y buffer1
|
||||
.ENDS NOT
|
||||
|
||||
.SUBCKT NOT A Y
|
||||
.model not1 d_inverter
|
||||
Anot A Y not1
|
||||
.ENDS NOT
|
||||
|
||||
.SUBCKT NAND A B Y
|
||||
.model nand1 d_nand
|
||||
Anand [A B] Y nand1
|
||||
.ENDS NAND
|
||||
|
||||
.SUBCKT NOR A B Y
|
||||
.model nor1 d_nor
|
||||
Anand [A B] Y nor1
|
||||
.ENDS NOR
|
||||
|
||||
.SUBCKT DLATCH E D Q
|
||||
.model latch1 d_latch
|
||||
Alatch D E null null Q nQ latch1
|
||||
.ENDS DLATCH
|
||||
|
||||
.SUBCKT DFF C D Q
|
||||
.model dff1 d_dff
|
||||
Adff D C null null Q nQ dff1
|
||||
.ENDS DFF
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
module counter (clk, rst, en, count);
|
||||
|
||||
input clk, rst, en;
|
||||
output reg [2:0] count;
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst)
|
||||
count <= 3'd0;
|
||||
else if (en)
|
||||
count <= count + 3'd1;
|
||||
|
||||
endmodule
|
|
@ -1,16 +0,0 @@
|
|||
read_verilog counter.v
|
||||
read_verilog -lib cmos_cells.v
|
||||
|
||||
synth
|
||||
dfflibmap -liberty cmos_cells.lib
|
||||
abc -liberty cmos_cells.lib
|
||||
opt_clean
|
||||
|
||||
stat -liberty cmos_cells.lib
|
||||
|
||||
# http://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/latest/cadence/lib/tsmc025/signalstorm/osu025_stdcells.lib
|
||||
# dfflibmap -liberty osu025_stdcells.lib
|
||||
# abc -liberty osu025_stdcells.lib;;
|
||||
|
||||
write_verilog synth.v
|
||||
write_spice synth.sp
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
read_verilog counter.v
|
||||
read_verilog -lib cmos_cells.v
|
||||
|
||||
proc;; memory;; techmap;;
|
||||
|
||||
dfflibmap -liberty cmos_cells.lib
|
||||
abc -liberty cmos_cells.lib;;
|
||||
|
||||
# http://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/latest/cadence/lib/tsmc025/signalstorm/osu025_stdcells.lib
|
||||
# dfflibmap -liberty osu025_stdcells.lib
|
||||
# abc -liberty osu025_stdcells.lib;;
|
||||
|
||||
write_verilog synth.v
|
||||
write_spice -neg 0s -pos 1s synth.sp
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[dumpfile] "counter_tb.vcd"
|
||||
counter_tb.clk
|
||||
counter_tb.count[2:0]
|
||||
counter_tb.en
|
||||
counter_tb.reset
|
|
@ -1,33 +0,0 @@
|
|||
module counter_tb;
|
||||
|
||||
/* Make a reset pulse and specify dump file */
|
||||
reg reset = 0;
|
||||
initial begin
|
||||
$dumpfile("counter_tb.vcd");
|
||||
$dumpvars(0,counter_tb);
|
||||
|
||||
# 0 reset = 1;
|
||||
# 4 reset = 0;
|
||||
# 36 reset = 1;
|
||||
# 4 reset = 0;
|
||||
# 6 $finish;
|
||||
end
|
||||
|
||||
/* Make enable with period of 8 and 6,7 low */
|
||||
reg en = 1;
|
||||
always begin
|
||||
en = 1;
|
||||
#6;
|
||||
en = 0;
|
||||
#2;
|
||||
end
|
||||
|
||||
/* Make a regular pulsing clock. */
|
||||
reg clk = 0;
|
||||
always #1 clk = !clk;
|
||||
|
||||
/* UUT */
|
||||
wire [2:0] count;
|
||||
counter c1 (clk, reset, en, count);
|
||||
|
||||
endmodule
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
../../yosys counter.ys
|
||||
ngspice testbench.sp
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
* supply voltages
|
||||
.global Vss Vdd
|
||||
Vss Vss 0 DC 0
|
||||
Vdd Vdd 0 DC 3
|
||||
|
||||
* simple transistor model
|
||||
.MODEL cmosn NMOS LEVEL=1 VT0=0.7 KP=110U GAMMA=0.4 LAMBDA=0.04 PHI=0.7
|
||||
.MODEL cmosp PMOS LEVEL=1 VT0=-0.7 KP=50U GAMMA=0.57 LAMBDA=0.05 PHI=0.8
|
||||
|
||||
* load design and library
|
||||
.include cmos_cells.sp
|
||||
.include synth.sp
|
||||
|
||||
* input signals
|
||||
Vclk clk 0 PULSE(0 3 1 0.1 0.1 0.8 2)
|
||||
Vrst rst 0 PULSE(0 3 0.5 0.1 0.1 2.9 40)
|
||||
Ven en 0 PULSE(0 3 0.5 0.1 0.1 5.9 8)
|
||||
|
||||
Xuut clk rst en out0 out1 out2 COUNTER
|
||||
|
||||
.tran 0.01 50
|
||||
|
||||
.control
|
||||
run
|
||||
plot v(clk) v(rst)+5 v(en)+10 v(out0)+20 v(out1)+25 v(out2)+30
|
||||
.endc
|
||||
|
||||
.end
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
# iverlog simulation
|
||||
echo "Doing Verilog simulation with iverilog"
|
||||
iverilog -o counter_tb counter.v counter_tb.v
|
||||
./counter_tb; gtkwave counter_tb.gtkw &
|
||||
|
||||
# yosys synthesis
|
||||
../../yosys counter_digital.ys
|
||||
|
||||
# requires ngspice with xspice support enabled:
|
||||
ngspice testbench_digital.sp
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
* load design and library
|
||||
.include cmos_cells_digital.sp
|
||||
.include synth.sp
|
||||
|
||||
* input signals
|
||||
Vclk clk 0 PULSE(0 3 1 0.1 0.1 0.8 2)
|
||||
Vrst rst 0 PULSE(0 3 0.5 0.1 0.1 2.9 40)
|
||||
Ven en 0 PULSE(0 3 0.5 0.1 0.1 5.9 8)
|
||||
|
||||
Xuut dclk drst den dout0 dout1 dout2 counter
|
||||
* Bridge to digital
|
||||
.model adc_buff adc_bridge(in_low = 0.8 in_high=2)
|
||||
.model dac_buff dac_bridge(out_high = 3.5)
|
||||
Aad [clk rst en] [dclk drst den] adc_buff
|
||||
Ada [dout0 dout1 dout2] [out0 out1 out2] dac_buff
|
||||
|
||||
|
||||
.tran 0.01 50
|
||||
|
||||
.control
|
||||
run
|
||||
plot v(clk) v(rst)+5 v(en)+10 v(out0)+20 v(out1)+25 v(out2)+30
|
||||
.endc
|
||||
|
||||
.end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue