Upgrade to yosys-0.9

This commit is contained in:
tangxifan 2019-11-27 14:40:39 -07:00
parent 8cc72536d1
commit 4d62dc1c3e
154 changed files with 4474 additions and 1559 deletions

13
yosys/.clang-format Normal file
View File

@ -0,0 +1,13 @@
# 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

13
yosys/.dockerignore Normal file
View File

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

7
yosys/.editorconfig Normal file
View File

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

24
yosys/.github/issue_template.md vendored Normal file
View File

@ -0,0 +1,24 @@
## 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.*

13
yosys/.gitignore vendored
View File

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

View File

@ -1,14 +1,26 @@
sudo: false
script: make && make test
language: cpp
addons:
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:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
- gperf
- build-essential
- clang
- bison
- flex
- libreadline-dev
@ -16,19 +28,113 @@ addons:
- tcl-dev
- libffi-dev
- git
- mercurial
- graphviz
- xdot
- pkg-config
- python
- g++-4.8
- 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:
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- git clone git://github.com/steveicarus/iverilog.git
- (cd iverilog && autoconf && ./configure --prefix=$HOME/iverilog && make && make install)
- export PATH=$PATH:$HOME/iverilog/bin
compiler:
# - clang
- gcc
os:
- linux
- ./.travis/setup.sh
script:
- ./.travis/build-and-test.sh
after_success:
- ./.travis/deploy-after-success.sh

51
yosys/.travis/build-and-test.sh Executable file
View File

@ -0,0 +1,51 @@
#! /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
##########################################################################

15
yosys/.travis/common.sh Normal file
View File

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

View File

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

63
yosys/.travis/setup.sh Executable file
View File

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

View File

@ -6,3 +6,4 @@ brew "git"
brew "graphviz"
brew "pkg-config"
brew "python3"
brew "tcl-tk"

View File

@ -3,21 +3,124 @@ List of major changes and improvements between releases
=======================================================
Yosys 0.8 .. Yosys 0.8-dev
Yosys 0.8 .. Yosys 0.9
--------------------------
* Various
- Added $changed support to read_verilog
- Many bugfixes and small improvements
- Added support for SystemVerilog interfaces and modports
- Added "write_edif -attrprop"
- Added "ice40_unlut" pass
- Added "opt_lut" pass
- Added "synth_ice40 -relut"
- Added "synth_ice40 -noabc"
- Added "gate2lut.v" techmap rule
- Added "rename -src"
- Added "equiv_opt" pass
- "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx"
- 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
----------------------
@ -30,7 +133,7 @@ Yosys 0.7 .. Yosys 0.8
- Added "write_verilog -decimal"
- Added "scc -set_attr"
- Added "verilog_defines" command
- Remeber defines from one read_verilog to next
- Remember defines from one read_verilog to next
- Added support for hierarchical defparam
- Added FIRRTL back-end
- Improved ABC default scripts
@ -39,7 +142,7 @@ Yosys 0.7 .. Yosys 0.8
- Added Verilog $rtoi and $itor support
- Added "check -initdrv"
- Added "read_blif -wideports"
- Added support for systemVerilog "++" and "--" operators
- 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

View File

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

View File

@ -1,4 +1,4 @@
Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at>
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

33
yosys/Dockerfile Normal file
View File

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

View File

@ -1,7 +1,8 @@
# CONFIG := clang
CONFIG := gcc
CONFIG := clang
# CONFIG := gcc
# CONFIG := gcc-4.8
# CONFIG := afl-gcc
# CONFIG := emcc
# CONFIG := mxe
# CONFIG := msys2
@ -21,12 +22,6 @@ ENABLE_PROTOBUF := 0
# python wrappers
ENABLE_PYOSYS := 0
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 := `$(PYTHON_EXECUTABLE)-config --prefix`
PYTHON_DESTDIR := $(PYTHON_PREFIX)/lib/python$(PYTHON_VERSION)/site-packages
# other configuration flags
ENABLE_GCOV := 0
@ -51,6 +46,10 @@ 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
@ -90,6 +89,11 @@ 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)
@ -110,7 +114,7 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
YOSYS_VER := 0.8+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 4d4665b.. 2> /dev/null | wc -l; })
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
@ -139,6 +143,21 @@ $(info $(subst $$--$$,$(newline),$(shell sed 's,^,[Makefile.conf] ,; 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++
@ -186,6 +205,12 @@ 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
@ -237,7 +262,8 @@ 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"
ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
# 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)
@ -273,30 +299,51 @@ 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 += `$(PYTHON_EXECUTABLE)-config --libs` $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += `$(PYTHON_EXECUTABLE)-config --includes` -D WITH_PYTHON
LDLIBS += $(shell $(PYTHON_EXECUTABLE)-config --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += $(shell $(PYTHON_EXECUTABLE)-config --includes) -DWITH_PYTHON
else
LDLIBS += `$(PYTHON_EXECUTABLE)-config --libs` $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
CXXFLAGS += `$(PYTHON_EXECUTABLE)-config --includes` -D WITH_PYTHON
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
@ -350,7 +397,7 @@ endif
ifeq ($(CONFIG),mxe)
CXXFLAGS += -DYOSYS_ENABLE_TCL
LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz
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)
@ -541,7 +588,11 @@ 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 $@)
@ -551,9 +602,11 @@ libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
$(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 $@)
@ -616,6 +669,12 @@ 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)
@ -624,13 +683,14 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+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 $(SEEDOPT)
+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
+cd tests/aiger && bash run-test.sh $(ABCOPT)
+cd tests/arch && bash run-test.sh
@echo ""
@echo " Passed \"make test\"."
@echo ""
@ -651,7 +711,7 @@ vloghtb: $(TARGETS) $(EXTRA_TARGETS)
ystests: $(TARGETS) $(EXTRA_TARGETS)
rm -rf tests/ystests
git clone https://github.com/YosysHQ/yosys-tests.git 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\"."
@ -788,6 +848,9 @@ config-gcc-static: clean
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
@ -801,9 +864,11 @@ config-mxe: clean
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
@ -834,5 +899,5 @@ echo-git-rev:
-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-gprof config-sudo
.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-afl-gcc config-gprof config-sudo

View File

@ -1,451 +0,0 @@
/-----------------------------------------------------------------------------\
| |
| yosys -- Yosys Open SYnthesis Suite |
| |
| Copyright (C) 2012 - 2016 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
========
More information and documentation can be found on the Yosys web site:
http://www.clifford.at/yosys/
Getting Started
===============
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 mercurial \
graphviz xdot pkg-config python3
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
$ make test
$ sudo make install
Note that this also downloads, builds and installs ABC (using yosys-abc
as executable name).
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", "trior", "wand" and "wor" net types
- The "config" keyword and library map files
- The "disable", "primitive" and "specify" statements
- Latched logic (is synthesized as logic with feedback loops)
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 onehot 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.
- 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.
- 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
tipple 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 and $display are supported in initial blocks
in an unconditional context (only if/case statements on parameters
and constant values). The intended use for this is synthesis-time DRC.
Non-standard or SystemVerilog features for formal verification
==============================================================
- Support for "assert", "assume", and "restrict" 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 task $anyconst evaluates to any constant value.
- The system task $anyseq evaluates to any value, possibly a different
value in each cycle.
- 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).
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 a $assert cell.
- The "assume" and "restrict" 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.
- 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.
Building the documentation
==========================
Note that there is no need to build the manual if you just want to read it.
Simply download the PDF from http://www.clifford.at/yosys/documentation.html
instead.
On Ubuntu, texlive needs these packages to be able to build the manual:
sudo apt-get install texlive-binaries
sudo apt-get install texlive-science # install algorithm2e.sty
sudo apt-get install texlive-bibtex-extra # gets multibib.sty
sudo apt-get install texlive-fonts-extra # gets skull.sty and dsfont.sty
sudo apt-get install texlive-publishers # IEEEtran.cls
Also the non-free font luximono should be installed, there is unfortunately
no Ubuntu package for this so it should be installed separately using
`getnonfreefonts`:
wget https://tug.org/fonts/getnonfreefonts/install-getnonfreefonts
sudo texlua install-getnonfreefonts # will install to /usr/local by default, can be changed by editing BINDIR at MANDIR at the top of the script
getnonfreefonts luximono # installs to /home/user/texmf
Then execute, from the root of the repository:
make manual
Notes:
- To run `make manual` you need to have installed yosys with `make install`,
otherwise it will fail on finding `kernel/yosys.h` while building
`PRESENTATION_Prog`.

View File

@ -1,7 +1,7 @@
```
yosys -- Yosys Open SYnthesis Suite
Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at>
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
@ -69,11 +69,14 @@ prerequisites for building yosys:
graphviz xdot pkg-config python3 libboost-system-dev \
libboost-python-dev libboost-filesystem-dev
Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
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
git graphviz pkgconfig python36 boost tcl
On FreeBSD use the following command to install all prerequisites:
@ -257,7 +260,7 @@ for them:
- Non-synthesizable language features as defined in
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
- The ``tri``, ``triand``, ``trior``, ``wand`` and ``wor`` net types
- The ``tri``, ``triand`` and ``trior`` net types
- The ``config`` and ``disable`` keywords and library map files
@ -350,6 +353,14 @@ Verilog Attributes and non-standard features
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
@ -413,7 +424,7 @@ Verilog Attributes and non-standard features
$ 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
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

View File

@ -1,174 +0,0 @@
# global parameters
set check # checks intermediate networks
#set checkfio # prints warnings when fanins/fanouts are duplicated
set checkread # checks new networks after reading from file
set backup # saves backup networks retrived by "undo" and "recall"
set savesteps 1 # sets the maximum number of backup networks to save
set progressbar # display the progress bar
# program names for internal calls
set dotwin dot.exe
set dotunix dot
set gsviewwin gsview32.exe
set gsviewunix gv
set siswin sis.exe
set sisunix sis
set mvsiswin mvsis.exe
set mvsisunix mvsis
set capowin MetaPl-Capo10.1-Win32.exe
set capounix MetaPl-Capo10.1
set gnuplotwin wgnuplot.exe
set gnuplotunix gnuplot
# standard aliases
alias b balance
alias cl cleanup
alias clp collapse
alias esd ext_seq_dcs
alias f fraig
alias fs fraig_sweep
alias fsto fraig_store
alias fres fraig_restore
alias ft fraig_trust
alias lp lutpack
alias pd print_dsd
alias pex print_exdc -d
alias pf print_factor
alias pfan print_fanio
alias pl print_level
alias pio print_io
alias pk print_kmap
alias ps print_stats
alias psu print_supp
alias psy print_symm
alias pun print_unate
alias q quit
alias r read
alias r3 retime -M 3
alias r3f retime -M 3 -f
alias r3b retime -M 3 -b
alias ren renode
alias rh read_hie
alias rl read_blif
alias rb read_bench
alias ret retime
alias rp read_pla
alias rt read_truth
alias rv read_verilog
alias rvl read_verlib
alias rsup read_super mcnc5_old.super
alias rlib read_library
alias rlibc read_library cadence.genlib
alias rw rewrite
alias rwz rewrite -z
alias rf refactor
alias rfz refactor -z
alias re restructure
alias rez restructure -z
alias rs resub
alias rsz resub -z
alias sa set autoexec ps
alias scl scleanup
alias sif if -s
alias so source -x
alias st strash
alias sw sweep
alias ssw ssweep
alias tr0 trace_start
alias tr1 trace_check
alias trt "r c.blif; st; tr0; b; tr1"
alias u undo
alias w write
alias wa write_aiger
alias wb write_bench
alias wc write_cnf
alias wh write_hie
alias wl write_blif
alias wp write_pla
alias wv write_verilog
# standard scripts
alias share "b; ren -s; fx; b"
alias sharedsd "b; ren -b; dsd -g; sw; fx; b"
alias resyn "b; rw; rwz; b; rwz; b"
alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b"
alias resyn2a "b; rw; b; rw; rwz; b; rwz; b"
alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b"
alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l"
alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l"
alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore"
alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore"
alias rwsat "st; rw -l; b -l; rw -l; rf -l"
alias rwsat2 "st; rw -l; b -l; rw -l; rf -l; fraig; rw -l; b -l; rw -l; rf -l"
alias shake "st; ps; sat -C 5000; rw -l; ps; sat -C 5000; b -l; rf -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000; rwz -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000"
# resubstitution scripts for the IWLS paper
alias src_rw "st; rw -l; rwz -l; rwz -l"
alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l"
alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l"
alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b"
alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l"
# experimental implementation of don't-cares
alias resyn2rsdc "b; rs -K 6 -F 2; rw; rs -K 6 -N 2 -F 2; rf; rs -K 8 -F 2; b; rs -K 8 -N 2 -F 2; rw; rs -K 10 -F 2; rwz; rs -K 10 -N 2 -F 2; b; rs -K 12 -F 2; rfz; rs -K 12 -N 2 -F 2; rwz; b"
alias compress2rsdc "b -l; rs -K 6 -F 2 -l; rw -l; rs -K 6 -N 2 -F 2 -l; rf -l; rs -K 8 -F 2 -l; b -l; rs -K 8 -N 2 -F 2 -l; rw -l; rs -K 10 -F 2 -l; rwz -l; rs -K 10 -N 2 -F 2 -l; b -l; rs -K 12 -F 2 -l; rfz -l; rs -K 12 -N 2 -F 2 -l; rwz -l; b -l"
# minimizing for FF literals
alias fflitmin "compress2rs; ren; sop; ps -f"
# temporaries
#alias t "rvl th/lib.v; rvv th/t2.v"
#alias t "so c/pure_sat/test.c"
#alias t "r c/14/csat_998.bench; st; ps"
#alias t0 "r res.blif; aig; mfs"
#alias t "r res2.blif; aig; mfs"
#alias tt "r a/quip_opt/nut_001_opt.blif"
#alias ttb "wh a/quip_opt/nut_001_opt.blif 1.blif"
#alias ttv "wh a/quip_opt/nut_001_opt.blif 1.v"
alias reach "st; ps; compress2; ps; qrel; ps; compress2; ps; qreach -v; ps"
alias qs1 "qvar -I 96 -u; ps; qbf -P 96"
alias qs2 "qvar -I 96 -u; qvar -I 97 -u; ps; qbf -P 96"
alias qs3 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; ps; qbf -P 96"
alias qs4 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; ps; qbf -P 96"
alias qs5 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; ps; qbf -P 96"
alias qs6 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; ps; qbf -P 96"
alias qs7 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; ps; qbf -P 96"
alias qs8 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; ps; qbf -P 96"
alias qs9 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; qvar -I 104 -u; ps; qbf -P 96"
alias qsA "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; qvar -I 104 -u; qvar -I 105 -u; ps; qbf -P 96"
alias chnew "st; haig_start; resyn2; haig_use"
alias chnewrs "st; haig_start; resyn2rs; haig_use"
alias stdsd "r test/6in.blif; st; ps; u; bdd; dsd -g; st; ps"
alias trec "rec_start; r c.blif; st; rec_add; rec_use"
alias trec4 "rec_start -K 4; r i10.blif; st; rec_add; rec_use"
alias trec5 "rec_start -K 5; r i10.blif; st; rec_add; rec_use"
alias trec6 "rec_start -K 6; r i10.blif; st; rec_add; rec_use"
alias trec7 "rec_start -K 7; r i10.blif; st; rec_add; rec_use"
alias trec8 "rec_start -K 8; r i10.blif; st; rec_add; rec_use"
alias trec10 "rec_start -K 10; r i10.blif; st; rec_add; rec_use"
alias trec12 "rec_start -K 12; r i10.blif; st; rec_add; rec_use"
#alias tsh "r i10_if.blif; st; ps; u; sw; st; ps; cec"
alias tst4 "r i10_if4.blif; st; ps; r x/rec4_.blif; st; rec_start; r i10_if4.blif; st -r; ps; cec"
alias tst4n "r i10_if4.blif; st; ps; r 5npn/all_functions.aig; st; rec_start; r i10_if4.blif; st -r; ps; cec"
alias tst6 "r i10_if6.blif; st; ps; r x/rec6_16_.blif; st; rec_start; r i10_if6.blif; st -r; ps; cec"
#alias t "r c.blif; st; wc c.cnf"
#alias t "r test/dsdmap6.blif; lutpack -vw; cec"
#alias t "r i10_if4.blif; lp"
#alias t1 "r pj1_if4.blif; lp"
#alias t2 "r pj1_if6.blif; lp"
#alias t "r pj/pj1.blif; st; dfraig -v"
#alias t "r c/16/csat_2.bench; st; dfraig -C 100 -v -r"
#alias t "r c/16/csat_147.bench; st; dfraig -C 10 -v -r"
#alias t "r i10.blif; st; ps; csweep; ps; cec"
#alias t "r c/5/csat_777.bench; st; csweep -v"
#alias t "r i10.blif; st; drw -v"
alias t "r c.blif; st; drf"

View File

@ -89,7 +89,8 @@ struct AigerWriter
aig_map[bit] = mkgate(a0, a1);
} else
if (alias_map.count(bit)) {
aig_map[bit] = bit2aig(alias_map.at(bit));
int a = bit2aig(alias_map.at(bit));
aig_map[bit] = a;
}
if (bit == State::Sx || bit == State::Sz)
@ -776,6 +777,7 @@ struct AigerBackend : public Backend {
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())

View File

@ -409,12 +409,26 @@ struct BlifDumper
f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type));
for (auto &conn : cell->connections())
for (int i = 0; i < conn.second.size(); i++) {
if (conn.second.size() == 1)
f << stringf(" %s", cstr(conn.first));
else
f << stringf(" %s[%d]", cstr(conn.first), i);
f << stringf("=%s", cstr(conn.second.extract(i, 1)));
{
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");

View File

@ -17,6 +17,11 @@
*
*/
// [[CITE]] Btor2 , BtorMC and Boolector 3.0
// Aina Niemetz, Mathias Preiner, Clifford Wolf, Armin Biere
// Computer Aided Verification - 30th International Conference, CAV 2018
// https://cs.stanford.edu/people/niemetz/publication/2018/niemetzpreinerwolfbiere-cav18/
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
@ -129,7 +134,13 @@ struct BtorWorker
void export_cell(Cell *cell)
{
log_assert(cell_recursion_guard.count(cell) == 0);
if (cell_recursion_guard.count(cell)) {
string cell_list;
for (auto c : cell_recursion_guard)
cell_list += stringf("\n %s", log_id(c));
log_error("Found topological loop while processing cell %s. Active cells:%s\n", log_id(cell), cell_list.c_str());
}
cell_recursion_guard.insert(cell);
btorf_push(log_id(cell));
@ -869,11 +880,30 @@ struct BtorWorker
else
{
if (bit_cell.count(bit) == 0)
log_error("No driver for signal bit %s.\n", log_signal(bit));
{
SigSpec s = bit;
while (i+GetSize(s) < GetSize(sig) && sig[i+GetSize(s)].wire != nullptr &&
bit_cell.count(sig[i+GetSize(s)]) == 0)
s.append(sig[i+GetSize(s)]);
log_warning("No driver for signal %s.\n", log_signal(s));
int sid = get_bv_sid(GetSize(s));
int nid = next_nid++;
btorf("%d input %d %s\n", nid, sid);
nid_width[nid] = GetSize(s);
i += GetSize(s)-1;
continue;
}
else
{
export_cell(bit_cell.at(bit));
log_assert(bit_nid.count(bit));
}
}
}
nidbits.push_back(bit_nid.at(bit));
}

View File

@ -204,6 +204,11 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const
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)
@ -483,6 +488,7 @@ struct DumpPass : public Pass {
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()) {

View File

@ -126,6 +126,10 @@ struct JsonWriter
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;
@ -189,6 +193,10 @@ struct JsonWriter
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");
@ -525,6 +533,7 @@ struct JsonPass : public Pass {
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()) {

View File

@ -336,6 +336,7 @@ struct ProtobufPass : public Pass {
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()) {

View File

@ -1023,6 +1023,8 @@ class MkVcd:
assert t >= self.t
if t != self.t:
if self.t == -1:
print("$version Generated by Yosys-SMTBMC $end", file=self.f)
print("$timescale 1ns $end", file=self.f)
print("$var integer 32 t smt_step $end", file=self.f)
print("$var event 1 ! smt_clock $end", file=self.f)
@ -1041,7 +1043,10 @@ class MkVcd:
scope = scope[:-1]
while uipath[:-1] != scope:
print("$scope module %s $end" % uipath[len(scope)], file=self.f)
scopename = uipath[len(scope)]
if scopename.startswith("$"):
scopename = "\\" + scopename
print("$scope module %s $end" % scopename, file=self.f)
scope.append(uipath[len(scope)])
if path in self.clocks and self.clocks[path][1] == "event":

View File

@ -364,20 +364,22 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
}
}
void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n', bool modattr = false)
void dump_attributes(std::ostream &f, std::string indent, dict<RTLIL::IdString, RTLIL::Const> &attributes, char term = '\n', bool modattr = false, bool as_comment = false)
{
if (noattr)
return;
if (attr2comment)
as_comment = true;
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
f << stringf("%s" "%s %s", indent.c_str(), attr2comment ? "/*" : "(*", id(it->first).c_str());
f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str());
f << stringf(" = ");
if (modattr && (it->second == Const(0, 1) || it->second == Const(0)))
f << stringf(" 0 ");
else if (modattr && (it->second == Const(1, 1) || it->second == Const(1)))
f << stringf(" 1 ");
else
dump_const(f, it->second, -1, 0, false, attr2comment);
f << stringf(" %s%c", attr2comment ? "*/" : "*)", term);
dump_const(f, it->second, -1, 0, false, as_comment);
f << stringf(" %s%c", as_comment ? "*/" : "*)", term);
}
}
@ -1492,12 +1494,14 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw
return;
}
dump_attributes(f, indent, sw->attributes);
f << stringf("%s" "casez (", indent.c_str());
dump_sigspec(f, sw->signal);
f << stringf(")\n");
bool got_default = false;
for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) {
dump_attributes(f, indent + " ", (*it)->attributes, '\n', /*modattr=*/false, /*as_comment=*/true);
if ((*it)->compare.size() == 0) {
if (got_default)
continue;
@ -1662,7 +1666,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
}
}
dump_attributes(f, indent, module->attributes, '\n', true);
dump_attributes(f, indent, module->attributes, '\n', /*attr2comment=*/true);
f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
bool keep_running = true;
for (int port_id = 1; keep_running; port_id++) {

View File

@ -81,11 +81,26 @@ end_of_header:
else
log_abort();
RTLIL::Wire* n0 = module->wire("\\n0");
if (n0)
module->connect(n0, RTLIL::S0);
for (unsigned i = 0; i < outputs.size(); ++i) {
RTLIL::Wire *wire = outputs[i];
if (wire->port_input) {
RTLIL::Wire *o_wire = module->addWire(wire->name.str() + "_o");
o_wire->port_output = true;
wire->port_output = false;
module->connect(o_wire, wire);
outputs[i] = o_wire;
}
}
// Parse footer (symbol table, comments, etc.)
unsigned l1;
std::string s;
for (int c = f.peek(); c != EOF; c = f.peek(), ++line_count) {
if (c == 'i' || c == 'l' || c == 'o') {
if (c == 'i' || c == 'l' || c == 'o' || c == 'b') {
f.ignore(1);
if (!(f >> l1 >> s))
log_error("Line %u cannot be interpreted as a symbol entry!\n", line_count);
@ -97,11 +112,12 @@ end_of_header:
if (c == 'i') wire = inputs[l1];
else if (c == 'l') wire = latches[l1];
else if (c == 'o') wire = outputs[l1];
else if (c == 'b') wire = bad_properties[l1];
else log_abort();
module->rename(wire, stringf("\\%s", s.c_str()));
}
else if (c == 'b' || c == 'j' || c == 'f') {
else if (c == 'j' || c == 'f') {
// TODO
}
else if (c == 'c') {
@ -153,7 +169,7 @@ void AigerReader::parse_aiger_ascii()
unsigned l1, l2, l3;
// Parse inputs
for (unsigned i = 0; i < I; ++i, ++line_count) {
for (unsigned i = 1; i <= I; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as an input!\n", line_count);
log_debug("%d is an input\n", l1);
@ -187,8 +203,10 @@ void AigerReader::parse_aiger_ascii()
if (!(f >> l3))
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0 || l3 == 1)
q_wire->attributes["\\init"] = RTLIL::Const(l3);
if (l3 == 0)
q_wire->attributes["\\init"] = RTLIL::S0;
else if (l3 == 1)
q_wire->attributes["\\init"] = RTLIL::S1;
else if (l3 == l1) {
//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
}
@ -197,7 +215,7 @@ void AigerReader::parse_aiger_ascii()
}
else {
// AIGER latches are assumed to be initialized to zero
q_wire->attributes["\\init"] = RTLIL::Const(0);
q_wire->attributes["\\init"] = RTLIL::S0;
}
latches.push_back(q_wire);
}
@ -212,11 +230,17 @@ void AigerReader::parse_aiger_ascii()
wire->port_output = true;
outputs.push_back(wire);
}
std::getline(f, line); // Ignore up to start of next line
// TODO: Parse bad state properties
for (unsigned i = 0; i < B; ++i, ++line_count)
std::getline(f, line); // Ignore up to start of next line
// Parse bad properties
for (unsigned i = 0; i < B; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as a bad state property!\n", line_count);
log_debug("%d is a bad state property\n", l1);
RTLIL::Wire *wire = createWireIfNotExists(module, l1);
wire->port_output = true;
bad_properties.push_back(wire);
}
// TODO: Parse invariant constraints
for (unsigned i = 0; i < C; ++i, ++line_count)
@ -290,8 +314,10 @@ void AigerReader::parse_aiger_binary()
if (!(f >> l3))
log_error("Line %u cannot be interpreted as a latch!\n", line_count);
if (l3 == 0 || l3 == 1)
q_wire->attributes["\\init"] = RTLIL::Const(l3);
if (l3 == 0)
q_wire->attributes["\\init"] = RTLIL::S0;
else if (l3 == 1)
q_wire->attributes["\\init"] = RTLIL::S1;
else if (l3 == l1) {
//q_wire->attributes["\\init"] = RTLIL::Const(RTLIL::State::Sx);
}
@ -300,7 +326,7 @@ void AigerReader::parse_aiger_binary()
}
else {
// AIGER latches are assumed to be initialized to zero
q_wire->attributes["\\init"] = RTLIL::Const(0);
q_wire->attributes["\\init"] = RTLIL::S0;
}
latches.push_back(q_wire);
}
@ -317,8 +343,17 @@ void AigerReader::parse_aiger_binary()
}
std::getline(f, line); // Ignore up to start of next line
// TODO: Parse bad state properties
for (unsigned i = 0; i < B; ++i, ++line_count)
// Parse bad properties
for (unsigned i = 0; i < B; ++i, ++line_count) {
if (!(f >> l1))
log_error("Line %u cannot be interpreted as a bad state property!\n", line_count);
log_debug("%d is a bad state property\n", l1);
RTLIL::Wire *wire = createWireIfNotExists(module, l1);
wire->port_output = true;
bad_properties.push_back(wire);
}
if (B > 0)
std::getline(f, line); // Ignore up to start of next line
// TODO: Parse invariant constraints
@ -363,7 +398,7 @@ struct AigerFrontend : public Frontend {
log("Load module from an AIGER file into the current design.\n");
log("\n");
log(" -module_name <module_name>\n");
log(" Name of module to be created (default: <filename>)"
log(" Name of module to be created (default: "
#ifdef _WIN32
"top" // FIXME
#else

View File

@ -39,6 +39,7 @@ struct AigerReader
std::vector<RTLIL::Wire*> inputs;
std::vector<RTLIL::Wire*> latches;
std::vector<RTLIL::Wire*> outputs;
std::vector<RTLIL::Wire*> bad_properties;
AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name);
void parse_aiger();

View File

@ -46,7 +46,7 @@ namespace AST {
// instantiate global variables (private API)
namespace AST_INTERNAL {
bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_autowire;
bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_autowire;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
@ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type)
X(AST_GENIF)
X(AST_GENCASE)
X(AST_GENBLOCK)
X(AST_TECALL)
X(AST_POSEDGE)
X(AST_NEGEDGE)
X(AST_EDGE)
@ -194,6 +195,9 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
is_logic = false;
is_signed = false;
is_string = false;
is_wand = false;
is_wor = false;
is_unsized = false;
was_checked = false;
range_valid = false;
range_swapped = false;
@ -722,7 +726,7 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
}
// create an AST node for a constant (using a bit vector as value)
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
{
AstNode *node = new AstNode(AST_CONSTANT);
node->is_signed = is_signed;
@ -736,9 +740,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
node->range_valid = true;
node->range_left = node->bits.size()-1;
node->range_right = 0;
node->is_unsized = is_unsized;
return node;
}
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
{
return mkconst_bits(v, is_signed, false);
}
// create an AST node for a constant (using a string in bit vector form as value)
AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
{
@ -775,6 +785,14 @@ bool AstNode::bits_only_01() const
return true;
}
RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
{
RTLIL::State extbit = bits.back();
while (width > int(bits.size()))
bits.push_back(extbit);
return RTLIL::Const(bits);
}
RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
{
std::vector<RTLIL::State> bits = this->bits;
@ -1094,6 +1112,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
current_module->nowb = flag_nowb;
current_module->noopt = flag_noopt;
current_module->icells = flag_icells;
current_module->pwires = flag_pwires;
current_module->autowire = flag_autowire;
current_module->fixup_ports();
@ -1108,7 +1127,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
// create AstModule instances for all modules in the AST tree and add them to 'design'
void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire)
{
current_ast = ast;
flag_dump_ast1 = dump_ast1;
@ -1126,6 +1145,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
flag_nowb = nowb;
flag_noopt = noopt;
flag_icells = icells;
flag_pwires = pwires;
flag_autowire = autowire;
log_assert(current_ast->type == AST_DESIGN);
@ -1462,6 +1482,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
flag_nowb = nowb;
flag_noopt = noopt;
flag_icells = icells;
flag_pwires = pwires;
flag_autowire = autowire;
use_internal_line_num();
@ -1533,6 +1554,7 @@ RTLIL::Module *AstModule::clone() const
new_mod->lib = lib;
new_mod->noopt = noopt;
new_mod->icells = icells;
new_mod->pwires = pwires;
new_mod->autowire = autowire;
return new_mod;

View File

@ -137,6 +137,7 @@ namespace AST
AST_GENIF,
AST_GENCASE,
AST_GENBLOCK,
AST_TECALL,
AST_POSEDGE,
AST_NEGEDGE,
@ -173,7 +174,7 @@ namespace AST
// node content - most of it is unused in most node types
std::string str;
std::vector<RTLIL::State> bits;
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked;
bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized;
int port_id, range_left, range_right;
uint32_t integer;
double realvalue;
@ -262,6 +263,7 @@ namespace AST
// helper functions for creating AST nodes for constants
static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32);
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
static AstNode *mkconst_str(const std::string &str);
@ -269,6 +271,7 @@ namespace AST
// helper function for creating sign-extended const objects
RTLIL::Const bitsAsConst(int width, bool is_signed);
RTLIL::Const bitsAsConst(int width = -1);
RTLIL::Const bitsAsUnsizedConst(int width);
RTLIL::Const asAttrConst();
RTLIL::Const asParaConst();
uint64_t asInt(bool is_signed);
@ -283,13 +286,13 @@ namespace AST
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit,
bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire);
// parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module {
AstNode *ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, autowire;
bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire;
~AstModule() YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
@ -322,7 +325,7 @@ namespace AST_INTERNAL
{
// internal state variables
extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_pwires, flag_autowire;
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr;

View File

@ -504,6 +504,7 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
current_case->attributes["\\src"] = stringf("%s:%d", child->filename.c_str(), child->linenum);
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
for (auto node : child->children) {
@ -853,7 +854,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_FUNCTION:
case AST_DPI_FUNCTION:
case AST_AUTOWIRE:
case AST_LOCALPARAM:
case AST_DEFPARAM:
case AST_GENVAR:
case AST_GENFOR:
@ -895,6 +895,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// remember the parameter, needed for example in techmap
case AST_PARAMETER:
current_module->avail_parameters.insert(str);
/* fall through */
case AST_LOCALPARAM:
if (flag_pwires)
{
if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT)
log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str());
RTLIL::Const val = children[0]->bitsAsConst();
RTLIL::Wire *wire = current_module->addWire(str, GetSize(val));
current_module->connect(wire, val);
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1;
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
wire->attributes[attr.first] = attr.second->asAttrConst();
}
}
break;
// create an RTLIL::Wire for an AST_WIRE node
@ -904,7 +924,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (!range_valid)
log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str());
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
if (!(range_left >= range_right || (range_left == -1 && range_right == 0)))
log_file_error(filename, linenum, "Signal `%s' with invalid width range %d!\n", str.c_str(), range_left - range_right + 1);
RTLIL::Wire *wire = current_module->addWire(str, range_left - range_right + 1);
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@ -919,6 +940,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
wire->attributes[attr.first] = attr.second->asAttrConst();
}
if (is_wand) wire->set_bool_attribute("\\wand");
if (is_wor) wire->set_bool_attribute("\\wor");
}
break;
@ -963,8 +987,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
detectSignWidth(width_hint, sign_hint);
is_signed = sign_hint;
if (type == AST_CONSTANT)
if (type == AST_CONSTANT) {
if (is_unsized) {
return RTLIL::SigSpec(bitsAsUnsizedConst(width_hint));
} else {
return RTLIL::SigSpec(bitsAsConst());
}
}
RTLIL::SigSpec sig = realAsConst(width_hint);
log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
@ -1566,6 +1595,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
delete always;
} break;
case AST_TECALL: {
int sz = children.size();
if (str == "$info") {
if (sz > 0)
log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str());
else
log_file_info(filename, linenum, "\n");
} else if (str == "$warning") {
if (sz > 0)
log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str());
else
log_file_warning(filename, linenum, "\n");
} else if (str == "$error") {
if (sz > 0)
log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str());
else
log_file_error(filename, linenum, "\n");
} else if (str == "$fatal") {
// TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish()
// if no parameter is given, default value is 1
// dollar_finish(sz ? children[0] : 1);
// perhaps create & use log_file_fatal()
if (sz > 0)
log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str());
else
log_file_error(filename, linenum, "FATAL.\n");
} else {
log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str());
}
} break;
case AST_FCALL: {
if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq")
{

View File

@ -282,14 +282,14 @@ proc_stmt:
} case_body sync_list TOK_END EOL;
switch_stmt:
attr_list TOK_SWITCH sigspec EOL {
TOK_SWITCH sigspec EOL {
RTLIL::SwitchRule *rule = new RTLIL::SwitchRule;
rule->signal = *$3;
rule->signal = *$2;
rule->attributes = attrbuf;
switch_stack.back()->push_back(rule);
attrbuf.clear();
delete $3;
} switch_body TOK_END EOL;
delete $2;
} attr_list switch_body TOK_END EOL;
attr_list:
/* empty */ |
@ -298,9 +298,11 @@ attr_list:
switch_body:
switch_body TOK_CASE {
RTLIL::CaseRule *rule = new RTLIL::CaseRule;
rule->attributes = attrbuf;
switch_stack.back()->back()->cases.push_back(rule);
switch_stack.push_back(&rule->switches);
case_stack.push_back(rule);
attrbuf.clear();
} compare_list EOL case_body {
switch_stack.pop_back();
case_stack.pop_back();
@ -319,12 +321,15 @@ compare_list:
/* empty */;
case_body:
case_body attr_stmt |
case_body switch_stmt |
case_body assign_stmt |
/* empty */;
assign_stmt:
TOK_ASSIGN sigspec sigspec EOL {
if (attrbuf.size() != 0)
rtlil_frontend_ilang_yyerror("dangling attribute");
case_stack.back()->actions.push_back(RTLIL::SigSig(*$2, *$3));
delete $2;
delete $3;

View File

@ -292,6 +292,18 @@ void json_import(Design *design, string &modname, JsonNode *node)
if (port_wire == nullptr)
port_wire = module->addWire(port_name, GetSize(port_bits_node->data_array));
if (port_node->data_dict.count("upto") != 0) {
JsonNode *val = port_node->data_dict.at("upto");
if (val->type == 'N')
port_wire->upto = val->data_number != 0;
}
if (port_node->data_dict.count("offset") != 0) {
JsonNode *val = port_node->data_dict.at("offset");
if (val->type == 'N')
port_wire->start_offset = val->data_number;
}
if (port_direction_node->data_string == "input") {
port_wire->port_input = true;
} else
@ -372,6 +384,18 @@ void json_import(Design *design, string &modname, JsonNode *node)
if (wire == nullptr)
wire = module->addWire(net_name, GetSize(bits_node->data_array));
if (net_node->data_dict.count("upto") != 0) {
JsonNode *val = net_node->data_dict.at("upto");
if (val->type == 'N')
wire->upto = val->data_number != 0;
}
if (net_node->data_dict.count("offset") != 0) {
JsonNode *val = net_node->data_dict.at("offset");
if (val->type == 'N')
wire->start_offset = val->data_number;
}
for (int i = 0; i < GetSize(bits_node->data_array); i++)
{
JsonNode *bitval_node = bits_node->data_array.at(i);

View File

@ -48,6 +48,14 @@ USING_YOSYS_NAMESPACE
#include "VhdlUnits.h"
#include "VeriLibrary.h"
#ifndef SYMBIOTIC_VERIFIC_API_VERSION
# error "Only Symbiotic EDA flavored Verific is supported. Please contact office@symbioticeda.com for commercial support for Yosys+Verific."
#endif
#if SYMBIOTIC_VERIFIC_API_VERSION < 1
# error "Please update your version of Symbiotic EDA flavored Verific."
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
@ -2016,6 +2024,9 @@ struct VerificPass : public Pass {
// WARNING: instantiating unknown module 'XYZ' (VERI-1063)
Message::SetMessageType("VERI-1063", VERIFIC_ERROR);
// https://github.com/YosysHQ/yosys/issues/1055
RuntimeFlags::SetVar("veri_elaborate_top_level_modules_having_interface_ports", 1) ;
#ifndef DB_PRESERVE_INITIAL_VALUE
# warning Verific was built without DB_PRESERVE_INITIAL_VALUE.
#endif

View File

@ -71,7 +71,7 @@ static int my_ilog2(int x)
}
// parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type)
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized)
{
// all digits in string (MSB at index 0)
std::vector<uint8_t> digits;
@ -129,6 +129,9 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
return;
}
if (is_unsized && (len > len_in_bits))
log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
for (len = len - 1; len >= 0; len--)
if (data[len] == RTLIL::S1)
break;
@ -150,7 +153,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
{
if (warn_z) {
AstNode *ret = const2ast(code, case_type);
if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
if (ret != nullptr && std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n",
current_filename.c_str(), get_line_num());
return ret;
@ -186,7 +189,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
// Simple base-10 integer
if (*endptr == 0) {
std::vector<RTLIL::State> data;
my_strtobin(data, str, -1, 10, case_type);
my_strtobin(data, str, -1, 10, case_type, false);
if (data.back() == RTLIL::S1)
data.push_back(RTLIL::S0);
return AstNode::mkconst_bits(data, true);
@ -201,6 +204,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
{
std::vector<RTLIL::State> data;
bool is_signed = false;
bool is_unsized = len_in_bits < 0;
if (*(endptr+1) == 's') {
is_signed = true;
endptr++;
@ -209,28 +213,34 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
{
case 'b':
case 'B':
my_strtobin(data, endptr+2, len_in_bits, 2, case_type);
my_strtobin(data, endptr+2, len_in_bits, 2, case_type, is_unsized);
break;
case 'o':
case 'O':
my_strtobin(data, endptr+2, len_in_bits, 8, case_type);
my_strtobin(data, endptr+2, len_in_bits, 8, case_type, is_unsized);
break;
case 'd':
case 'D':
my_strtobin(data, endptr+2, len_in_bits, 10, case_type);
my_strtobin(data, endptr+2, len_in_bits, 10, case_type, is_unsized);
break;
case 'h':
case 'H':
my_strtobin(data, endptr+2, len_in_bits, 16, case_type);
my_strtobin(data, endptr+2, len_in_bits, 16, case_type, is_unsized);
break;
default:
char next_char = char(tolower(*(endptr+1)));
if (next_char == '0' || next_char == '1' || next_char == 'x' || next_char == 'z') {
is_unsized = true;
my_strtobin(data, endptr+1, 1, 2, case_type, is_unsized);
} else {
return NULL;
}
}
if (len_in_bits < 0) {
if (is_signed && data.back() == RTLIL::S1)
data.push_back(RTLIL::S0);
}
return AstNode::mkconst_bits(data, is_signed);
return AstNode::mkconst_bits(data, is_signed, is_unsized);
}
return NULL;

View File

@ -168,6 +168,9 @@ struct VerilogFrontend : public Frontend {
log(" -icells\n");
log(" interpret cell types starting with '$' as internal cell types\n");
log("\n");
log(" -pwires\n");
log(" add a wire for each module parameter\n");
log("\n");
log(" -nooverwrite\n");
log(" ignore re-definitions of modules. (the default behavior is to\n");
log(" create an error message if the existing module is not a black box\n");
@ -228,6 +231,7 @@ struct VerilogFrontend : public Frontend {
bool flag_nodpi = false;
bool flag_noopt = false;
bool flag_icells = false;
bool flag_pwires = false;
bool flag_nooverwrite = false;
bool flag_overwrite = false;
bool flag_defer = false;
@ -368,6 +372,10 @@ struct VerilogFrontend : public Frontend {
flag_icells = true;
continue;
}
if (arg == "-pwires") {
flag_pwires = true;
continue;
}
if (arg == "-ignore_redef" || arg == "-nooverwrite") {
flag_nooverwrite = true;
flag_overwrite = false;
@ -458,7 +466,7 @@ struct VerilogFrontend : public Frontend {
error_on_dpi_function(current_ast);
AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
if (!flag_nopp)
delete lexin;

View File

@ -193,6 +193,8 @@ YOSYS_NAMESPACE_END
to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
global state.. its a mess) */
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
if (!strcmp(yytext, "default"))
return TOK_DEFAULT;
frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext);
return TOK_SVA_LABEL;
}
@ -218,6 +220,8 @@ YOSYS_NAMESPACE_END
"output" { return TOK_OUTPUT; }
"inout" { return TOK_INOUT; }
"wire" { return TOK_WIRE; }
"wor" { return TOK_WOR; }
"wand" { return TOK_WAND; }
"reg" { return TOK_REG; }
"integer" { return TOK_INTEGER; }
"signed" { return TOK_SIGNED; }
@ -232,7 +236,7 @@ YOSYS_NAMESPACE_END
return TOK_CONSTVAL;
}
[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
[0-9]*[ \t]*\'s?[bodhBODH]*[ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
frontend_verilog_yylval.string = new std::string(yytext);
return TOK_CONSTVAL;
}
@ -309,6 +313,11 @@ supply1 { return TOK_SUPPLY1; }
return TOK_ID;
}
"$"(info|warning|error|fatal) {
frontend_verilog_yylval.string = new std::string(yytext);
return TOK_MSG_TASKS;
}
"$signed" { return TOK_TO_SIGNED; }
"$unsigned" { return TOK_TO_UNSIGNED; }

View File

@ -133,13 +133,13 @@ struct specify_rise_fall {
}
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER
%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS
%token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
%token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
%token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC
%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
%token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC
@ -319,15 +319,17 @@ module_para_list:
single_module_para:
/* empty */ |
TOK_PARAMETER {
attr TOK_PARAMETER {
if (astbuf1) delete astbuf1;
astbuf1 = new AstNode(AST_PARAMETER);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_range single_param_decl |
TOK_LOCALPARAM {
attr TOK_LOCALPARAM {
if (astbuf1) delete astbuf1;
astbuf1 = new AstNode(AST_LOCALPARAM);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_range single_param_decl |
single_param_decl;
@ -345,7 +347,13 @@ module_arg_opt_assignment:
if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
AstNode *wire = new AstNode(AST_IDENTIFIER);
wire->str = ast_stack.back()->children.back()->str;
if (ast_stack.back()->children.back()->is_reg)
if (ast_stack.back()->children.back()->is_input) {
AstNode *n = ast_stack.back()->children.back();
if (n->attributes.count("\\defaultvalue"))
delete n->attributes.at("\\defaultvalue");
n->attributes["\\defaultvalue"] = $2;
} else
if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic)
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
else
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
@ -485,6 +493,12 @@ wire_type_token_io:
wire_type_token:
TOK_WIRE {
} |
TOK_WOR {
astbuf3->is_wor = true;
} |
TOK_WAND {
astbuf3->is_wand = true;
} |
TOK_REG {
astbuf3->is_reg = true;
} |
@ -503,6 +517,7 @@ wire_type_token:
TOK_GENVAR {
astbuf3->type = AST_GENVAR;
astbuf3->is_reg = true;
astbuf3->is_signed = true;
astbuf3->range_left = 31;
astbuf3->range_right = 0;
} |
@ -1006,13 +1021,8 @@ list_of_specparam_assignments:
specparam_assignment:
ignspec_id '=' constant_mintypmax_expression ;
/*
pulsestyle_declaration :
;
showcancelled_declaration :
;
*/
ignspec_opt_cond:
TOK_IF '(' ignspec_expr ')' | /* empty */;
path_declaration :
simple_path_declaration ';'
@ -1021,8 +1031,8 @@ path_declaration :
;
simple_path_declaration :
parallel_path_description '=' path_delay_value |
full_path_description '=' path_delay_value
ignspec_opt_cond parallel_path_description '=' path_delay_value |
ignspec_opt_cond full_path_description '=' path_delay_value
;
path_delay_value :
@ -1032,32 +1042,20 @@ path_delay_value :
;
list_of_path_delay_extra_expressions :
/*
t_path_delay_expression
| trise_path_delay_expression ',' tfall_path_delay_expression
| trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression
| t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression
| t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ','
t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ','
tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression
*/
',' path_delay_expression
| ',' path_delay_expression ',' path_delay_expression
| ',' path_delay_expression ',' path_delay_expression ','
path_delay_expression ',' path_delay_expression ',' path_delay_expression
| ',' path_delay_expression ',' path_delay_expression ','
path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
path_delay_expression ',' path_delay_expression ',' path_delay_expression
;
',' path_delay_expression | ',' path_delay_expression list_of_path_delay_extra_expressions;
specify_edge_identifier :
TOK_POSEDGE | TOK_NEGEDGE ;
parallel_path_description :
'(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ;
'(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' |
'(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor opt_polarity_operator ':' ignspec_expr ')' ')' |
'(' specify_edge_identifier specify_input_terminal_descriptor '=' '>' '(' specify_output_terminal_descriptor TOK_POS_INDEXED ignspec_expr ')' ')' ;
full_path_description :
'(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ;
'(' list_of_path_inputs '*' '>' list_of_path_outputs ')' |
'(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs opt_polarity_operator ':' ignspec_expr ')' ')' |
'(' specify_edge_identifier list_of_path_inputs '*' '>' '(' list_of_path_outputs TOK_POS_INDEXED ignspec_expr ')' ')' ;
// This was broken into 2 rules to solve shift/reduce conflicts
list_of_path_inputs :
@ -1097,56 +1095,6 @@ system_timing_args :
system_timing_arg |
system_timing_args ',' system_timing_arg ;
/*
t_path_delay_expression :
path_delay_expression;
trise_path_delay_expression :
path_delay_expression;
tfall_path_delay_expression :
path_delay_expression;
tz_path_delay_expression :
path_delay_expression;
t01_path_delay_expression :
path_delay_expression;
t10_path_delay_expression :
path_delay_expression;
t0z_path_delay_expression :
path_delay_expression;
tz1_path_delay_expression :
path_delay_expression;
t1z_path_delay_expression :
path_delay_expression;
tz0_path_delay_expression :
path_delay_expression;
t0x_path_delay_expression :
path_delay_expression;
tx1_path_delay_expression :
path_delay_expression;
t1x_path_delay_expression :
path_delay_expression;
tx0_path_delay_expression :
path_delay_expression;
txz_path_delay_expression :
path_delay_expression;
tzx_path_delay_expression :
path_delay_expression;
*/
path_delay_expression :
ignspec_constant_expression;
@ -1205,6 +1153,7 @@ param_decl:
attr TOK_PARAMETER {
astbuf1 = new AstNode(AST_PARAMETER);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_real param_range param_decl_list ';' {
delete astbuf1;
};
@ -1213,6 +1162,7 @@ localparam_decl:
attr TOK_LOCALPARAM {
astbuf1 = new AstNode(AST_LOCALPARAM);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
append_attr(astbuf1, $1);
} param_signed param_integer param_real param_range param_decl_list ';' {
delete astbuf1;
};
@ -1354,7 +1304,12 @@ wire_name_and_opt_assign:
wire_name '=' expr {
AstNode *wire = new AstNode(AST_IDENTIFIER);
wire->str = ast_stack.back()->children.back()->str;
if (astbuf1->is_reg)
if (astbuf1->is_input) {
if (astbuf1->attributes.count("\\defaultvalue"))
delete astbuf1->attributes.at("\\defaultvalue");
astbuf1->attributes["\\defaultvalue"] = $3;
} else
if (astbuf1->is_reg || astbuf1->is_logic)
ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3))));
else
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3));
@ -1379,7 +1334,13 @@ wire_name:
node->children.push_back(rng);
}
node->type = AST_MEMORY;
node->children.push_back($2);
auto *rangeNode = $2;
if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) {
// SV array size [n], rewrite as [n-1:0]
rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true));
rangeNode->children.push_back(AstNode::mkconst_int(0, false));
}
node->children.push_back(rangeNode);
}
if (current_function_or_task == NULL) {
if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
@ -1526,27 +1487,40 @@ cell_port_list_rules:
cell_port | cell_port_list_rules ',' cell_port;
cell_port:
/* empty */ {
attr {
AstNode *node = new AstNode(AST_ARGUMENT);
astbuf2->children.push_back(node);
free_attr($1);
} |
expr {
attr expr {
AstNode *node = new AstNode(AST_ARGUMENT);
astbuf2->children.push_back(node);
node->children.push_back($1);
node->children.push_back($2);
free_attr($1);
} |
'.' TOK_ID '(' expr ')' {
attr '.' TOK_ID '(' expr ')' {
AstNode *node = new AstNode(AST_ARGUMENT);
node->str = *$2;
node->str = *$3;
astbuf2->children.push_back(node);
node->children.push_back($4);
delete $2;
node->children.push_back($5);
delete $3;
free_attr($1);
} |
'.' TOK_ID '(' ')' {
attr '.' TOK_ID '(' ')' {
AstNode *node = new AstNode(AST_ARGUMENT);
node->str = *$2;
node->str = *$3;
astbuf2->children.push_back(node);
delete $2;
delete $3;
free_attr($1);
} |
attr '.' TOK_ID {
AstNode *node = new AstNode(AST_ARGUMENT);
node->str = *$3;
astbuf2->children.push_back(node);
node->children.push_back(new AstNode(AST_IDENTIFIER));
node->children.back()->str = *$3;
delete $3;
free_attr($1);
};
always_stmt:
@ -1862,6 +1836,16 @@ behavioral_stmt:
} opt_arg_list ';'{
ast_stack.pop_back();
} |
TOK_MSG_TASKS attr {
AstNode *node = new AstNode(AST_TCALL);
node->str = *$1;
delete $1;
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
append_attr(node, $2);
} opt_arg_list ';'{
ast_stack.pop_back();
} |
attr TOK_BEGIN opt_label {
AstNode *node = new AstNode(AST_BLOCK);
ast_stack.back()->children.push_back(node);
@ -2157,6 +2141,15 @@ gen_stmt:
if ($6 != NULL)
delete $6;
ast_stack.pop_back();
} |
TOK_MSG_TASKS {
AstNode *node = new AstNode(AST_TECALL);
node->str = *$1;
delete $1;
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
} opt_arg_list ';'{
ast_stack.pop_back();
};
gen_stmt_block:

View File

@ -230,6 +230,9 @@ static void logv_warning_with_prefix(const char *prefix,
}
else
{
int bak_log_make_debug = log_make_debug;
log_make_debug = 0;
for (auto &re : log_werror_regexes)
if (std::regex_search(message, re))
log_error("%s", message.c_str());
@ -254,6 +257,7 @@ static void logv_warning_with_prefix(const char *prefix,
}
log_warnings_count++;
log_make_debug = bak_log_make_debug;
}
}
@ -278,6 +282,17 @@ void log_file_warning(const std::string &filename, int lineno,
va_end(ap);
}
void log_file_info(const std::string &filename, int lineno,
const char *format, ...)
{
va_list ap;
va_start(ap, format);
std::string fmt = stringf("%s:%d: Info: %s",
filename.c_str(), lineno, format);
logv(fmt.c_str(), ap);
va_end(ap);
}
YS_ATTRIBUTE(noreturn)
static void logv_error_with_prefix(const char *prefix,
const char *format, va_list ap)
@ -285,6 +300,9 @@ static void logv_error_with_prefix(const char *prefix,
#ifdef EMSCRIPTEN
auto backup_log_files = log_files;
#endif
int bak_log_make_debug = log_make_debug;
log_make_debug = 0;
log_suppressed();
if (log_errfile != NULL)
log_files.push_back(log_errfile);
@ -298,6 +316,8 @@ static void logv_error_with_prefix(const char *prefix,
log("%s%s", prefix, log_last_error.c_str());
log_flush();
log_make_debug = bak_log_make_debug;
if (log_error_atexit)
log_error_atexit();

View File

@ -80,6 +80,7 @@ void log_warning(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
// Log with filename to report a problem in a source file.
void log_file_warning(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
void log_file_info(const std::string &filename, int lineno, const char *format, ...) YS_ATTRIBUTE(format(printf, 3, 4));
void log_warning_noprefix(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));
YS_NORETURN void log_error(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2), noreturn);

View File

@ -545,6 +545,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st
}
filename = arg;
rewrite_filename(filename);
std::ofstream *ff = new std::ofstream;
ff->open(filename.c_str(), std::ofstream::trunc);
yosys_output_files.insert(filename);

View File

@ -1381,7 +1381,34 @@ void RTLIL::Module::check()
for (auto &it : processes) {
log_assert(it.first == it.second->name);
log_assert(!it.first.empty());
// FIXME: More checks here..
log_assert(it.second->root_case.compare.empty());
std::vector<CaseRule*> all_cases = {&it.second->root_case};
for (size_t i = 0; i < all_cases.size(); i++) {
for (auto &switch_it : all_cases[i]->switches) {
for (auto &case_it : switch_it->cases) {
for (auto &compare_it : case_it->compare) {
log_assert(switch_it->signal.size() == compare_it.size());
}
all_cases.push_back(case_it);
}
}
}
for (auto &sync_it : it.second->syncs) {
switch (sync_it->type) {
case SyncType::ST0:
case SyncType::ST1:
case SyncType::STp:
case SyncType::STn:
case SyncType::STe:
log_assert(!sync_it->signal.empty());
break;
case SyncType::STa:
case SyncType::STg:
case SyncType::STi:
log_assert(sync_it->signal.empty());
break;
}
}
}
for (auto &it : connections_) {

View File

@ -601,6 +601,7 @@ struct RTLIL::SigChunk
RTLIL::SigChunk &operator =(const RTLIL::SigChunk &other) = default;
RTLIL::SigChunk extract(int offset, int length) const;
inline int size() const { return width; }
bool operator <(const RTLIL::SigChunk &other) const;
bool operator ==(const RTLIL::SigChunk &other) const;
@ -1314,7 +1315,7 @@ public:
#endif
};
struct RTLIL::CaseRule
struct RTLIL::CaseRule : public RTLIL::AttrObject
{
std::vector<RTLIL::SigSpec> compare;
std::vector<RTLIL::SigSig> actions;

View File

@ -129,7 +129,7 @@ void yosys_banner()
log(" | |\n");
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
log(" | |\n");
log(" | Copyright (C) 2012 - 2018 Clifford Wolf <clifford@clifford.at> |\n");
log(" | Copyright (C) 2012 - 2019 Clifford Wolf <clifford@clifford.at> |\n");
log(" | |\n");
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
@ -651,6 +651,10 @@ void rewrite_filename(std::string &filename)
filename = filename.substr(1, GetSize(filename)-2);
if (filename.substr(0, 2) == "+/")
filename = proc_share_dirname() + filename.substr(2);
#ifndef _WIN32
if (filename.substr(0, 2) == "~/")
filename = filename.replace(0, 1, getenv("HOME"));
#endif
}
#ifdef YOSYS_ENABLE_TCL

View File

@ -87,6 +87,10 @@ extern int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName);
extern void Tcl_Finalize(void);
extern int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName, Tcl_CmdInfo *infoPtr);
extern const char *Tcl_GetStringResult(Tcl_Interp *interp);
extern Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length);
extern Tcl_Obj *Tcl_NewIntObj(int intValue);
extern Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[]);
extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *newValuePtr, int flags);
# endif
#endif

View File

@ -331,8 +331,9 @@ to update {\tt \textbackslash{}q}.
An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and
exactly one RTLIL::CaseRule object, which is called the {\it root case}.
An RTLIL::SyncRule object contains an (optional) synchronization condition
(signal and edge-type) and zero or more assignments (RTLIL::SigSig).
An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type) and zero or
more assignments (RTLIL::SigSig). The {\tt always} synchronization condition is used to break combinatorial
loops when a latch should be inferred instead.
An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig)
and zero or more RTLIL::SwitchRule objects. An RTLIL::SwitchRule objects is a
@ -350,6 +351,18 @@ and this bit is a one (the second ``1'').} for {\tt \textbackslash{}reset == 1}
sets {\tt \$0\textbackslash{}q[0:0]} to the value of {\tt \textbackslash{}d} if {\tt
\textbackslash{}enable} is active (lines $6 \dots 11$).
A case can specify zero or more compare values that will determine whether it matches. Each of the compare values
must be the exact same width as the control signal. When more than one compare value is specified, the case matches
if any of them matches the control signal; when zero compare values are specified, the case always matches (i.e.
it is the default case).
A switch prioritizes cases from first to last: multiple cases can match, but only the first matched case becomes
active. This normally synthesizes to a priority encoder. The {\tt parallel\_case} attribute allows passes to assume
that no more than one case will match, and {\tt full\_case} attribute allows passes to assume that exactly one
case will match; if these invariants are ever dynamically violated, the behavior is undefined. These attributes
are useful when an invariant invisible to the synthesizer causes the control signal to never take certain
bit patterns.
The lines $13 \dots 16$ then cause {\tt \textbackslash{}q} to be updated whenever there is
a positive clock edge on {\tt \textbackslash{}clock} or {\tt \textbackslash{}reset}.

View File

@ -61,6 +61,7 @@ SOFTWARE. */
#include <windows.h>
#include <tchar.h>
#include <fcntl.h>
#include <unistd.h>
int child_pid=0;
@ -338,7 +339,7 @@ int run(int argc, char **argv, int is_gui) {
if (is_gui) {
/* Use exec, we don't need to wait for the GUI to finish */
execv(ptr, (const char * const *)(newargs));
execv(ptr, (char * const *)(newargs));
return fail("Could not exec %s", ptr); /* shouldn't get here! */
}

View File

@ -779,6 +779,9 @@ class WClass:
#if self.link_type != link_types.pointer:
text += "\n\t\tstatic " + self.name + "* get_py_obj(" + long_name + "* ref)\n\t\t{"
text += "\n\t\t\tif(ref == nullptr){"
text += "\n\t\t\t\tthrow std::runtime_error(\"" + self.name + " does not exist.\");"
text += "\n\t\t\t}"
text += "\n\t\t\t" + self.name + "* ret = (" + self.name + "*)malloc(sizeof(" + self.name + "));"
if self.link_type == link_types.pointer:
text += "\n\t\t\tret->ref_obj = ref;"
@ -2026,7 +2029,6 @@ def gen_wrappers(filename, debug_level_ = 0):
#include <boost/python/wrapper.hpp>
#include <boost/python/call.hpp>
#include <boost/python.hpp>
#include <boost/log/exceptions.hpp>
USING_YOSYS_NAMESPACE
@ -2060,7 +2062,6 @@ namespace YOSYS_PYTHON {
Yosys::log_streams.push_back(&std::cout);
Yosys::log_error_stderr = true;
Yosys::yosys_setup();
Yosys::yosys_banner();
}
}

View File

@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct BlackboxPass : public Pass {
BlackboxPass() : Pass("blackbox", "change type of cells in the design") { }
BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|

View File

@ -393,46 +393,114 @@ struct SetundefPass : public Pass {
ffbits.insert(bit);
}
auto process_initwires = [&]()
{
dict<Wire*, int> wire_weights;
for (auto wire : initwires)
{
int weight = 0;
for (auto bit : sigmap(wire))
weight += ffbits.count(bit) ? +1 : -1;
wire_weights[wire] = weight;
}
initwires.sort([&](Wire *a, Wire *b) { return wire_weights.at(a) > wire_weights.at(b); });
for (auto wire : initwires)
{
Const &initval = wire->attributes["\\init"];
initval.bits.resize(GetSize(wire), State::Sx);
for (int i = 0; i < GetSize(wire); i++) {
SigBit bit = sigmap(SigBit(wire, i));
if (initval[i] == State::Sx && ffbits.count(bit)) {
initval[i] = worker.next_bit();
ffbits.erase(bit);
}
}
if (initval.is_fully_undef())
wire->attributes.erase("\\init");
}
initwires.clear();
};
for (int wire_types = 0; wire_types < 2; wire_types++)
{
// prioritize wires that already have an init attribute
if (!ffbits.empty())
{
for (auto wire : module->wires())
{
if (wire->name[0] == (wire_types ? '\\' : '$'))
continue;
if (!wire->attributes.count("\\init"))
continue;
for (auto bit : sigmap(wire))
ffbits.erase(bit);
Const &initval = wire->attributes["\\init"];
initval.bits.resize(GetSize(wire), State::Sx);
if (initval.is_fully_undef()) {
wire->attributes.erase("\\init");
continue;
}
for (int i = 0; i < GetSize(wire); i++)
if (initval[i] != State::Sx)
ffbits.erase(sigmap(SigBit(wire, i)));
initwires.insert(wire);
}
for (int wire_types = 0; wire_types < 2; wire_types++)
process_initwires();
}
// next consider wires that completely contain bits to be initialized
if (!ffbits.empty())
{
for (auto wire : module->wires())
{
if (wire->name[0] == (wire_types ? '\\' : '$'))
next_wire:
continue;
for (auto bit : sigmap(wire))
if (!ffbits.count(bit))
goto next_wire;
for (auto bit : sigmap(wire))
ffbits.erase(bit);
initwires.insert(wire);
next_wire:
continue;
}
process_initwires();
}
// finally use whatever wire we can find.
if (!ffbits.empty())
{
for (auto wire : module->wires())
{
if (wire->name[0] == (wire_types ? '\\' : '$'))
continue;
for (auto bit : sigmap(wire))
if (ffbits.count(bit))
initwires.insert(wire);
}
for (auto wire : initwires)
{
Const &initval = wire->attributes["\\init"];
for (int i = 0; i < GetSize(wire); i++)
if (GetSize(initval) <= i)
initval.bits.push_back(worker.next_bit());
else if (initval.bits[i] == State::Sx)
initval.bits[i] = worker.next_bit();
process_initwires();
}
}
log_assert(ffbits.empty());
}
module->rewrite_sigspecs(worker);
if (worker.next_bit_mode == MODE_ANYSEQ || worker.next_bit_mode == MODE_ANYCONST)

View File

@ -285,8 +285,8 @@ struct StatPass : public Pass {
log(" use cell area information from the provided liberty file\n");
log("\n");
log(" -tech <technology>\n");
log(" print area estemate for the specified technology. Corrently supported\n");
log(" calues for <technology>: xilinx\n");
log(" print area estemate for the specified technology. Currently supported\n");
log(" values for <technology>: xilinx\n");
log("\n");
log(" -width\n");
log(" annotate internal cell types with their word width.\n");

View File

@ -52,7 +52,9 @@ struct TeePass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::vector<FILE*> backup_log_files, files_to_close;
std::vector<std::ostream*> backup_log_streams;
int backup_log_verbose_level = log_verbose_level;
backup_log_streams = log_streams;
backup_log_files = log_files;
size_t argidx;
@ -60,6 +62,7 @@ struct TeePass : public Pass {
{
if (args[argidx] == "-q" && files_to_close.empty()) {
log_files.clear();
log_streams.clear();
continue;
}
if ((args[argidx] == "-o" || args[argidx] == "-a") && argidx+1 < args.size()) {
@ -89,6 +92,7 @@ struct TeePass : public Pass {
for (auto cf : files_to_close)
fclose(cf);
log_files = backup_log_files;
log_streams = backup_log_streams;
throw;
}
@ -97,6 +101,7 @@ struct TeePass : public Pass {
log_verbose_level = backup_log_verbose_level;
log_files = backup_log_files;
log_streams = backup_log_streams;
}
} TeePass;

View File

@ -62,7 +62,7 @@ struct WriteFileFrontend : public Frontend {
if (argidx < args.size() && args[argidx].rfind("-", 0) != 0)
output_filename = args[argidx++];
else
log_cmd_error("Missing putput filename.\n");
log_cmd_error("Missing output filename.\n");
extra_args(f, filename, args, argidx);

View File

@ -562,7 +562,8 @@ struct HierarchyPass : public Pass {
log("In parametric designs, a module might exists in several variations with\n");
log("different parameter values. This pass looks at all modules in the current\n");
log("design an re-runs the language frontends for the parametric modules as\n");
log("needed.\n");
log("needed. It also resolves assignments to wired logic data types (wand/wor),\n");
log("resolves positional module parameters, unroll array instances, and more.\n");
log("\n");
log(" -check\n");
log(" also check the design hierarchy. this generates an error when\n");
@ -590,6 +591,9 @@ struct HierarchyPass : public Pass {
log(" module instances when the width does not match the module port. This\n");
log(" option disables this behavior.\n");
log("\n");
log(" -nodefaults\n");
log(" do not resolve input port default values\n");
log("\n");
log(" -nokeep_asserts\n");
log(" per default this pass sets the \"keep\" attribute on all modules\n");
log(" that directly or indirectly contain one or more formal properties.\n");
@ -644,6 +648,7 @@ struct HierarchyPass : public Pass {
bool generate_mode = false;
bool keep_positionals = false;
bool keep_portwidths = false;
bool nodefaults = false;
bool nokeep_asserts = false;
std::vector<std::string> generate_cells;
std::vector<generate_port_decl_t> generate_ports;
@ -711,6 +716,10 @@ struct HierarchyPass : public Pass {
keep_portwidths = true;
continue;
}
if (args[argidx] == "-nodefaults") {
nodefaults = true;
continue;
}
if (args[argidx] == "-nokeep_asserts") {
nokeep_asserts = true;
continue;
@ -939,10 +948,155 @@ struct HierarchyPass : public Pass {
}
}
if (!nodefaults)
{
dict<IdString, dict<IdString, Const>> defaults_db;
for (auto module : design->modules())
for (auto wire : module->wires())
if (wire->port_input && wire->attributes.count("\\defaultvalue"))
defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue");
for (auto module : design->modules())
for (auto cell : module->cells())
{
if (defaults_db.count(cell->type) == 0)
continue;
if (keep_positionals) {
bool found_positionals = false;
for (auto &conn : cell->connections())
if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9')
found_positionals = true;
if (found_positionals)
continue;
}
for (auto &it : defaults_db.at(cell->type))
if (!cell->hasPort(it.first))
cell->setPort(it.first, it.second);
}
}
std::set<Module*> blackbox_derivatives;
std::vector<Module*> design_modules = design->modules();
for (auto module : design_modules)
{
pool<Wire*> wand_wor_index;
dict<Wire*, SigSpec> wand_map, wor_map;
vector<SigSig> new_connections;
for (auto wire : module->wires())
{
if (wire->get_bool_attribute("\\wand")) {
wand_map[wire] = SigSpec();
wand_wor_index.insert(wire);
}
if (wire->get_bool_attribute("\\wor")) {
wor_map[wire] = SigSpec();
wand_wor_index.insert(wire);
}
}
for (auto &conn : module->connections())
{
SigSig new_conn;
int cursor = 0;
for (auto c : conn.first.chunks())
{
Wire *w = c.wire;
SigSpec rhs = conn.second.extract(cursor, GetSize(c));
if (wand_wor_index.count(w) == 0) {
new_conn.first.append(c);
new_conn.second.append(rhs);
} else {
if (wand_map.count(w)) {
SigSpec sig = SigSpec(State::S1, GetSize(w));
sig.replace(c.offset, rhs);
wand_map.at(w).append(sig);
} else {
SigSpec sig = SigSpec(State::S0, GetSize(w));
sig.replace(c.offset, rhs);
wor_map.at(w).append(sig);
}
}
cursor += GetSize(c);
}
new_connections.push_back(new_conn);
}
module->new_connections(new_connections);
for (auto cell : module->cells())
{
if (!cell->known())
continue;
for (auto &conn : cell->connections())
{
if (!cell->output(conn.first))
continue;
SigSpec new_sig;
bool update_port = false;
for (auto c : conn.second.chunks())
{
Wire *w = c.wire;
if (wand_wor_index.count(w) == 0) {
new_sig.append(c);
continue;
}
Wire *t = module->addWire(NEW_ID, GetSize(c));
new_sig.append(t);
update_port = true;
if (wand_map.count(w)) {
SigSpec sig = SigSpec(State::S1, GetSize(w));
sig.replace(c.offset, t);
wand_map.at(w).append(sig);
} else {
SigSpec sig = SigSpec(State::S0, GetSize(w));
sig.replace(c.offset, t);
wor_map.at(w).append(sig);
}
}
if (update_port)
cell->setPort(conn.first, new_sig);
}
}
for (auto w : wand_wor_index)
{
bool wand = wand_map.count(w);
SigSpec sigs = wand ? wand_map.at(w) : wor_map.at(w);
if (GetSize(sigs) == 0)
continue;
if (GetSize(w) == 1) {
if (wand)
module->addReduceAnd(NEW_ID, sigs, w);
else
module->addReduceOr(NEW_ID, sigs, w);
continue;
}
SigSpec s = sigs.extract(0, GetSize(w));
for (int i = GetSize(w); i < GetSize(sigs); i += GetSize(w)) {
if (wand)
s = module->And(NEW_ID, s, sigs.extract(i, GetSize(w)));
else
s = module->Or(NEW_ID, s, sigs.extract(i, GetSize(w)));
}
module->connect(w, s);
}
for (auto cell : module->cells())
{
Module *m = design->module(cell->type);
@ -1001,6 +1155,7 @@ struct HierarchyPass : public Pass {
log_id(module), log_id(cell), log_id(conn.first), log_id(cell->type), log_signal(sig));
}
}
}
for (auto module : blackbox_derivatives)
design->remove(module);

View File

@ -17,6 +17,7 @@
*
*/
#include <algorithm>
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
@ -182,20 +183,27 @@ struct MemoryDffWorker
if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data))
{
RTLIL::SigSpec en;
std::vector<RTLIL::SigSpec> check_q;
do {
bool enable_invert = mux_cells_a.count(sig_data) != 0;
Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data);
SigSpec check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A"));
check_q.push_back(sigmap(mux->getPort(enable_invert ? "\\B" : "\\A")));
sig_data = sigmap(mux->getPort("\\Y"));
en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S"));
} while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data));
for (auto bit : sig_data)
if (sigbit_users_count[bit] > 1)
goto skip_ff_after_read_merging;
if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q)
if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) &&
std::all_of(check_q.begin(), check_q.end(), [&](const SigSpec &cq) {return cq == sig_data; }))
{
disconnect_dff(sig_data);
cell->setPort("\\CLK", clk_data);
cell->setPort("\\EN", enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S"));
cell->setPort("\\EN", en.size() > 1 ? module->ReduceAnd(NEW_ID, en) : en);
cell->setPort("\\DATA", sig_data);
cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1);
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity);

View File

@ -14,5 +14,6 @@ OBJS += passes/opt/opt_demorgan.o
OBJS += passes/opt/rmports.o
OBJS += passes/opt/opt_lut.o
OBJS += passes/opt/pmux2shiftx.o
OBJS += passes/opt/muxpack.o
endif

368
yosys/passes/opt/muxpack.cc Normal file
View File

@ -0,0 +1,368 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
* 2019 Eddie Hung <eddie@fpgeh.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 "kernel/yosys.h"
#include "kernel/sigtools.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct ExclusiveDatabase
{
Module *module;
const SigMap &sigmap;
dict<SigBit, std::pair<SigSpec,std::vector<Const>>> sig_cmp_prev;
ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap)
{
SigSpec const_sig, nonconst_sig;
SigBit y_port;
pool<Cell*> reduce_or;
for (auto cell : module->cells()) {
if (cell->type == "$eq") {
nonconst_sig = sigmap(cell->getPort("\\A"));
const_sig = sigmap(cell->getPort("\\B"));
if (!const_sig.is_fully_const()) {
if (!nonconst_sig.is_fully_const())
continue;
std::swap(nonconst_sig, const_sig);
}
y_port = sigmap(cell->getPort("\\Y"));
}
else if (cell->type == "$logic_not") {
nonconst_sig = sigmap(cell->getPort("\\A"));
const_sig = Const(RTLIL::S0, GetSize(nonconst_sig));
y_port = sigmap(cell->getPort("\\Y"));
}
else if (cell->type == "$reduce_or") {
reduce_or.insert(cell);
continue;
}
else continue;
log_assert(!nonconst_sig.empty());
log_assert(!const_sig.empty());
sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::vector<Const>{const_sig.as_const()});
}
for (auto cell : reduce_or) {
nonconst_sig = SigSpec();
std::vector<Const> values;
SigSpec a_port = sigmap(cell->getPort("\\A"));
for (auto bit : a_port) {
auto it = sig_cmp_prev.find(bit);
if (it == sig_cmp_prev.end()) {
nonconst_sig = SigSpec();
break;
}
if (nonconst_sig.empty())
nonconst_sig = it->second.first;
else if (nonconst_sig != it->second.first) {
nonconst_sig = SigSpec();
break;
}
for (auto value : it->second.second)
values.push_back(value);
}
if (nonconst_sig.empty())
continue;
y_port = sigmap(cell->getPort("\\Y"));
sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values));
}
}
bool query(const SigSpec &sig) const
{
SigSpec nonconst_sig;
pool<Const> const_values;
for (auto bit : sig.bits()) {
auto it = sig_cmp_prev.find(bit);
if (it == sig_cmp_prev.end())
return false;
if (nonconst_sig.empty())
nonconst_sig = it->second.first;
else if (nonconst_sig != it->second.first)
return false;
for (auto value : it->second.second)
if (!const_values.insert(value).second)
return false;
}
return true;
}
};
struct MuxpackWorker
{
Module *module;
SigMap sigmap;
int mux_count, pmux_count;
pool<Cell*> remove_cells;
dict<SigSpec, Cell*> sig_chain_next;
dict<SigSpec, Cell*> sig_chain_prev;
pool<SigBit> sigbit_with_non_chain_users;
pool<Cell*> chain_start_cells;
pool<Cell*> candidate_cells;
ExclusiveDatabase excl_db;
void make_sig_chain_next_prev()
{
for (auto wire : module->wires())
{
if (wire->port_output || wire->get_bool_attribute("\\keep")) {
for (auto bit : sigmap(wire))
sigbit_with_non_chain_users.insert(bit);
}
}
for (auto cell : module->cells())
{
if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
{
SigSpec a_sig = sigmap(cell->getPort("\\A"));
SigSpec b_sig;
if (cell->type == "$mux")
b_sig = sigmap(cell->getPort("\\B"));
SigSpec y_sig = sigmap(cell->getPort("\\Y"));
if (sig_chain_next.count(a_sig))
for (auto a_bit : a_sig.bits())
sigbit_with_non_chain_users.insert(a_bit);
else {
sig_chain_next[a_sig] = cell;
candidate_cells.insert(cell);
}
if (!b_sig.empty()) {
if (sig_chain_next.count(b_sig))
for (auto b_bit : b_sig.bits())
sigbit_with_non_chain_users.insert(b_bit);
else {
sig_chain_next[b_sig] = cell;
candidate_cells.insert(cell);
}
}
sig_chain_prev[y_sig] = cell;
continue;
}
for (auto conn : cell->connections())
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
sigbit_with_non_chain_users.insert(bit);
}
}
void find_chain_start_cells()
{
for (auto cell : candidate_cells)
{
log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
SigSpec a_sig = sigmap(cell->getPort("\\A"));
if (cell->type == "$mux") {
SigSpec b_sig = sigmap(cell->getPort("\\B"));
if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
goto start_cell;
if (!sig_chain_prev.count(a_sig))
a_sig = b_sig;
}
else if (cell->type == "$pmux") {
if (!sig_chain_prev.count(a_sig))
goto start_cell;
}
else log_abort();
for (auto bit : a_sig.bits())
if (sigbit_with_non_chain_users.count(bit))
goto start_cell;
{
Cell *prev_cell = sig_chain_prev.at(a_sig);
log_assert(prev_cell);
SigSpec s_sig = sigmap(cell->getPort("\\S"));
s_sig.append(sigmap(prev_cell->getPort("\\S")));
if (!excl_db.query(s_sig))
goto start_cell;
}
continue;
start_cell:
chain_start_cells.insert(cell);
}
}
vector<Cell*> create_chain(Cell *start_cell)
{
vector<Cell*> chain;
Cell *c = start_cell;
while (c != nullptr)
{
chain.push_back(c);
SigSpec y_sig = sigmap(c->getPort("\\Y"));
if (sig_chain_next.count(y_sig) == 0)
break;
c = sig_chain_next.at(y_sig);
if (chain_start_cells.count(c) != 0)
break;
}
return chain;
}
void process_chain(vector<Cell*> &chain)
{
if (GetSize(chain) < 2)
return;
int cursor = 0;
while (cursor < GetSize(chain))
{
int cases = GetSize(chain) - cursor;
Cell *first_cell = chain[cursor];
dict<int, SigBit> taps_dict;
if (cases < 2) {
cursor++;
continue;
}
Cell *last_cell = chain[cursor+cases-1];
log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n",
log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases);
mux_count += cases;
pmux_count += 1;
first_cell->type = "$pmux";
SigSpec b_sig = first_cell->getPort("\\B");
SigSpec s_sig = first_cell->getPort("\\S");
for (int i = 1; i < cases; i++) {
Cell* prev_cell = chain[cursor+i-1];
Cell* cursor_cell = chain[cursor+i];
if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
b_sig.append(cursor_cell->getPort("\\B"));
s_sig.append(cursor_cell->getPort("\\S"));
}
else {
log_assert(cursor_cell->type == "$mux");
b_sig.append(cursor_cell->getPort("\\A"));
s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
}
remove_cells.insert(cursor_cell);
}
first_cell->setPort("\\B", b_sig);
first_cell->setPort("\\S", s_sig);
first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
cursor += cases;
}
}
void cleanup()
{
for (auto cell : remove_cells)
module->remove(cell);
remove_cells.clear();
sig_chain_next.clear();
sig_chain_prev.clear();
chain_start_cells.clear();
candidate_cells.clear();
}
MuxpackWorker(Module *module) :
module(module), sigmap(module), mux_count(0), pmux_count(0), excl_db(module, sigmap)
{
make_sig_chain_next_prev();
find_chain_start_cells();
for (auto c : chain_start_cells) {
vector<Cell*> chain = create_chain(c);
process_chain(chain);
}
cleanup();
}
};
struct MuxpackPass : public Pass {
MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" muxpack [selection]\n");
log("\n");
log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n");
log("constructs) and $mux cells (e.g. those created by if-else constructs) into\n");
log("$pmux cells.\n");
log("\n");
log("This optimisation is conservative --- it will only pack $mux or $pmux cells\n");
log("whose select lines are driven by '$eq' cells with other such cells if it can be\n");
log("certain that their select inputs are mutually exclusive.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
break;
}
extra_args(args, argidx, design);
int mux_count = 0;
int pmux_count = 0;
for (auto module : design->selected_modules()) {
MuxpackWorker worker(module);
mux_count += worker.mux_count;
pmux_count += worker.pmux_count;
}
log("Converted %d (p)mux cells into %d pmux cells.\n", mux_count, pmux_count);
}
} MuxpackPass;
PRIVATE_NAMESPACE_END

View File

@ -106,7 +106,7 @@ void rmunused_module_cells(Module *module, bool verbose)
if (raw_bit.wire == nullptr)
continue;
auto bit = sigmap(raw_bit);
if (bit.wire == nullptr)
if (bit.wire == nullptr && ct_all.cell_known(cell->type))
driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict "
"for %s between cell %s.%s and constant %s in %s: Resolved using constant.",
log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module)));
@ -319,14 +319,15 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
wire->attributes.erase("\\init");
if (GetSize(wire) == 0) {
// delete zero-width wires
// delete zero-width wires, unless they are module ports
if (wire->port_id == 0)
goto delete_this_wire;
} else
if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) {
// do not delete anything with "keep" or module ports or initialized wires
} else
if (!purge_mode && check_public_name(wire->name)) {
// do not get rid of public names unless in purge mode
if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) {
// do not get rid of public names unless in purge mode or if the wire is entirely unused, not even aliased
} else
if (!raw_used_signals.check_any(s1)) {
// delete wires that aren't used by anything directly
@ -479,7 +480,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool
std::vector<RTLIL::Cell*> delcells;
for (auto cell : module->cells())
if (cell->type.in("$pos", "$_BUF_")) {
if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) {
bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool();
RTLIL::SigSpec a = cell->getPort("\\A");
RTLIL::SigSpec y = cell->getPort("\\Y");

View File

@ -81,7 +81,7 @@ struct OptLutWorker
}
}
log("Number of LUTs: %8zu\n", luts.size());
log("Number of LUTs: %8d\n", GetSize(luts));
for (int arity = 1; arity <= max_arity; arity++)
{
if (arity_counts[arity])
@ -353,14 +353,14 @@ struct OptLutWorker
int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
if (lutA_dlogic_inputs.size())
log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
log(" Cell A is a %d-LUT with %d dedicated connections. ", lutA_arity, GetSize(lutA_dlogic_inputs));
else
log(" Cell A is a %d-LUT. ", lutA_arity);
if (lutB_dlogic_inputs.size())
log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
log("Cell B is a %d-LUT with %d dedicated connections.\n", lutB_arity, GetSize(lutB_dlogic_inputs));
else
log("Cell B is a %d-LUT.\n", lutB_arity);
log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
log(" Cells share %d input(s) and can be merged into one %d-LUT.\n", GetSize(common_inputs), lutM_arity);
const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
int combine_mask = 0;

View File

@ -260,8 +260,8 @@ delete_dlatch:
bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
{
RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r;
RTLIL::Const val_cp, val_rp, val_rv;
RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e;
RTLIL::Const val_cp, val_rp, val_rv, val_ep;
if (dff->type == "$_FF_") {
sig_d = dff->getPort("\\D");
@ -285,6 +285,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
val_rp = RTLIL::Const(dff->type[7] == 'P', 1);
val_rv = RTLIL::Const(dff->type[8] == '1', 1);
}
else if (dff->type.substr(0,7) == "$_DFFE_" && dff->type.substr(9) == "_" &&
(dff->type[7] == 'N' || dff->type[7] == 'P') &&
(dff->type[8] == 'N' || dff->type[8] == 'P')) {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\C");
sig_e = dff->getPort("\\E");
val_cp = RTLIL::Const(dff->type[7] == 'P', 1);
val_ep = RTLIL::Const(dff->type[8] == 'P', 1);
}
else if (dff->type == "$ff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
@ -295,6 +305,14 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
sig_c = dff->getPort("\\CLK");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
}
else if (dff->type == "$dffe") {
sig_e = dff->getPort("\\EN");
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
sig_c = dff->getPort("\\CLK");
val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1);
val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1);
}
else if (dff->type == "$adff") {
sig_d = dff->getPort("\\D");
sig_q = dff->getPort("\\Q");
@ -337,39 +355,60 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
}
}
// If clock is driven by a constant and (i) no reset signal
// (ii) Q has no initial value
// (iii) initial value is same as reset value
if (!sig_c.empty() && sig_c.is_fully_const() && (!sig_r.size() || !has_init || val_init == val_rv)) {
if (val_rv.bits.size() == 0)
val_rv = val_init;
// Q is permanently reset value or initial value
mod->connect(sig_q, val_rv);
goto delete_dff;
}
// If D is fully undefined and reset signal present and (i) Q has no initial value
// (ii) initial value is same as reset value
if (sig_d.is_fully_undef() && sig_r.size() && (!has_init || val_init == val_rv)) {
// Q is permanently reset value
mod->connect(sig_q, val_rv);
goto delete_dff;
}
// If D is fully undefined and no reset signal and Q has an initial value
if (sig_d.is_fully_undef() && !sig_r.size() && has_init) {
// Q is permanently initial value
mod->connect(sig_q, val_init);
goto delete_dff;
}
// If D is fully constant and (i) no reset signal
// (ii) reset value is same as constant D
// and (a) has no initial value
// (b) initial value same as constant D
if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) {
// Q is permanently D
mod->connect(sig_q, sig_d);
goto delete_dff;
}
// If D input is same as Q output and (i) no reset signal
// (ii) no initial signal
// (iii) initial value is same as reset value
if (sig_d == sig_q && (sig_r.empty() || !has_init || val_init == val_rv)) {
// Q is permanently reset value or initial value
if (sig_r.size())
mod->connect(sig_q, val_rv);
if (has_init)
else if (has_init)
mod->connect(sig_q, val_init);
goto delete_dff;
}
// If reset signal is present, and is fully constant
if (!sig_r.empty() && sig_r.is_fully_const())
{
// If reset value is permanently active or if reset is undefined
if (sig_r == val_rp || sig_r.is_fully_undef()) {
// Q is permanently reset value
mod->connect(sig_q, val_rv);
goto delete_dff;
}
@ -389,6 +428,30 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff)
dff->unsetPort("\\R");
}
// If enable signal is present, and is fully constant
if (!sig_e.empty() && sig_e.is_fully_const())
{
// If enable value is permanently inactive
if (sig_e != val_ep) {
// Q is permanently initial value
mod->connect(sig_q, val_init);
goto delete_dff;
}
log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod));
if (dff->type == "$dffe") {
dff->type = "$dff";
dff->unsetPort("\\EN");
dff->unsetParam("\\EN_POLARITY");
return true;
}
log_assert(dff->type.substr(0,7) == "$_DFFE_");
dff->type = stringf("$_DFF_%c_", + dff->type[7]);
dff->unsetPort("\\E");
}
return false;
delete_dff:
@ -489,7 +552,8 @@ struct OptRmdffPass : public Pass {
if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_",
"$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
"$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_",
"$ff", "$dff", "$adff"))
"$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_",
"$ff", "$dff", "$dffe", "$adff"))
dff_list.push_back(cell->name);
if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_"))

View File

@ -221,6 +221,9 @@ struct Pmux2ShiftxPass : public Pass {
log(" select strategy for one-hot encoded control signals\n");
log(" default: pmux\n");
log("\n");
log(" -norange\n");
log(" disable $sub inference for \"range decoders\"\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
@ -230,6 +233,7 @@ struct Pmux2ShiftxPass : public Pass {
bool optimize_onehot = true;
bool verbose = false;
bool verbose_onehot = false;
bool norange = false;
log_header(design, "Executing PMUX2SHIFTX pass.\n");
@ -270,6 +274,10 @@ struct Pmux2ShiftxPass : public Pass {
verbose_onehot = true;
continue;
}
if (args[argidx] == "-norange") {
norange = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -559,7 +567,7 @@ struct Pmux2ShiftxPass : public Pass {
int this_inv_delta = this_maxval - this_minval;
bool this_inv = false;
if (this_delta != this_inv_delta)
if (!norange && this_delta != this_inv_delta)
this_inv = this_inv_delta < this_delta;
else if (this_maxval != this_inv_maxval)
this_inv = this_inv_maxval < this_maxval;
@ -574,7 +582,7 @@ struct Pmux2ShiftxPass : public Pass {
if (best_src_col < 0)
this_is_better = true;
else if (this_delta != best_delta)
else if (!norange && this_delta != best_delta)
this_is_better = this_delta < best_delta;
else if (this_maxval != best_maxval)
this_is_better = this_maxval < best_maxval;
@ -656,7 +664,7 @@ struct Pmux2ShiftxPass : public Pass {
// check density percentages
Const offset(State::S0, GetSize(sig));
if (absolute_density < min_density && range_density >= min_density)
if (!norange && absolute_density < min_density && range_density >= min_density)
{
offset = Const(min_choice, GetSize(sig));
log(" offset: %s\n", log_signal(offset));

View File

@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass {
wire->port_output = false;
wire->port_id = 0;
}
log("Removed %zu unused ports.\n", unused_ports.size());
log("Removed %d unused ports.\n", GetSize(unused_ports));
// Re-number all of the wires that DO have ports still on them
for(size_t i=0; i<module->ports.size(); i++)

View File

@ -1,4 +1,7 @@
pattern shiftmul
//
// Optimize mul+shift pairs that result from expressions such as foo[s*W+:W]
//
state <SigSpec> shamt
@ -49,12 +52,16 @@ code
if (GetSize(port(shift, \Y)) > const_factor)
reject;
int factor_bits = ceil_log2(const_factor);
SigSpec mul_din = port(mul, const_factor_port == \A ? \B : \A);
if (GetSize(shamt) < factor_bits+GetSize(mul_din))
reject;
did_something = true;
log("shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul));
int new_const_factor_log2 = ceil_log2(const_factor);
int new_const_factor = 1 << new_const_factor_log2;
int new_const_factor = 1 << factor_bits;
SigSpec padding(State::Sx, new_const_factor-const_factor);
SigSpec old_a = port(shift, \A), new_a;
int trunc = 0;
@ -73,7 +80,7 @@ code
if (trunc > 0)
new_a.remove(GetSize(new_a)-trunc, trunc);
SigSpec new_b = {port(mul, const_factor_port == \A ? \B : \A), SigSpec(State::S0, new_const_factor_log2)};
SigSpec new_b = {mul_din, SigSpec(State::S0, factor_bits)};
if (param(shift, \B_SIGNED).as_bool())
new_b.append(State::S0);

View File

@ -144,7 +144,13 @@ struct SnippetSwCache
}
};
RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw, bool ifxmode)
void apply_attrs(RTLIL::Cell *cell, const RTLIL::SwitchRule *sw, const RTLIL::CaseRule *cs)
{
cell->attributes = sw->attributes;
cell->add_strpool_attribute("\\src", cs->get_strpool_attribute("\\src"));
}
RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
{
std::stringstream sstr;
sstr << "$procmux$" << (autoidx++);
@ -173,7 +179,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
{
// create compare cell
RTLIL::Cell *eq_cell = mod->addCell(stringf("%s_CMP%d", sstr.str().c_str(), cmp_wire->width), ifxmode ? "$eqx" : "$eq");
eq_cell->attributes = sw->attributes;
apply_attrs(eq_cell, sw, cs);
eq_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
eq_cell->parameters["\\B_SIGNED"] = RTLIL::Const(0);
@ -199,7 +205,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
// reduce cmp vector to one logic signal
RTLIL::Cell *any_cell = mod->addCell(sstr.str() + "_ANY", "$reduce_or");
any_cell->attributes = sw->attributes;
apply_attrs(any_cell, sw, cs);
any_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
any_cell->parameters["\\A_WIDTH"] = RTLIL::Const(cmp_wire->width);
@ -212,7 +218,7 @@ RTLIL::SigSpec gen_cmp(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
return RTLIL::SigSpec(ctrl_wire);
}
RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode)
RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::SigSpec else_signal, RTLIL::Cell *&last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
{
log_assert(when_signal.size() == else_signal.size());
@ -224,7 +230,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
return when_signal;
// compare results
RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode);
RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode);
if (ctrl_sig.size() == 0)
return when_signal;
log_assert(ctrl_sig.size() == 1);
@ -234,7 +240,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
// create the multiplexer itself
RTLIL::Cell *mux_cell = mod->addCell(sstr.str(), "$mux");
mux_cell->attributes = sw->attributes;
apply_attrs(mux_cell, sw, cs);
mux_cell->parameters["\\WIDTH"] = RTLIL::Const(when_signal.size());
mux_cell->setPort("\\A", else_signal);
@ -246,7 +252,7 @@ RTLIL::SigSpec gen_mux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const s
return RTLIL::SigSpec(result_wire);
}
void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, bool ifxmode)
void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::vector<RTLIL::SigSpec> &compare, RTLIL::SigSpec when_signal, RTLIL::Cell *last_mux_cell, RTLIL::SwitchRule *sw, RTLIL::CaseRule *cs, bool ifxmode)
{
log_assert(last_mux_cell != NULL);
log_assert(when_signal.size() == last_mux_cell->getPort("\\A").size());
@ -254,7 +260,7 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve
if (when_signal == last_mux_cell->getPort("\\A"))
return;
RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, ifxmode);
RTLIL::SigSpec ctrl_sig = gen_cmp(mod, signal, compare, sw, cs, ifxmode);
log_assert(ctrl_sig.size() == 1);
last_mux_cell->type = "$pmux";
@ -395,9 +401,9 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
RTLIL::CaseRule *cs2 = sw->cases[case_idx];
RTLIL::SigSpec value = signal_to_mux_tree(mod, swcache, swpara, cs2, sig, initial_val, ifxmode);
if (last_mux_cell && pgroups[case_idx] == pgroups[case_idx+1])
append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, ifxmode);
append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, cs2, ifxmode);
else
result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, ifxmode);
result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, cs2, ifxmode);
}
}

View File

@ -180,7 +180,7 @@ struct AssertpmuxWorker
};
struct AssertpmuxPass : public Pass {
AssertpmuxPass() : Pass("assertpmux", "convert internal signals to module ports") { }
AssertpmuxPass() : Pass("assertpmux", "adds asserts for parallel muxes") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
@ -195,8 +195,8 @@ struct AssertpmuxPass : public Pass {
log("\n");
log(" -always\n");
log(" usually the $pmux condition is only checked when the $pmux output\n");
log(" is used be the mux tree it drives. this option will deactivate this\n");
log(" additional constrained and check the $pmux condition always.\n");
log(" is used by the mux tree it drives. this option will deactivate this\n");
log(" additional constraint and check the $pmux condition always.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE

View File

@ -24,7 +24,7 @@ USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct CutpointPass : public Pass {
CutpointPass() : Pass("cutpoint", "add hi/lo cover cells for each wire bit") { }
CutpointPass() : Pass("cutpoint", "adds formal cut points to the design") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|

View File

@ -332,7 +332,7 @@ struct FmcombinePass : public Pass {
gate_cell = module->cell(gate_name);
if (gate_cell == nullptr)
log_cmd_error("Gold cell %s not found in module %s.\n", log_id(gate_name), log_id(module));
log_cmd_error("Gate cell %s not found in module %s.\n", log_id(gate_name), log_id(module));
}
else
{
@ -351,7 +351,7 @@ struct FmcombinePass : public Pass {
if (!gold_cell->parameters.empty())
log_cmd_error("Gold cell has unresolved instance parameters.\n");
if (!gate_cell->parameters.empty())
log_cmd_error("Gold cell has unresolved instance parameters.\n");
log_cmd_error("Gate cell has unresolved instance parameters.\n");
FmcombineWorker worker(design, gold_cell->type, opts);
worker.generate();

View File

@ -659,6 +659,7 @@ struct SatHelper
void dump_model_to_vcd(std::string vcd_file_name)
{
rewrite_filename(vcd_file_name);
FILE *f = fopen(vcd_file_name.c_str(), "w");
if (!f)
log_cmd_error("Can't open output file `%s' for writing: %s\n", vcd_file_name.c_str(), strerror(errno));
@ -761,6 +762,7 @@ struct SatHelper
void dump_model_to_json(std::string json_file_name)
{
rewrite_filename(json_file_name);
FILE *f = fopen(json_file_name.c_str(), "w");
if (!f)
log_cmd_error("Can't open output file `%s' for writing: %s\n", json_file_name.c_str(), strerror(errno));
@ -1505,6 +1507,7 @@ struct SatPass : public Pass {
{
if (!cnf_file_name.empty())
{
rewrite_filename(cnf_file_name);
FILE *f = fopen(cnf_file_name.c_str(), "w");
if (!f)
log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno));
@ -1608,6 +1611,7 @@ struct SatPass : public Pass {
if (!cnf_file_name.empty())
{
rewrite_filename(cnf_file_name);
FILE *f = fopen(cnf_file_name.c_str(), "w");
if (!f)
log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno));

View File

@ -88,6 +88,8 @@ struct SimInstance
SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
{
log_assert(module);
if (parent) {
log_assert(parent->children.count(instance) == 0);
parent->children[instance] = this;
@ -848,6 +850,9 @@ struct SimPass : public Pass {
if (design->full_selection()) {
top_mod = design->top_module();
if (!top_mod)
log_cmd_error("Design has no top module, use the 'hierarchy' command to specify one.\n");
} else {
auto mods = design->selected_whole_modules();
if (GetSize(mods) != 1)

View File

@ -49,6 +49,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cctype>
#include <cerrno>
#include <sstream>
#include <climits>

View File

@ -783,7 +783,7 @@ struct FlowmapWorker
int depth = 0;
for (auto label : labels)
depth = max(depth, label.second);
log("Mapped to %zu LUTs with maximum depth %d.\n", lut_nodes.size(), depth);
log("Mapped to %d LUTs with maximum depth %d.\n", GetSize(lut_nodes), depth);
if (debug)
{
@ -1195,7 +1195,7 @@ struct FlowmapWorker
bool relax_depth_for_bound(bool first, int depth_bound, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> &lut_critical_outputs)
{
size_t initial_count = lut_nodes.size();
int initial_count = GetSize(lut_nodes);
for (auto node : lut_nodes)
{
@ -1215,7 +1215,7 @@ struct FlowmapWorker
if (potentials.empty())
{
log(" Relaxed to %zu (+%zu) LUTs.\n", lut_nodes.size(), lut_nodes.size() - initial_count);
log(" Relaxed to %d (+%d) LUTs.\n", GetSize(lut_nodes), GetSize(lut_nodes) - initial_count);
if (!first && break_num == 1)
{
log(" Design fully relaxed.\n");
@ -1419,9 +1419,9 @@ struct FlowmapWorker
lut_area += lut_table.size();
if ((int)input_nodes.size() >= minlut)
log(" Packed into a %zu-LUT %s.%s.\n", input_nodes.size(), log_id(module), log_id(lut));
log(" Packed into a %d-LUT %s.%s.\n", GetSize(input_nodes), log_id(module), log_id(lut));
else
log(" Packed into a %zu-LUT %s.%s (implemented as %d-LUT).\n", input_nodes.size(), log_id(module), log_id(lut), minlut);
log(" Packed into a %d-LUT %s.%s (implemented as %d-LUT).\n", GetSize(input_nodes), log_id(module), log_id(lut), minlut);
}
for (auto node : mapped_nodes)

View File

@ -23,6 +23,7 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#define COST_DMUX 90
#define COST_MUX2 100
#define COST_MUX4 220
#define COST_MUX8 460
@ -57,6 +58,13 @@ struct MuxcoverWorker
bool use_mux8;
bool use_mux16;
bool nodecode;
bool nopartial;
int cost_dmux;
int cost_mux2;
int cost_mux4;
int cost_mux8;
int cost_mux16;
MuxcoverWorker(Module *module) : module(module), sigmap(module)
{
@ -64,9 +72,32 @@ struct MuxcoverWorker
use_mux8 = false;
use_mux16 = false;
nodecode = false;
nopartial = false;
cost_dmux = COST_DMUX;
cost_mux2 = COST_MUX2;
cost_mux4 = COST_MUX4;
cost_mux8 = COST_MUX8;
cost_mux16 = COST_MUX16;
decode_mux_counter = 0;
}
bool xcmp(std::initializer_list<SigBit> list)
{
auto cursor = list.begin(), end = list.end();
log_assert(cursor != end);
SigBit tmp = *(cursor++);
while (cursor != end) {
SigBit bit = *(cursor++);
if (bit == State::Sx)
continue;
if (tmp == State::Sx)
tmp = bit;
if (bit != tmp)
return false;
}
return true;
}
void treeify()
{
pool<SigBit> roots;
@ -124,13 +155,22 @@ struct MuxcoverWorker
log(" Finished treeification: Found %d trees.\n", GetSize(tree_list));
}
bool follow_muxtree(SigBit &ret_bit, tree_t &tree, SigBit bit, const char *path)
bool follow_muxtree(SigBit &ret_bit, tree_t &tree, SigBit bit, const char *path, bool first_layer = true)
{
if (*path) {
if (tree.muxes.count(bit) == 0)
if (tree.muxes.count(bit) == 0) {
if (first_layer || nopartial)
return false;
while (path[0] && path[1])
path++;
if (path[0] == 'S')
ret_bit = State::Sx;
else
ret_bit = bit;
return true;
}
char port_name[3] = {'\\', *path, 0};
return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1);
return follow_muxtree(ret_bit, tree, sigmap(tree.muxes.at(bit)->getPort(port_name)), path+1, false);
} else {
ret_bit = bit;
return true;
@ -139,7 +179,7 @@ struct MuxcoverWorker
int prepare_decode_mux(SigBit &A, SigBit B, SigBit sel, SigBit bit)
{
if (A == B)
if (A == B || sel == State::Sx)
return 0;
tuple<SigBit, SigBit, SigBit> key(A, B, sel);
@ -157,7 +197,10 @@ struct MuxcoverWorker
if (std::get<2>(entry))
return 0;
return COST_MUX2 / GetSize(std::get<1>(entry));
if (A == State::Sx || B == State::Sx)
return 0;
return cost_dmux / GetSize(std::get<1>(entry));
}
void implement_decode_mux(SigBit ctrl_bit)
@ -174,10 +217,33 @@ struct MuxcoverWorker
implement_decode_mux(std::get<0>(key));
implement_decode_mux(std::get<1>(key));
if (std::get<0>(key) == State::Sx) {
module->addBufGate(NEW_ID, std::get<1>(key), ctrl_bit);
} else if (std::get<1>(key) == State::Sx) {
module->addBufGate(NEW_ID, std::get<0>(key), ctrl_bit);
} else {
module->addMuxGate(NEW_ID, std::get<0>(key), std::get<1>(key), std::get<2>(key), ctrl_bit);
std::get<2>(entry) = true;
decode_mux_counter++;
}
std::get<2>(entry) = true;
}
void find_best_covers(tree_t &tree, const vector<SigBit> &bits)
{
for (auto bit : bits)
find_best_cover(tree, bit);
}
int sum_best_covers(tree_t &tree, const vector<SigBit> &bits)
{
int sum = 0;
for (auto bit : pool<SigBit>(bits.begin(), bits.end())) {
int cost = tree.newmuxes.at(bit).cost;
log_debug(" Best cost for %s: %d\n", log_signal(bit), cost);
sum += cost;
}
return sum;
}
int find_best_cover(tree_t &tree, SigBit bit)
{
@ -209,9 +275,13 @@ struct MuxcoverWorker
mux.inputs.push_back(B);
mux.selects.push_back(S1);
mux.cost += COST_MUX2;
mux.cost += find_best_cover(tree, A);
mux.cost += find_best_cover(tree, B);
find_best_covers(tree, mux.inputs);
log_debug(" Decode cost for mux2 at %s: %d\n", log_signal(bit), mux.cost);
mux.cost += cost_mux2;
mux.cost += sum_best_covers(tree, mux.inputs);
log_debug(" Cost of mux2 at %s: %d\n", log_signal(bit), mux.cost);
best_mux = mux;
}
@ -229,7 +299,7 @@ struct MuxcoverWorker
ok = ok && follow_muxtree(S2, tree, bit, "BS");
if (nodecode)
ok = ok && S1 == S2;
ok = ok && xcmp({S1, S2});
ok = ok && follow_muxtree(T1, tree, bit, "S");
@ -247,13 +317,15 @@ struct MuxcoverWorker
mux.selects.push_back(S1);
mux.selects.push_back(T1);
mux.cost += COST_MUX4;
mux.cost += find_best_cover(tree, A);
mux.cost += find_best_cover(tree, B);
mux.cost += find_best_cover(tree, C);
mux.cost += find_best_cover(tree, D);
find_best_covers(tree, mux.inputs);
log_debug(" Decode cost for mux4 at %s: %d\n", log_signal(bit), mux.cost);
if (best_mux.cost > mux.cost)
mux.cost += cost_mux4;
mux.cost += sum_best_covers(tree, mux.inputs);
log_debug(" Cost of mux4 at %s: %d\n", log_signal(bit), mux.cost);
if (best_mux.cost >= mux.cost)
best_mux = mux;
}
}
@ -277,13 +349,13 @@ struct MuxcoverWorker
ok = ok && follow_muxtree(S4, tree, bit, "BBS");
if (nodecode)
ok = ok && S1 == S2 && S2 == S3 && S3 == S4;
ok = ok && xcmp({S1, S2, S3, S4});
ok = ok && follow_muxtree(T1, tree, bit, "AS");
ok = ok && follow_muxtree(T2, tree, bit, "BS");
if (nodecode)
ok = ok && T1 == T2;
ok = ok && xcmp({T1, T2});
ok = ok && follow_muxtree(U1, tree, bit, "S");
@ -310,17 +382,15 @@ struct MuxcoverWorker
mux.selects.push_back(T1);
mux.selects.push_back(U1);
mux.cost += COST_MUX8;
mux.cost += find_best_cover(tree, A);
mux.cost += find_best_cover(tree, B);
mux.cost += find_best_cover(tree, C);
mux.cost += find_best_cover(tree, D);
mux.cost += find_best_cover(tree, E);
mux.cost += find_best_cover(tree, F);
mux.cost += find_best_cover(tree, G);
mux.cost += find_best_cover(tree, H);
find_best_covers(tree, mux.inputs);
log_debug(" Decode cost for mux8 at %s: %d\n", log_signal(bit), mux.cost);
if (best_mux.cost > mux.cost)
mux.cost += cost_mux8;
mux.cost += sum_best_covers(tree, mux.inputs);
log_debug(" Cost of mux8 at %s: %d\n", log_signal(bit), mux.cost);
if (best_mux.cost >= mux.cost)
best_mux = mux;
}
}
@ -356,7 +426,7 @@ struct MuxcoverWorker
ok = ok && follow_muxtree(S8, tree, bit, "BBBS");
if (nodecode)
ok = ok && S1 == S2 && S2 == S3 && S3 == S4 && S4 == S5 && S5 == S6 && S6 == S7 && S7 == S8;
ok = ok && xcmp({S1, S2, S3, S4, S5, S6, S7, S8});
ok = ok && follow_muxtree(T1, tree, bit, "AAS");
ok = ok && follow_muxtree(T2, tree, bit, "ABS");
@ -364,13 +434,13 @@ struct MuxcoverWorker
ok = ok && follow_muxtree(T4, tree, bit, "BBS");
if (nodecode)
ok = ok && T1 == T2 && T2 == T3 && T3 == T4;
ok = ok && xcmp({T1, T2, T3, T4});
ok = ok && follow_muxtree(U1, tree, bit, "AS");
ok = ok && follow_muxtree(U2, tree, bit, "BS");
if (nodecode)
ok = ok && U1 == U2;
ok = ok && xcmp({U1, U2});
ok = ok && follow_muxtree(V1, tree, bit, "S");
@ -414,25 +484,15 @@ struct MuxcoverWorker
mux.selects.push_back(U1);
mux.selects.push_back(V1);
mux.cost += COST_MUX16;
mux.cost += find_best_cover(tree, A);
mux.cost += find_best_cover(tree, B);
mux.cost += find_best_cover(tree, C);
mux.cost += find_best_cover(tree, D);
mux.cost += find_best_cover(tree, E);
mux.cost += find_best_cover(tree, F);
mux.cost += find_best_cover(tree, G);
mux.cost += find_best_cover(tree, H);
mux.cost += find_best_cover(tree, I);
mux.cost += find_best_cover(tree, J);
mux.cost += find_best_cover(tree, K);
mux.cost += find_best_cover(tree, L);
mux.cost += find_best_cover(tree, M);
mux.cost += find_best_cover(tree, N);
mux.cost += find_best_cover(tree, O);
mux.cost += find_best_cover(tree, P);
find_best_covers(tree, mux.inputs);
log_debug(" Decode cost for mux16 at %s: %d\n", log_signal(bit), mux.cost);
if (best_mux.cost > mux.cost)
mux.cost += cost_mux16;
mux.cost += sum_best_covers(tree, mux.inputs);
log_debug(" Cost of mux16 at %s: %d\n", log_signal(bit), mux.cost);
if (best_mux.cost >= mux.cost)
best_mux = mux;
}
}
@ -528,6 +588,7 @@ struct MuxcoverWorker
void treecover(tree_t &tree)
{
int count_muxes_by_type[4] = {0, 0, 0, 0};
log_debug(" Searching for best cover for tree at %s.\n", log_signal(tree.root));
find_best_cover(tree, tree.root);
implement_best_cover(tree, tree.root, count_muxes_by_type);
log(" Replaced tree at %s: %d MUX2, %d MUX4, %d MUX8, %d MUX16\n", log_signal(tree.root),
@ -544,12 +605,13 @@ struct MuxcoverWorker
log(" Covering trees:\n");
// pre-fill cache of decoder muxes
if (!nodecode)
if (!nodecode) {
log_debug(" Populating cache of decoder muxes.\n");
for (auto &tree : tree_list) {
find_best_cover(tree, tree.root);
tree.newmuxes.clear();
}
}
for (auto &tree : tree_list)
treecover(tree);
@ -569,15 +631,25 @@ struct MuxcoverPass : public Pass {
log("\n");
log("Cover trees of $_MUX_ cells with $_MUX{4,8,16}_ cells\n");
log("\n");
log(" -mux4, -mux8, -mux16\n");
log(" Use the specified types of MUXes. If none of those options are used,\n");
log(" the effect is the same as if all of them where used.\n");
log(" -mux4[=cost], -mux8[=cost], -mux16[=cost]\n");
log(" Use the specified types of MUXes (with optional integer costs). If none\n");
log(" of these options are given, the effect is the same as if all of them are.\n");
log(" Default costs: $_MUX_ = %d, $_MUX4_ = %d,\n", COST_MUX2, COST_MUX4);
log(" $_MUX8_ = %d, $_MUX16_ = %d\n", COST_MUX8, COST_MUX16);
log("\n");
log(" -dmux=cost\n");
log(" Use the specified cost for $_MUX_ cells used in decoders.\n");
log(" Default cost: %d\n", COST_DMUX);
log("\n");
log(" -nodecode\n");
log(" Do not insert decoder logic. This reduces the number of possible\n");
log(" substitutions, but guarantees that the resulting circuit is not\n");
log(" less efficient than the original circuit.\n");
log("\n");
log(" -nopartial\n");
log(" Do not consider mappings that use $_MUX<N>_ to select from less\n");
log(" than <N> different signals.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
@ -587,26 +659,52 @@ struct MuxcoverPass : public Pass {
bool use_mux8 = false;
bool use_mux16 = false;
bool nodecode = false;
bool nopartial = false;
int cost_dmux = COST_DMUX;
int cost_mux4 = COST_MUX4;
int cost_mux8 = COST_MUX8;
int cost_mux16 = COST_MUX16;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-mux4") {
const auto &arg = args[argidx];
if (arg.size() >= 5 && arg.substr(0,5) == "-mux4") {
use_mux4 = true;
if (arg.size() > 5) {
if (arg[5] != '=') break;
cost_mux4 = atoi(arg.substr(6).c_str());
}
continue;
}
if (args[argidx] == "-mux8") {
if (arg.size() >= 5 && arg.substr(0,5) == "-mux8") {
use_mux8 = true;
if (arg.size() > 5) {
if (arg[5] != '=') break;
cost_mux8 = atoi(arg.substr(6).c_str());
}
continue;
}
if (args[argidx] == "-mux16") {
if (arg.size() >= 6 && arg.substr(0,6) == "-mux16") {
use_mux16 = true;
if (arg.size() > 6) {
if (arg[6] != '=') break;
cost_mux16 = atoi(arg.substr(7).c_str());
}
continue;
}
if (args[argidx] == "-nodecode") {
if (arg.size() >= 6 && arg.substr(0,6) == "-dmux=") {
cost_dmux = atoi(arg.substr(6).c_str());
continue;
}
if (arg == "-nodecode") {
nodecode = true;
continue;
}
if (arg == "-nopartial") {
nopartial = true;
continue;
}
break;
}
extra_args(args, argidx, design);
@ -623,7 +721,12 @@ struct MuxcoverPass : public Pass {
worker.use_mux4 = use_mux4;
worker.use_mux8 = use_mux8;
worker.use_mux16 = use_mux16;
worker.cost_dmux = cost_dmux;
worker.cost_mux4 = cost_mux4;
worker.cost_mux8 = cost_mux8;
worker.cost_mux16 = cost_mux16;
worker.nodecode = nodecode;
worker.nopartial = nopartial;
worker.run();
}
}

View File

@ -293,10 +293,22 @@ struct ShregmapWorker
if (opts.init || sigbit_init.count(q_bit) == 0)
{
if (sigbit_chain_next.count(d_bit)) {
auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell));
if (!r.second) {
// Insertion not successful means that d_bit is already
// connected to another register, thus mark it as a
// non chain user ...
sigbit_with_non_chain_users.insert(d_bit);
} else
sigbit_chain_next[d_bit] = cell;
// ... and clone d_bit into another wire, and use that
// wire as a different key in the d_bit-to-cell dictionary
// so that it can be identified as another chain
// (omitting this common flop)
// Link: https://github.com/YosysHQ/yosys/pull/1085
Wire *wire = module->addWire(NEW_ID);
module->connect(wire, d_bit);
sigmap.add(wire, d_bit);
sigbit_chain_next.insert(std::make_pair(wire, cell));
}
sigbit_chain_prev[q_bit] = cell;
continue;
@ -605,6 +617,11 @@ struct ShregmapPass : public Pass {
log("\n");
log(" -tech greenpak4\n");
log(" map to greenpak4 shift registers.\n");
log(" this option also implies -clkpol pos -zinit\n");
log("\n");
log(" -tech xilinx\n");
log(" map to xilinx dynamic-length shift registers.\n");
log(" this option also implies -params -init\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE

View File

@ -50,7 +50,7 @@ struct AnlogicDetermineInitPass : public Pass {
extra_args(args, args.size(), design);
size_t cnt = 0;
int cnt = 0;
for (auto module : design->selected_modules())
{
for (auto cell : module->selected_cells())
@ -65,7 +65,7 @@ struct AnlogicDetermineInitPass : public Pass {
}
}
}
log_header(design, "Updated %lu cells with determined init value.\n", cnt);
log_header(design, "Updated %d cells with determined init value.\n", cnt);
}
} AnlogicDetermineInitPass;

View File

@ -69,7 +69,7 @@ struct AnlogicEqnPass : public Pass {
extra_args(args, args.size(), design);
size_t cnt = 0;
int cnt = 0;
for (auto module : design->selected_modules())
{
for (auto cell : module->selected_cells())
@ -106,7 +106,7 @@ struct AnlogicEqnPass : public Pass {
}
}
}
log_header(design, "Updated %lu of AL_MAP_LUT* elements with equation.\n", cnt);
log_header(design, "Updated %d of AL_MAP_LUT* elements with equation.\n", cnt);
}
} AnlogicEqnPass;

View File

@ -50,20 +50,21 @@ module _80_ecp5_alu (A, B, CI, BI, X, Y, CO);
wire [Y_WIDTH2-1:0] AA = A_buf;
wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH2-1:0] BX = B_buf;
wire [Y_WIDTH2-1:0] C = {CO, CI};
wire [Y_WIDTH2-1:0] FCO, Y1;
genvar i;
generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
CCU2C #(
.INIT0(16'b0110011010101010),
.INIT1(16'b0110011010101010),
.INIT0(16'b1001011010101010),
.INIT1(16'b1001011010101010),
.INJECT1_0("NO"),
.INJECT1_1("NO")
) ccu2c_i (
.CIN(C[i]),
.A0(AA[i]), .B0(BB[i]), .C0(1'b0), .D0(1'b1),
.A1(AA[i+1]), .B1(BB[i+1]), .C1(1'b0), .D1(1'b1),
.A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),
.A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),
.S0(Y[i]), .S1(Y1[i]),
.COUT(FCO[i])
);

View File

@ -47,8 +47,59 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
// TODO: Diamond flip-flops
// module FD1P3AX(); endmodule
// module FD1P3AY(); endmodule
// module FD1P3BX(); endmodule
// module FD1P3DX(); endmodule
// module FD1P3IX(); endmodule
// module FD1P3JX(); endmodule
// module FD1S3AX(); endmodule
// module FD1S3AY(); endmodule
module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
// module FL1P3AY(); endmodule
// module FL1P3AZ(); endmodule
// module FL1P3BX(); endmodule
// module FL1P3DX(); endmodule
// module FL1P3IY(); endmodule
// module FL1P3JY(); endmodule
// module FL1S3AX(); endmodule
// module FL1S3AY(); endmodule
// Diamond I/O buffers
module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(I), .O(O)); endmodule
module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I)); endmodule
module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(O), .I(I), .T(T)); endmodule
module OBCO (input I, output OT, OC); OLVDS _TECHMAP_REPLACE_ (.A(I), .Z(OT), .ZN(OC)); endmodule
module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.B(B), .I(I), .O(O), .T(T)); endmodule
module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.B(A), .O(Z)); endmodule
module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.B(Z), .I(A)); endmodule
// Diamond I/O registers
module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
// TODO: Diamond I/O latches
// module IFS1S1B(input PD, D, SCLK, output Q); endmodule
// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
// module IFS1S1J(input CD, D, SCLK, output Q); endmodule
`ifndef NO_LUT
module \$lut (A, Y);

View File

@ -250,18 +250,6 @@ module TRELLIS_FF(input CLK, LSR, CE, DI, M, output reg Q);
endgenerate
endmodule
// ---------------------------------------
module OBZ(input I, T, output O);
assign O = T ? 1'bz : I;
endmodule
// ---------------------------------------
module IB(input I, output O);
assign O = I;
endmodule
// ---------------------------------------
(* keep *)
module TRELLIS_IO(
@ -293,19 +281,6 @@ endmodule
// ---------------------------------------
module OB(input I, output O);
assign O = I;
endmodule
// ---------------------------------------
module BB(input I, T, output O, inout B);
assign B = T ? 1'bz : I;
assign O = B;
endmodule
// ---------------------------------------
module INV(input A, output Z);
assign Z = !A;
endmodule
@ -558,19 +533,56 @@ module DP16KD(
parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
endmodule
// For Diamond compatibility, FIXME: add all Diamond flipflop mappings
module FD1S3BX(input PD, D, CK, output Q);
TRELLIS_FF #(
.GSR("DISABLED"),
.CEMUX("1"),
.CLKMUX("CLK"),
.LSRMUX("LSR"),
.REGSET("SET"),
.SRMODE("ASYNC")
) tff_i (
.CLK(CK),
.LSR(PD),
.DI(D),
.Q(Q)
);
endmodule
// TODO: Diamond flip-flops
// module FD1P3AX(); endmodule
// module FD1P3AY(); endmodule
// module FD1P3BX(); endmodule
// module FD1P3DX(); endmodule
// module FD1P3IX(); endmodule
// module FD1P3JX(); endmodule
// module FD1S3AX(); endmodule
// module FD1S3AY(); endmodule
module FD1S3BX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
module FD1S3DX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3IX(input CD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(CD), .DI(D), .Q(Q)); endmodule
module FD1S3JX(input PD, D, CK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(CK), .LSR(PD), .DI(D), .Q(Q)); endmodule
// module FL1P3AY(); endmodule
// module FL1P3AZ(); endmodule
// module FL1P3BX(); endmodule
// module FL1P3DX(); endmodule
// module FL1P3IY(); endmodule
// module FL1P3JY(); endmodule
// module FL1S3AX(); endmodule
// module FL1S3AY(); endmodule
// Diamond I/O buffers
module IB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
module IBPU (input I, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
module IBPD (input I, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("INPUT")) tio (.B(I), .O(O)); endmodule
module OB (input I, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I)); endmodule
module OBZ (input I, T, output O); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
module OBZPU(input I, T, output O); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
module OBZPD(input I, T, output O); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(O), .I(I), .T(T)); endmodule
module OBCO (input I, output OT, OC); OLVDS olvds (.A(I), .Z(OT), .ZN(OC)); endmodule
module BB (input I, T, output O, inout B); (* PULLMODE="NONE" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
module BBPU (input I, T, output O, inout B); (* PULLMODE="UP" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
module BBPD (input I, T, output O, inout B); (* PULLMODE="DOWN" *) TRELLIS_IO #(.DIR("BIDIR")) tio (.B(B), .I(I), .O(O), .T(T)); endmodule
module ILVDS(input A, AN, output Z); TRELLIS_IO #(.DIR("INPUT")) tio (.B(A), .O(Z)); endmodule
module OLVDS(input A, output Z, ZN); TRELLIS_IO #(.DIR("OUTPUT")) tio (.B(Z), .I(A)); endmodule
// Diamond I/O registers
module IFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module IFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3BX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3DX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3IX(input CD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule
module OFS1P3JX(input PD, D, SP, SCLK, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) tff (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule
// TODO: Diamond I/O latches
// module IFS1S1B(input PD, D, SCLK, output Q); endmodule
// module IFS1S1D(input CD, D, SCLK, output Q); endmodule
// module IFS1S1I(input PD, D, SCLK, output Q); endmodule
// module IFS1S1J(input CD, D, SCLK, output Q); endmodule

View File

@ -76,7 +76,7 @@ struct SynthEcp5Pass : public ScriptPass
log(" -nodram\n");
log(" do not use distributed RAM cells in output netlist\n");
log("\n");
log(" -nomux\n");
log(" -nowidelut\n");
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -abc2\n");
@ -93,7 +93,7 @@ struct SynthEcp5Pass : public ScriptPass
}
string top_opt, blif_file, edif_file, json_file;
bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr;
bool noccu2, nodffe, nobram, nodram, nowidelut, flatten, retime, abc2, vpr;
void clear_flags() YS_OVERRIDE
{
@ -105,7 +105,7 @@ struct SynthEcp5Pass : public ScriptPass
nodffe = false;
nobram = false;
nodram = false;
nomux = false;
nowidelut = false;
flatten = true;
retime = false;
abc2 = false;
@ -172,8 +172,8 @@ struct SynthEcp5Pass : public ScriptPass
nodram = true;
continue;
}
if (args[argidx] == "-nomux") {
nomux = true;
if (args[argidx] == "-nowidelut" || args[argidx] == "-nomux") {
nowidelut = true;
continue;
}
if (args[argidx] == "-abc2") {
@ -264,7 +264,7 @@ struct SynthEcp5Pass : public ScriptPass
run("abc", " (only if -abc2)");
}
run("techmap -map +/ecp5/latches_map.v");
if (nomux)
if (nowidelut)
run("abc -lut 4 -dress");
else
run("abc -lut 4:7 -dress");

View File

@ -50,7 +50,7 @@ struct DetermineInitPass : public Pass {
extra_args(args, args.size(), design);
size_t cnt = 0;
int cnt = 0;
for (auto module : design->selected_modules())
{
for (auto cell : module->selected_cells())
@ -65,7 +65,7 @@ struct DetermineInitPass : public Pass {
}
}
}
log_header(design, "Updated %lu cells with determined init value.\n", cnt);
log_header(design, "Updated %d cells with determined init value.\n", cnt);
}
} DetermineInitPass;

View File

@ -973,6 +973,30 @@ parameter RGB1_CURRENT = "0b000000";
parameter RGB2_CURRENT = "0b000000";
endmodule
(* blackbox *)
module SB_LED_DRV_CUR(
input EN,
output LEDPU
);
endmodule
(* blackbox *)
module SB_RGB_DRV(
input RGBLEDEN,
input RGB0PWM,
input RGB1PWM,
input RGB2PWM,
input RGBPU,
output RGB0,
output RGB1,
output RGB2
);
parameter CURRENT_MODE = "0b0";
parameter RGB0_CURRENT = "0b000000";
parameter RGB1_CURRENT = "0b000000";
parameter RGB2_CURRENT = "0b000000";
endmodule
(* blackbox *)
module SB_I2C(
input SBCLKI,

View File

@ -74,7 +74,7 @@ static void run_ice40_unlut(Module *module)
}
struct Ice40UnlutPass : public Pass {
Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: perform simple optimizations") { }
Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SB_LUT4 cells to $lut cells") { }
void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|

View File

@ -278,6 +278,23 @@ module FDPE_1 (output reg Q, input C, CE, D, PRE);
always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
endmodule
module RAM32X1D (
output DPO, SPO,
input D, WCLK, WE,
input A0, A1, A2, A3, A4,
input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
);
parameter INIT = 32'h0;
parameter IS_WCLK_INVERTED = 1'b0;
wire [4:0] a = {A4, A3, A2, A1, A0};
wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
reg [31:0] mem = INIT;
assign SPO = mem[a];
assign DPO = mem[dpra];
wire clk = WCLK ^ IS_WCLK_INVERTED;
always @(posedge clk) if (WE) mem[a] <= D;
endmodule
module RAM64X1D (
output DPO, SPO,
input D, WCLK, WE,

View File

@ -116,11 +116,11 @@ function xtract_cell_decl()
xtract_cell_decl PS7 "(* keep *)"
xtract_cell_decl PULLDOWN
xtract_cell_decl PULLUP
xtract_cell_decl RAM128X1D
#xtract_cell_decl RAM128X1D
xtract_cell_decl RAM128X1S
xtract_cell_decl RAM256X1S
xtract_cell_decl RAM32M
xtract_cell_decl RAM32X1D
#xtract_cell_decl RAM32X1D
xtract_cell_decl RAM32X1S
xtract_cell_decl RAM32X1S_1
xtract_cell_decl RAM32X2S

View File

@ -3655,17 +3655,6 @@ module PULLUP (...);
output O;
endmodule
module RAM128X1D (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output DPO, SPO;
input [6:0] A;
input [6:0] DPRA;
input D;
input WCLK;
input WE;
endmodule
module RAM128X1S (...);
parameter [127:0] INIT = 128'h00000000000000000000000000000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@ -3705,13 +3694,6 @@ module RAM32M (...);
input WE;
endmodule
module RAM32X1D (...);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;
output DPO, SPO;
input A0, A1, A2, A3, A4, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, WCLK, WE;
endmodule
module RAM32X1S (...);
parameter [31:0] INIT = 32'h00000000;
parameter [0:0] IS_WCLK_INVERTED = 1'b0;

View File

@ -1,4 +1,17 @@
bram $__XILINX_RAM32X1D
init 1
abits 5
dbits 1
groups 2
ports 1 1
wrmode 0 1
enable 0 1
transp 0 0
clocks 0 1
clkpol 0 2
endbram
bram $__XILINX_RAM64X1D
init 1
abits 6
@ -25,6 +38,13 @@ bram $__XILINX_RAM128X1D
clkpol 0 2
endbram
match $__XILINX_RAM32X1D
min bits 3
min wports 1
make_outreg
or_next_if_better
endmatch
match $__XILINX_RAM64X1D
min bits 5
min wports 1

View File

@ -1,4 +1,38 @@
module \$__XILINX_RAM32X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
parameter [31:0] INIT = 32'bx;
parameter CLKPOL2 = 1;
input CLK1;
input [4:0] A1ADDR;
output A1DATA;
input [4:0] B1ADDR;
input B1DATA;
input B1EN;
RAM32X1D #(
.INIT(INIT),
.IS_WCLK_INVERTED(!CLKPOL2)
) _TECHMAP_REPLACE_ (
.DPRA0(A1ADDR[0]),
.DPRA1(A1ADDR[1]),
.DPRA2(A1ADDR[2]),
.DPRA3(A1ADDR[3]),
.DPRA4(A1ADDR[4]),
.DPO(A1DATA),
.A0(B1ADDR[0]),
.A1(B1ADDR[1]),
.A2(B1ADDR[2]),
.A3(B1ADDR[3]),
.A4(B1ADDR[4]),
.D(B1DATA),
.WCLK(CLK1),
.WE(B1EN)
);
endmodule
module \$__XILINX_RAM64X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
parameter [63:0] INIT = 64'bx;
parameter CLKPOL2 = 1;

View File

@ -42,8 +42,9 @@ struct SynthXilinxPass : public ScriptPass
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
log(" -arch {xcup|xcu|xc7|xc6s}\n");
log(" -family {xcup|xcu|xc7|xc6s}\n");
log(" run synthesis for the specified Xilinx architecture\n");
log(" generate the synthesis netlist for the specified family.\n");
log(" default: xc7\n");
log("\n");
log(" -edif <file>\n");
@ -67,6 +68,12 @@ struct SynthXilinxPass : public ScriptPass
log(" -nosrl\n");
log(" disable inference of shift registers\n");
log("\n");
log(" -nocarry\n");
log(" do not use XORCY/MUXCY/CARRY4 cells in output netlist\n");
log("\n");
log(" -nowidelut\n");
log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
log(" from label is synonymous to 'begin', and empty to label is\n");
@ -84,8 +91,8 @@ struct SynthXilinxPass : public ScriptPass
log("\n");
}
std::string top_opt, edif_file, blif_file, arch;
bool flatten, retime, vpr, nobram, nodram, nosrl;
std::string top_opt, edif_file, blif_file, family;
bool flatten, retime, vpr, nobram, nodram, nosrl, nocarry, nowidelut;
void clear_flags() YS_OVERRIDE
{
@ -98,7 +105,9 @@ struct SynthXilinxPass : public ScriptPass
nobram = false;
nodram = false;
nosrl = false;
arch = "xc7";
nocarry = false;
nowidelut = false;
family = "xc7";
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
@ -113,8 +122,8 @@ struct SynthXilinxPass : public ScriptPass
top_opt = "-top " + args[++argidx];
continue;
}
if (args[argidx] == "-arch" && argidx+1 < args.size()) {
arch = args[++argidx];
if ((args[argidx] == "-family" || args[argidx] == "-arch") && argidx+1 < args.size()) {
family = args[++argidx];
continue;
}
if (args[argidx] == "-edif" && argidx+1 < args.size()) {
@ -141,6 +150,14 @@ struct SynthXilinxPass : public ScriptPass
retime = true;
continue;
}
if (args[argidx] == "-nocarry") {
nocarry = true;
continue;
}
if (args[argidx] == "-nowidelut") {
nowidelut = true;
continue;
}
if (args[argidx] == "-vpr") {
vpr = true;
continue;
@ -161,8 +178,8 @@ struct SynthXilinxPass : public ScriptPass
}
extra_args(args, argidx, design);
if (arch != "xcup" && arch != "xcu" && arch != "xc7" && arch != "xc6s")
log_cmd_error("Invalid Xilinx -arch setting: %s\n", arch.c_str());
if (family != "xcup" && family != "xcu" && family != "xc7" && family != "xc6s")
log_cmd_error("Invalid Xilinx -family setting: %s\n", family.c_str());
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
@ -229,11 +246,6 @@ struct SynthXilinxPass : public ScriptPass
run("dff2dffe");
run("opt -full");
if (!vpr || help_mode)
run("techmap -map +/xilinx/arith_map.v");
else
run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
if (!nosrl || help_mode) {
// shregmap operates on bit-level flops, not word-level,
// so break those down here
@ -242,7 +254,15 @@ struct SynthXilinxPass : public ScriptPass
run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
}
run("techmap");
if (help_mode)
run("techmap -map +/techmap.v [-map +/xilinx/arith_map.v]", "(skip if '-nocarry')");
else if (!nocarry) {
if (!vpr)
run("techmap -map +/techmap.v -map +/xilinx/arith_map.v");
else
run("techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
}
run("opt -fast");
}
@ -253,7 +273,9 @@ struct SynthXilinxPass : public ScriptPass
if (check_label("map_luts")) {
if (help_mode)
run("abc -luts 2:2,3,6:5,10,20 [-dff]");
run("abc -luts 2:2,3,6:5[,10,20] [-dff]", "(skip if 'nowidelut', only for '-retime')");
else if (nowidelut)
run("abc -luts 2:2,3,6:5" + string(retime ? " -dff" : ""));
else
run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
run("clean");

View File

@ -1,2 +1 @@
*.log
*.out
/*_ref.v

View File

@ -1,3 +0,0 @@
aig 3 2 0 1 1
6


View File

@ -3,3 +3,6 @@ aag 3 2 0 1 1
4
6
6 2 4
i0 pi0
i1 pi1
o0 po0

View File

@ -0,0 +1,5 @@
aig 3 2 0 1 1
6
i0 pi0
i1 pi1
o0 po0

View File

@ -1,3 +1,5 @@
aag 1 1 0 1 0
2
2
i0 pi0
o0 po0

View File

@ -1,2 +1,4 @@
aig 1 1 0 1 0
2
i0 pi0
o0 po0

View File

@ -1,3 +1,4 @@
aag 1 0 1 0 0 1
2 3
2
b0 po0

View File

@ -1,3 +1,4 @@
aig 1 0 1 0 0 1
3
2
b0 po0

View File

@ -6,3 +6,4 @@ aag 5 1 1 0 3 1
8 4 2
10 9 7
b0 AIGER_NEVER
i0 po0

View File

@ -1,4 +1,5 @@
aig 5 1 1 0 3 1
10
4
b0 AIGER_NEVER
i0 po0
b0 AIGER_NEVER

View File

@ -1,2 +1,3 @@
aag 0 0 0 1 0
0
o0 po0

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