mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-22 00:26:40 +00:00
Yosys sync
This commit is contained in:
commit
4356eae4c9
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,128 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at contact@yosyshq.com and/or
|
||||
claire@clairexen.net.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
9
Makefile
9
Makefile
|
@ -1050,15 +1050,12 @@ docs/source/cell/word_add.rst: $(TARGETS) $(EXTRA_TARGETS)
|
|||
docs/source/generated/cells.json: docs/source/generated $(TARGETS) $(EXTRA_TARGETS)
|
||||
$(Q) ./$(PROGRAM_PREFIX)yosys -p 'help -dump-cells-json $@'
|
||||
|
||||
PHONY: docs/gen docs/guidelines docs/usage docs/reqs
|
||||
PHONY: docs/gen docs/usage docs/reqs
|
||||
docs/gen: $(TARGETS)
|
||||
$(Q) $(MAKE) -C docs gen
|
||||
|
||||
DOCS_GUIDELINE_FILES := GettingStarted CodingStyle
|
||||
DOCS_GUIDELINE_SOURCE := $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES))
|
||||
docs/guidelines docs/source/generated: $(DOCS_GUIDELINE_SOURCE)
|
||||
docs/source/generated:
|
||||
$(Q) mkdir -p docs/source/generated
|
||||
$(Q) cp -f $(DOCS_GUIDELINE_SOURCE) docs/source/generated
|
||||
|
||||
# some commands return an error and print the usage text to stderr
|
||||
define DOC_USAGE_STDERR
|
||||
|
@ -1088,7 +1085,7 @@ docs/reqs:
|
|||
$(Q) $(MAKE) -C docs reqs
|
||||
|
||||
.PHONY: docs/prep
|
||||
docs/prep: docs/source/cmd/abc.rst docs/source/generated/cells.json docs/gen docs/guidelines docs/usage
|
||||
docs/prep: docs/source/cmd/abc.rst docs/source/generated/cells.json docs/gen docs/usage
|
||||
|
||||
DOC_TARGET ?= html
|
||||
docs: docs/prep
|
||||
|
|
474
README.md
474
README.md
|
@ -1,22 +1,3 @@
|
|||
```
|
||||
yosys -- Yosys Open SYnthesis Suite
|
||||
|
||||
Copyright (C) 2012 - 2024 Claire Xenia Wolf <claire@yosyshq.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.
|
||||
```
|
||||
|
||||
|
||||
yosys – Yosys Open SYnthesis Suite
|
||||
===================================
|
||||
|
||||
|
@ -37,23 +18,21 @@ Third-party software distributed alongside this software
|
|||
is licensed under compatible licenses.
|
||||
Please refer to `abc` and `libs` subdirectories for their license terms.
|
||||
|
||||
|
||||
Web Site and Other Resources
|
||||
============================
|
||||
|
||||
More information and documentation can be found on the Yosys web site:
|
||||
- https://yosyshq.net/yosys/
|
||||
|
||||
The "Documentation" page on the web site contains links to more resources,
|
||||
including a manual that even describes some of the Yosys internals:
|
||||
- https://yosyshq.net/yosys/documentation.html
|
||||
Documentation from this repository is automatically built and available on Read
|
||||
the Docs:
|
||||
- https://yosyshq.readthedocs.io/projects/yosys
|
||||
|
||||
The directory `guidelines` contains additional information
|
||||
for people interested in using the Yosys C++ APIs.
|
||||
|
||||
Users interested in formal verification might want to use the formal verification
|
||||
front-end for Yosys, SymbiYosys:
|
||||
- https://symbiyosys.readthedocs.io/en/latest/
|
||||
- https://github.com/YosysHQ/SymbiYosys
|
||||
Users interested in formal verification might want to use the formal
|
||||
verification front-end for Yosys, SBY:
|
||||
- https://yosyshq.readthedocs.io/projects/sby/
|
||||
- https://github.com/YosysHQ/sby
|
||||
|
||||
|
||||
Installation
|
||||
|
@ -71,9 +50,25 @@ For more information about the difference between Tabby CAD Suite and the OSS CA
|
|||
|
||||
Many Linux distributions also provide Yosys binaries, some more up to date than others. Check with your package manager!
|
||||
|
||||
|
||||
Building from Source
|
||||
====================
|
||||
|
||||
For more details, and instructions for other platforms, check [building from
|
||||
source](https://yosyshq.readthedocs.io/projects/yosys/en/latest/getting_started/installation.html#building-from-source)
|
||||
on Read the Docs.
|
||||
|
||||
When cloning Yosys, some required libraries are included as git submodules. Make
|
||||
sure to call e.g.
|
||||
|
||||
$ git clone --recurse-submodules https://github.com/YosysHQ/yosys.git
|
||||
|
||||
or
|
||||
|
||||
$ git clone https://github.com/YosysHQ/yosys.git
|
||||
$ cd yosys
|
||||
$ git submodule update --init --recursive
|
||||
|
||||
You need a C++ compiler with C++17 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).
|
||||
|
@ -87,58 +82,22 @@ prerequisites for building yosys:
|
|||
graphviz xdot pkg-config python3 libboost-system-dev \
|
||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
||||
|
||||
Similarily, on Mac OS X Homebrew can be used to install dependencies (from within cloned yosys repository):
|
||||
|
||||
$ brew tap Homebrew/bundle && brew bundle
|
||||
|
||||
or MacPorts:
|
||||
|
||||
$ sudo port install bison flex readline gawk libffi \
|
||||
git graphviz pkgconfig python36 boost zlib tcl
|
||||
|
||||
On FreeBSD use the following command to install all prerequisites:
|
||||
|
||||
# pkg install bison flex readline gawk libffi\
|
||||
git graphviz pkgconf python3 python36 tcl-wrapper boost-libs
|
||||
|
||||
On FreeBSD system use gmake instead of make. To run tests use:
|
||||
% MAKE=gmake CC=cc gmake test
|
||||
|
||||
For Cygwin use the following command to install all prerequisites, or select these additional packages:
|
||||
|
||||
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
|
||||
|
||||
The environment variable `CXX` can be used to control the C++ compiler used, or
|
||||
run one of the following:
|
||||
run one of the following to override it:
|
||||
|
||||
$ make config-clang
|
||||
$ make config-gcc
|
||||
|
||||
Note that these will result in `make` ignoring the `CXX` environment variable,
|
||||
unless `CXX` is assigned in the call to make, e.g.
|
||||
The Makefile has many variables influencing the build process. These can be
|
||||
adjusted by modifying the Makefile.conf file which is created at the `make
|
||||
config-...` step (see above), or they can be set by passing an option to the
|
||||
make command directly:
|
||||
|
||||
$ make CXX=$CXX
|
||||
|
||||
The Makefile has many variables influencing the build process. These can be
|
||||
adjusted by modifying the Makefile.conf file which is created at the
|
||||
`make config-...` step (see above), or they can be set by passing an option
|
||||
to the make command directly.
|
||||
|
||||
For example, if you have clang, and (a compatible version of) `ld.lld`
|
||||
available in PATH, it's recommended to speed up incremental builds with
|
||||
lld by enabling LTO:
|
||||
|
||||
$ make ENABLE_LTO=1
|
||||
|
||||
On macOS, LTO requires using clang from homebrew which isn't in PATH
|
||||
rather than xcode clang.
|
||||
|
||||
$ make ENABLE_LTO=1 CXX=$(brew --prefix)/opt/llvm/bin/clang++
|
||||
|
||||
For other compilers and build configurations it might be
|
||||
necessary to make some changes to the config section of the
|
||||
Makefile. It's also an alternative way to set the make variables
|
||||
mentioned above.
|
||||
For other compilers and build configurations it might be necessary to make some
|
||||
changes to the config section of the Makefile. It's also an alternative way to
|
||||
set the make variables mentioned above.
|
||||
|
||||
$ vi Makefile # ..or..
|
||||
$ vi Makefile.conf
|
||||
|
@ -148,10 +107,9 @@ To build Yosys simply type 'make' in this directory.
|
|||
$ make
|
||||
$ sudo make install
|
||||
|
||||
Note that this also downloads, builds and installs ABC (using yosys-abc
|
||||
as executable name).
|
||||
|
||||
Tests are located in the tests subdirectory and can be executed using the test target. Note that you need gawk as well as a recent version of iverilog (i.e. build from git). Then, execute tests via:
|
||||
Tests are located in the tests subdirectory and can be executed using the test
|
||||
target. Note that you need gawk as well as a recent version of iverilog (i.e.
|
||||
build from git). Then, execute tests via:
|
||||
|
||||
$ make test
|
||||
|
||||
|
@ -162,6 +120,7 @@ To use a separate (out-of-tree) build directory, provide a path to the Makefile.
|
|||
|
||||
Out-of-tree builds require a clean source tree.
|
||||
|
||||
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
|
@ -276,367 +235,6 @@ source with another tool such as
|
|||
``verilator --lint-only``.
|
||||
|
||||
|
||||
Unsupported Verilog-2005 Features
|
||||
=================================
|
||||
|
||||
The following Verilog-2005 features are not supported by
|
||||
Yosys and there are currently no plans to add support
|
||||
for them:
|
||||
|
||||
- Non-synthesizable language features as defined in
|
||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||
|
||||
- The ``tri``, ``triand`` and ``trior`` net types
|
||||
|
||||
- The ``config`` and ``disable`` keywords and library map files
|
||||
|
||||
|
||||
Verilog Attributes and non-standard features
|
||||
============================================
|
||||
|
||||
- The ``full_case`` attribute on case statements is supported
|
||||
(also the non-standard ``// synopsys full_case`` directive)
|
||||
|
||||
- The ``parallel_case`` attribute on case statements is supported
|
||||
(also the non-standard ``// synopsys parallel_case`` directive)
|
||||
|
||||
- The ``// synopsys translate_off`` and ``// synopsys translate_on``
|
||||
directives are also supported (but the use of ``` `ifdef .. `endif ```
|
||||
is strongly recommended instead).
|
||||
|
||||
- The ``nomem2reg`` attribute on modules or arrays prohibits the
|
||||
automatic early conversion of arrays to separate registers. This
|
||||
is potentially dangerous. Usually the front-end has good reasons
|
||||
for converting an array to a list of registers. Prohibiting this
|
||||
step will likely result in incorrect synthesis results.
|
||||
|
||||
- The ``mem2reg`` attribute on modules or arrays forces the early
|
||||
conversion of arrays to separate registers.
|
||||
|
||||
- The ``nomeminit`` attribute on modules or arrays prohibits the
|
||||
creation of initialized memories. This effectively puts ``mem2reg``
|
||||
on all memories that are written to in an ``initial`` block and
|
||||
are not ROMs.
|
||||
|
||||
- The ``nolatches`` attribute on modules or always-blocks
|
||||
prohibits the generation of logic-loops for latches. Instead
|
||||
all not explicitly assigned values default to x-bits. This does
|
||||
not affect clocked storage elements such as flip-flops.
|
||||
|
||||
- The ``nosync`` attribute on registers prohibits the generation of a
|
||||
storage element. The register itself will always have all bits set
|
||||
to 'x' (undefined). The variable may only be used as blocking assigned
|
||||
temporary variable within an always block. This is mostly used internally
|
||||
by Yosys to synthesize Verilog functions and access arrays.
|
||||
|
||||
- The ``nowrshmsk`` attribute on a register prohibits the generation of
|
||||
shift-and-mask type circuits for writing to bit slices of that register.
|
||||
|
||||
- The ``onehot`` attribute on wires mark them as one-hot state register. This
|
||||
is used for example for memory port sharing and set by the fsm_map pass.
|
||||
|
||||
- The ``blackbox`` attribute on modules is used to mark empty stub modules
|
||||
that have the same ports as the real thing but do not contain information
|
||||
on the internal configuration. This modules are only used by the synthesis
|
||||
passes to identify input and output ports of cells. The Verilog backend
|
||||
also does not output blackbox modules on default. ``read_verilog``, unless
|
||||
called with ``-noblackbox`` will automatically set the blackbox attribute
|
||||
on any empty module it reads.
|
||||
|
||||
- The ``noblackbox`` attribute set on an empty module prevents ``read_verilog``
|
||||
from automatically setting the blackbox attribute on the module.
|
||||
|
||||
- The ``whitebox`` attribute on modules triggers the same behavior as
|
||||
``blackbox``, but is for whitebox modules, i.e. library modules that
|
||||
contain a behavioral model of the cell type.
|
||||
|
||||
- The ``lib_whitebox`` attribute overwrites ``whitebox`` when ``read_verilog``
|
||||
is run in `-lib` mode. Otherwise it's automatically removed.
|
||||
|
||||
- The ``dynports`` attribute is used by the Verilog front-end to mark modules
|
||||
that have ports with a width that depends on a parameter.
|
||||
|
||||
- The ``hdlname`` attribute is used by some passes to document the original
|
||||
(HDL) name of a module when renaming a module. It should contain a single
|
||||
name, or, when describing a hierarchical name in a flattened design, multiple
|
||||
names separated by a single space character.
|
||||
|
||||
- The ``keep`` attribute on cells and wires is used to mark objects that should
|
||||
never be removed by the optimizer. This is used for example for cells that
|
||||
have hidden connections that are not part of the netlist, such as IO pads.
|
||||
Setting the ``keep`` attribute on a module has the same effect as setting it
|
||||
on all instances of the module.
|
||||
|
||||
- The ``keep_hierarchy`` attribute on cells and modules keeps the ``flatten``
|
||||
command from flattening the indicated cells and modules.
|
||||
|
||||
- The ``init`` attribute on wires is set by the frontend when a register is
|
||||
initialized "FPGA-style" with ``reg foo = val``. It can be used during
|
||||
synthesis to add the necessary reset logic.
|
||||
|
||||
- The ``top`` attribute on a module marks this module as the top of the
|
||||
design hierarchy. The ``hierarchy`` command sets this attribute when called
|
||||
with ``-top``. Other commands, such as ``flatten`` and various backends
|
||||
use this attribute to determine the top module.
|
||||
|
||||
- The ``src`` attribute is set on cells and wires created by to the string
|
||||
``<hdl-file-name>:<line-number>`` by the HDL front-end and is then carried
|
||||
through the synthesis. When entities are combined, a new |-separated
|
||||
string is created that contains all the string from the original entities.
|
||||
|
||||
- The ``defaultvalue`` attribute is used to store default values for
|
||||
module inputs. The attribute is attached to the input wire by the HDL
|
||||
front-end when the input is declared with a default value.
|
||||
|
||||
- The ``parameter`` and ``localparam`` attributes are used to mark wires
|
||||
that represent module parameters or localparams (when the HDL front-end
|
||||
is run in ``-pwires`` mode).
|
||||
|
||||
- Wires marked with the ``hierconn`` attribute are connected to wires with the
|
||||
same name (format ``cell_name.identifier``) when they are imported from
|
||||
sub-modules by ``flatten``.
|
||||
|
||||
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
|
||||
module to mark it as a clock buffer output, and thus prevent ``clkbufmap``
|
||||
from inserting another clock buffer on a net driven by such output.
|
||||
|
||||
- The ``clkbuf_sink`` attribute can be set on an input port of a module to
|
||||
request clock buffer insertion by the ``clkbufmap`` pass.
|
||||
|
||||
- The ``clkbuf_inv`` attribute can be set on an output port of a module
|
||||
with the value set to the name of an input port of that module. When
|
||||
the ``clkbufmap`` would otherwise insert a clock buffer on this output,
|
||||
it will instead try inserting the clock buffer on the input port (this
|
||||
is used to implement clock inverter cells that clock buffer insertion
|
||||
will "see through").
|
||||
|
||||
- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent
|
||||
automatic clock buffer insertion by ``clkbufmap``. This behaviour can be
|
||||
overridden by providing a custom selection to ``clkbufmap``.
|
||||
|
||||
- The ``invertible_pin`` attribute can be set on a port to mark it as
|
||||
invertible via a cell parameter. The name of the inversion parameter
|
||||
is specified as the value of this attribute. The value of the inversion
|
||||
parameter must be of the same width as the port, with 1 indicating
|
||||
an inverted bit and 0 indicating a non-inverted bit.
|
||||
|
||||
- The ``iopad_external_pin`` attribute on a blackbox module's port marks
|
||||
it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
|
||||
from inserting another pad cell on it.
|
||||
|
||||
- The module attribute ``abc9_lut`` is an integer attribute indicating to
|
||||
`abc9` that this module describes a LUT with an area cost of this value, and
|
||||
propagation delays described using `specify` statements.
|
||||
|
||||
- The module attribute ``abc9_box`` is a boolean specifying a black/white-box
|
||||
definition, with propagation delays described using `specify` statements, for
|
||||
use by `abc9`.
|
||||
|
||||
- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and
|
||||
carry-out (if output port) ports of a box. This information is necessary for
|
||||
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
|
||||
onto a bus port will affect only its most significant bit.
|
||||
|
||||
- The module attribute ``abc9_flop`` is a boolean marking the module as a
|
||||
flip-flop. This allows `abc9` to analyse its contents in order to perform
|
||||
sequential synthesis.
|
||||
|
||||
- The frontend sets attributes ``always_comb``, ``always_latch`` and
|
||||
``always_ff`` on processes derived from SystemVerilog style always blocks
|
||||
according to the type of the always. These are checked for correctness in
|
||||
``proc_dlatch``.
|
||||
|
||||
- The cell attribute ``wildcard_port_conns`` represents wildcard port
|
||||
connections (SystemVerilog ``.*``). These are resolved to concrete
|
||||
connections to matching wires in ``hierarchy``.
|
||||
|
||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports
|
||||
the non-standard ``{* ... *}`` attribute syntax to set default attributes
|
||||
for everything that comes after the ``{* ... *}`` statement. (Reset
|
||||
by adding an empty ``{* *}`` statement.)
|
||||
|
||||
- In module parameter and port declarations, and cell port and parameter
|
||||
lists, a trailing comma is ignored. This simplifies writing Verilog code
|
||||
generators a bit in some cases.
|
||||
|
||||
- Modules can be declared with ``module mod_name(...);`` (with three dots
|
||||
instead of a list of module ports). With this syntax it is sufficient
|
||||
to simply declare a module port as 'input' or 'output' in the module
|
||||
body.
|
||||
|
||||
- When defining a macro with `define, all text between triple double quotes
|
||||
is interpreted as macro body, even if it contains unescaped newlines. The
|
||||
triple double quotes are removed from the macro body. For example:
|
||||
|
||||
`define MY_MACRO(a, b) """
|
||||
assign a = 23;
|
||||
assign b = 42;
|
||||
"""
|
||||
|
||||
- The attribute ``via_celltype`` can be used to implement a Verilog task or
|
||||
function by instantiating the specified cell type. The value is the name
|
||||
of the cell type to use. For functions the name of the output port can
|
||||
be specified by appending it to the cell type separated by a whitespace.
|
||||
The body of the task or function is unused in this case and can be used
|
||||
to specify a behavioral model of the cell type for simulation. For example:
|
||||
|
||||
module my_add3(A, B, C, Y);
|
||||
parameter WIDTH = 8;
|
||||
input [WIDTH-1:0] A, B, C;
|
||||
output [WIDTH-1:0] Y;
|
||||
...
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
...
|
||||
(* via_celltype = "my_add3 Y" *)
|
||||
(* via_celltype_defparam_WIDTH = 32 *)
|
||||
function [31:0] add3;
|
||||
input [31:0] A, B, C;
|
||||
begin
|
||||
add3 = A + B + C;
|
||||
end
|
||||
endfunction
|
||||
...
|
||||
endmodule
|
||||
|
||||
- The ``wiretype`` attribute is added by the verilog parser for wires of a
|
||||
typedef'd type to indicate the type identifier.
|
||||
|
||||
- Various ``enum_value_{value}`` attributes are added to wires of an enumerated type
|
||||
to give a map of possible enum items to their values.
|
||||
|
||||
- The ``enum_base_type`` attribute is added to enum items to indicate which
|
||||
enum they belong to (enums -- anonymous and otherwise -- are
|
||||
automatically named with an auto-incrementing counter). Note that enums
|
||||
are currently not strongly typed.
|
||||
|
||||
- A limited subset of DPI-C functions is supported. The plugin mechanism
|
||||
(see ``help plugin``) can be used to load .so files with implementations
|
||||
of DPI-C routines. As a non-standard extension it is possible to specify
|
||||
a plugin alias using the ``<alias>:`` syntax. For example:
|
||||
|
||||
module dpitest;
|
||||
import "DPI-C" function foo:round = real my_round (real);
|
||||
parameter real r = my_round(12.345);
|
||||
endmodule
|
||||
|
||||
$ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v'
|
||||
|
||||
- Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant
|
||||
expressions as ``<size>``. If the expression is not a simple identifier, it
|
||||
must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010``
|
||||
|
||||
- The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in
|
||||
initial blocks in an unconditional context (only if/case statements on
|
||||
expressions over parameters and constant values are allowed). The intended
|
||||
use for this is synthesis-time DRC.
|
||||
|
||||
- There is limited support for converting ``specify`` .. ``endspecify``
|
||||
statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells,
|
||||
for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to
|
||||
enable this functionality. (By default these blocks are ignored.)
|
||||
|
||||
- The ``reprocess_after`` internal attribute is used by the Verilog frontend to
|
||||
mark cells with bindings which might depend on the specified instantiated
|
||||
module. Modules with such cells will be reprocessed during the ``hierarchy``
|
||||
pass once the referenced module definition(s) become available.
|
||||
|
||||
- The ``smtlib2_module`` attribute can be set on a blackbox module to specify a
|
||||
formal model directly using SMT-LIB 2. For such a module, the
|
||||
``smtlib2_comb_expr`` attribute can be used on output ports to define their
|
||||
value using an SMT-LIB 2 expression. For example:
|
||||
|
||||
(* blackbox *)
|
||||
(* smtlib2_module *)
|
||||
module submod(a, b);
|
||||
input [7:0] a;
|
||||
(* smtlib2_comb_expr = "(bvnot a)" *)
|
||||
output [7:0] b;
|
||||
endmodule
|
||||
|
||||
Non-standard or SystemVerilog features for formal verification
|
||||
==============================================================
|
||||
|
||||
- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
|
||||
when ``read_verilog`` is called with ``-formal``.
|
||||
|
||||
- The system task ``$initstate`` evaluates to 1 in the initial state and
|
||||
to 0 otherwise.
|
||||
|
||||
- The system function ``$anyconst`` evaluates to any constant value. This is
|
||||
equivalent to declaring a reg as ``rand const``, but also works outside
|
||||
of checkers. (Yosys also supports ``rand const`` outside checkers.)
|
||||
|
||||
- The system function ``$anyseq`` evaluates to any value, possibly a different
|
||||
value in each cycle. This is equivalent to declaring a reg as ``rand``,
|
||||
but also works outside of checkers. (Yosys also supports ``rand``
|
||||
variables outside checkers.)
|
||||
|
||||
- The system functions ``$allconst`` and ``$allseq`` can be used to construct
|
||||
formal exist-forall problems. Assumptions only hold if the trace satisfies
|
||||
the assumption for all ``$allconst/$allseq`` values. For assertions and cover
|
||||
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
|
||||
the property (similar to ``$anyconst/$anyseq``).
|
||||
|
||||
- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq`` attribute
|
||||
(for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven
|
||||
by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
|
||||
|
||||
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
|
||||
supported in any clocked block.
|
||||
|
||||
- The syntax ``@($global_clock)`` can be used to create FFs that have no
|
||||
explicit clock input (``$ff`` cells). The same can be achieved by using
|
||||
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
|
||||
is marked with the ``(* gclk *)`` Verilog attribute.
|
||||
|
||||
|
||||
Supported features from SystemVerilog
|
||||
=====================================
|
||||
|
||||
When ``read_verilog`` is called with ``-sv``, it accepts some language features
|
||||
from SystemVerilog:
|
||||
|
||||
- The ``assert`` statement from SystemVerilog is supported in its most basic
|
||||
form. In module context: ``assert property (<expression>);`` and within an
|
||||
always block: ``assert(<expression>);``. It is transformed to an ``$assert`` cell.
|
||||
|
||||
- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
|
||||
also supported. The same limitations as with the ``assert`` statement apply.
|
||||
|
||||
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
|
||||
and ``bit`` are supported.
|
||||
|
||||
- Declaring free variables with ``rand`` and ``rand const`` is supported.
|
||||
|
||||
- Checkers without a port list that do not need to be instantiated (but instead
|
||||
behave like a named block) are supported.
|
||||
|
||||
- SystemVerilog packages are supported. Once a SystemVerilog file is read
|
||||
into a design with ``read_verilog``, all its packages are available to
|
||||
SystemVerilog files being read into the same design afterwards.
|
||||
|
||||
- typedefs are supported (including inside packages)
|
||||
- type casts are currently not supported
|
||||
|
||||
- enums are supported (including inside packages)
|
||||
- but are currently not strongly typed
|
||||
|
||||
- packed structs and unions are supported
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- multidimensional arrays are supported
|
||||
- array assignment of unpacked arrays is currently not supported
|
||||
- array literals are currently not supported
|
||||
|
||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
||||
ports are inputs or outputs are supported.
|
||||
|
||||
- Assignments within expressions are supported.
|
||||
|
||||
|
||||
Building the documentation
|
||||
==========================
|
||||
|
||||
|
|
|
@ -262,7 +262,8 @@ struct Index {
|
|||
if (cell->type.in(ID($gt), ID($ge)))
|
||||
std::swap(aport, bport);
|
||||
int carry = cell->type.in(ID($le), ID($ge)) ? CFALSE : CTRUE;
|
||||
Lit a, b;
|
||||
Lit a = Writer::EMPTY_LIT;
|
||||
Lit b = Writer::EMPTY_LIT;
|
||||
// TODO: this might not be the most economic structure; revisit at a later date
|
||||
for (int i = 0; i < width; i++) {
|
||||
a = visit(cursor, aport[i]);
|
||||
|
@ -664,8 +665,6 @@ struct Index {
|
|||
struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
||||
typedef unsigned int Lit;
|
||||
|
||||
const static Lit CONST_FALSE = 0;
|
||||
const static Lit CONST_TRUE = 1;
|
||||
const static constexpr Lit EMPTY_LIT = std::numeric_limits<Lit>::max();
|
||||
|
||||
static Lit negate(Lit lit) {
|
||||
|
@ -802,8 +801,6 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
};
|
||||
|
||||
struct XAigerAnalysis : Index<XAigerAnalysis, int, 0, 0> {
|
||||
const static int CONST_FALSE = 0;
|
||||
const static int CONST_TRUE = 0;
|
||||
const static constexpr int EMPTY_LIT = -1;
|
||||
|
||||
XAigerAnalysis()
|
||||
|
|
|
@ -338,7 +338,7 @@ struct EdifBackend : public Backend {
|
|||
*f << stringf("\n (property %s (integer %u))", EDIF_DEF(name), val.as_int());
|
||||
else {
|
||||
std::string hex_string = "";
|
||||
for (size_t i = 0; i < val.size(); i += 4) {
|
||||
for (auto i = 0; i < val.size(); i += 4) {
|
||||
int digit_value = 0;
|
||||
if (i+0 < val.size() && val.at(i+0) == RTLIL::State::S1) digit_value |= 1;
|
||||
if (i+1 < val.size() && val.at(i+1) == RTLIL::State::S1) digit_value |= 2;
|
||||
|
|
|
@ -62,9 +62,25 @@ The `OSS CAD Suite`_ releases `nightly builds`_ for the following architectures:
|
|||
Building from source
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Refer to the `readme`_ for the most up-to-date install instructions.
|
||||
The Yosys source files can be obtained from the `YosysHQ/Yosys git repository`_.
|
||||
`ABC`_ and some of the other libraries used are included as git submodules. To
|
||||
clone these submodules at the same time, use e.g.:
|
||||
|
||||
.. _readme: https://github.com/YosysHQ/yosys#building-from-source
|
||||
.. code:: console
|
||||
|
||||
git clone --recurse-submodules https://github.com/YosysHQ/yosys.git # ..or..
|
||||
git clone https://github.com/YosysHQ/yosys.git
|
||||
cd yosys
|
||||
git submodule update --init --recursive
|
||||
|
||||
.. _YosysHQ/Yosys git repository: https://github.com/yosyshq/yosys/
|
||||
.. _ABC: https://github.com/berkeley-abc/abc
|
||||
|
||||
.. note::
|
||||
|
||||
As of Yosys v0.47, releases include a ``yosys.tar.gz`` file which includes
|
||||
all source code and all sub-modules in a single archive. This can be used as
|
||||
an alternative which does not rely on ``git``.
|
||||
|
||||
Supported platforms
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -94,17 +110,116 @@ Installing all prerequisites for Ubuntu 20.04:
|
|||
|
||||
.. code:: console
|
||||
|
||||
sudo sudo apt-get install build-essential clang lld bison flex \
|
||||
libreadline-dev gawk tcl-dev libffi-dev git make \
|
||||
graphviz xdot pkg-config python3 libboost-system-dev \
|
||||
sudo apt-get install gperf build-essential bison flex \
|
||||
libreadline-dev gawk tcl-dev libffi-dev git graphviz \
|
||||
xdot pkg-config python3 libboost-system-dev \
|
||||
libboost-python-dev libboost-filesystem-dev zlib1g-dev
|
||||
|
||||
Installing all prerequisites for macOS 11 (with Homebrew):
|
||||
Installing all prerequisites for macOS 13 (with Homebrew):
|
||||
|
||||
.. code:: console
|
||||
|
||||
brew install bison flex gawk libffi git graphviz \
|
||||
pkg-config python3 tcl-tk xdot bash boost-python3
|
||||
brew tap Homebrew/bundle && brew bundle
|
||||
|
||||
or MacPorts:
|
||||
|
||||
.. code:: console
|
||||
|
||||
sudo port install bison flex readline gawk libffi graphviz \
|
||||
pkgconfig python311 boost zlib tcl
|
||||
|
||||
On FreeBSD use the following command to install all prerequisites:
|
||||
|
||||
.. code:: console
|
||||
|
||||
pkg install bison flex readline gawk libffi graphviz \
|
||||
pkgconf python311 tcl-wrapper boost-libs
|
||||
|
||||
.. note:: On FreeBSD system use gmake instead of make. To run tests use:
|
||||
``MAKE=gmake CXX=cxx CC=cc gmake test``
|
||||
|
||||
For Cygwin use the following command to install all prerequisites, or select these additional packages:
|
||||
|
||||
.. code:: console
|
||||
|
||||
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
|
||||
|
||||
.. warning::
|
||||
|
||||
As of this writing, Cygwin only supports up to Python 3.9.16 while the
|
||||
minimum required version of Python is 3.11. This means that Cygwin is not
|
||||
compatible with many of the Python-based frontends. While this does not
|
||||
currently prevent Yosys itself from working, no guarantees are made for
|
||||
continued support. It is instead recommended to use Windows Subsystem for
|
||||
Linux (WSL) and follow the instructions for Ubuntu.
|
||||
|
||||
..
|
||||
For MSYS2 (MINGW64):
|
||||
|
||||
.. code:: console
|
||||
|
||||
pacman -S bison flex mingw-w64-x86_64-gcc git libffi-devel libreadline-devel make pkg-config python3 tcl-devel mingw-w64-x86_64-boost zlib-devel
|
||||
|
||||
Not that I can get this to work; it's failing during ld with what looks like
|
||||
math library issues: ``multiple definition of `tanh'`` and
|
||||
``undefined reference to `__imp_acosh'``, as well as issues in `aiger2` with
|
||||
``seekg`` et al not being available.
|
||||
|
||||
.. note::
|
||||
|
||||
The ``config-msys2-64`` target uses the ``mingw-w64-x86_64-`` prefixed
|
||||
compiler in order to allow compiled exe files to be run without an MSYS2
|
||||
shell.
|
||||
|
||||
Build configuration
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Yosys build is based solely on Makefiles, and uses a number of variables
|
||||
which influence the build process. The recommended method for configuring
|
||||
builds is with a ``Makefile.conf`` file in the root ``yosys`` directory. The
|
||||
following commands will clean the directory and provide an initial configuration
|
||||
file:
|
||||
|
||||
.. code:: console
|
||||
|
||||
make config-clang # ..or..
|
||||
make config-gcc
|
||||
|
||||
Check the root Makefile to see what other configuration targets are available.
|
||||
Other variables can then be added to the ``Makefile.conf`` as needed, for
|
||||
example:
|
||||
|
||||
.. code:: console
|
||||
|
||||
echo "ENABLE_ZLIB := 0" >> Makefile.conf
|
||||
|
||||
Using one of these targets will set the ``CONFIG`` variable to something other
|
||||
than ``none``, and will override the environment variable for ``CXX``. To use a
|
||||
different compiler than the default when building, use:
|
||||
|
||||
.. code:: console
|
||||
|
||||
make CXX=$CXX # ..or..
|
||||
make CXX="g++-11"
|
||||
|
||||
.. note::
|
||||
|
||||
Setting the compiler in this way will prevent some other options such as
|
||||
``ENABLE_CCACHE`` from working as expected.
|
||||
|
||||
If you have clang, and (a compatible version of) ``ld.lld`` available in PATH,
|
||||
it's recommended to speed up incremental builds with lld by enabling LTO with
|
||||
``ENABLE_LTO=1``. On macOS, LTO requires using clang from homebrew rather than
|
||||
clang from xcode. For example:
|
||||
|
||||
.. code:: console
|
||||
|
||||
make ENABLE_LTO=1 CXX=$(brew --prefix)/opt/llvm/bin/clang++
|
||||
|
||||
By default, building (and installing) yosys will build (and install) `ABC`_,
|
||||
using :program:`yosys-abc` as the executable name. To use an existing ABC
|
||||
executable instead, set the ``ABCEXTERNAL`` make variable to point to the
|
||||
desired executable.
|
||||
|
||||
Running the build system
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -116,25 +231,14 @@ From the root ``yosys`` directory, call the following commands:
|
|||
make
|
||||
sudo make install
|
||||
|
||||
This will build and then install Yosys, making it available on the command line
|
||||
as ``yosys``. Note that this also downloads, builds, and installs `ABC`_ (using
|
||||
:program:`yosys-abc` as the executable name).
|
||||
|
||||
.. _ABC: https://github.com/berkeley-abc/abc
|
||||
|
||||
The default compiler is ``clang``, to change between ``clang`` and ``gcc``, use
|
||||
one of the following:
|
||||
To use a separate (out-of-tree) build directory, provide a path to the Makefile.
|
||||
|
||||
.. code:: console
|
||||
|
||||
make config-clang
|
||||
make config-gcc
|
||||
mkdir build; cd build
|
||||
make -f ../Makefile
|
||||
|
||||
To use a compiler different than the default, use:
|
||||
|
||||
.. code:: console
|
||||
|
||||
make CXX="g++-11"
|
||||
Out-of-tree builds require a clean source tree.
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
@ -161,10 +265,6 @@ directories:
|
|||
``frontends/``
|
||||
This directory contains a subdirectory for each of the frontend modules.
|
||||
|
||||
``guidelines/``
|
||||
Contains developer guidelines, including the code of conduct and coding style
|
||||
guide.
|
||||
|
||||
``kernel/``
|
||||
This directory contains all the core functionality of Yosys. This includes
|
||||
the functions and definitions for working with the RTLIL data structures
|
||||
|
@ -206,9 +306,6 @@ commands.
|
|||
Good starting points for reading example source code to learn how to write
|
||||
passes are :file:`passes/opt/opt_dff.cc` and :file:`passes/opt/opt_merge.cc`.
|
||||
|
||||
See the top-level README file for a quick Getting Started guide and build
|
||||
instructions. The Yosys build is based solely on Makefiles.
|
||||
|
||||
Users of the Qt Creator IDE can generate a QT Creator project file using make
|
||||
qtcreator. Users of the Eclipse IDE can use the "Makefile Project with Existing
|
||||
Code" project type in the Eclipse "New Project" dialog (only available after the
|
||||
|
|
36
docs/source/yosys_internals/extending_yosys/contributing.rst
Normal file
36
docs/source/yosys_internals/extending_yosys/contributing.rst
Normal file
|
@ -0,0 +1,36 @@
|
|||
Contributing to Yosys
|
||||
=====================
|
||||
|
||||
Coding Style
|
||||
------------
|
||||
|
||||
Formatting of code
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Yosys code is using tabs for indentation. Tabs are 8 characters.
|
||||
|
||||
- A continuation of a statement in the following line is indented by two
|
||||
additional tabs.
|
||||
|
||||
- Lines are as long as you want them to be. A good rule of thumb is to break
|
||||
lines at about column 150.
|
||||
|
||||
- Opening braces can be put on the same or next line as the statement opening
|
||||
the block (if, switch, for, while, do). Put the opening brace on its own line
|
||||
for larger blocks, especially blocks that contains blank lines.
|
||||
|
||||
- Otherwise stick to the `Linux Kernel Coding Style`_.
|
||||
|
||||
.. _Linux Kernel Coding Style: https://www.kernel.org/doc/Documentation/process/coding-style.rst
|
||||
|
||||
|
||||
C++ Language
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Yosys is written in C++17.
|
||||
|
||||
In general Yosys uses ``int`` instead of ``size_t``. To avoid compiler warnings
|
||||
for implicit type casts, always use ``GetSize(foobar)`` instead of
|
||||
``foobar.size()``. (``GetSize()`` is defined in :file:`kernel/yosys.h`)
|
||||
|
||||
Use range-based for loops whenever applicable.
|
|
@ -11,11 +11,7 @@ Writing extensions
|
|||
This chapter contains some bits and pieces of information about programming
|
||||
yosys extensions. Don't be afraid to ask questions on the YosysHQ Slack.
|
||||
|
||||
The :file:`guidelines/` directory of the Yosys source code contains notes on
|
||||
various aspects of Yosys development. In particular, the files GettingStarted
|
||||
and CodingStyle may be of interest.
|
||||
|
||||
.. todo:: what's in guidelines/GettingStarted that's missing from the manual?
|
||||
.. todo:: mention coding guide
|
||||
|
||||
Quick guide
|
||||
-----------
|
||||
|
|
|
@ -11,5 +11,6 @@ of interest for developers looking to customise Yosys builds.
|
|||
extensions
|
||||
build_verific
|
||||
functional_ir
|
||||
contributing
|
||||
test_suites
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Testing Yosys
|
||||
=============
|
||||
|
||||
.. todo:: more about the included test suite
|
||||
.. TODO:: more about the included test suite and how to add tests
|
||||
|
||||
Automatic testing
|
||||
-----------------
|
||||
|
@ -23,3 +23,79 @@ For up to date information, including OS versions, refer to `the git actions
|
|||
page`_.
|
||||
|
||||
.. _the git actions page: https://github.com/YosysHQ/yosys/actions
|
||||
|
||||
.. todo:: are unit tests currently working
|
||||
|
||||
..
|
||||
How to add a unit test
|
||||
----------------------
|
||||
|
||||
Unit test brings some advantages, briefly, we can list some of them (reference
|
||||
[1](https://en.wikipedia.org/wiki/Unit_testing)):
|
||||
|
||||
* Tests reduce bugs in new features;
|
||||
* Tests reduce bugs in existing features;
|
||||
* Tests are good documentation;
|
||||
* Tests reduce the cost of change;
|
||||
* Tests allow refactoring;
|
||||
|
||||
With those advantages in mind, it was required to choose a framework which fits
|
||||
well with C/C++ code. Hence, `google test`_ was chosen, because it is widely
|
||||
used and it is relatively easy learn.
|
||||
|
||||
.. _google test: https://github.com/google/googletest
|
||||
|
||||
Install and configure google test (manually)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In this section, you will see a brief description of how to install google test.
|
||||
However, it is strongly recommended that you take a look to the official
|
||||
repository (https://github.com/google/googletest) and refers to that if you have
|
||||
any problem to install it. Follow the steps below:
|
||||
|
||||
* Install: cmake and pthread
|
||||
* Clone google test project from: https://github.com/google/googletest and enter
|
||||
in the project directory
|
||||
* Inside project directory, type:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake -DBUILD_SHARED_LIBS=ON .
|
||||
make
|
||||
|
||||
* After compilation, copy all ``*.so`` inside directory ``googlemock`` and
|
||||
``googlemock/gtest`` to ``/usr/lib/``
|
||||
* Done! Now you can compile your tests.
|
||||
|
||||
If you have any problem, go to the official repository to find help.
|
||||
|
||||
Ps.: Some distros already have googletest packed. If your distro supports it,
|
||||
you can use it instead of compile.
|
||||
|
||||
Create a new unit test
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to add new unit tests for Yosys, just follow the steps below:
|
||||
|
||||
* Go to directory :file:`test/unit/`
|
||||
* In this directory you can find something similar Yosys's directory structure.
|
||||
To create your unit test file you have to follow this pattern:
|
||||
fileNameToImplementUnitTest + Test.cc. E.g.: if you want to implement the unit
|
||||
test for ``kernel/celledges.cc``, you will need to create a file like this:
|
||||
``tests/unit/kernel/celledgesTest.cc``;
|
||||
* Implement your unit test
|
||||
|
||||
Run unit tests
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
To compile and run all unit tests, just go to yosys root directory and type:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
make unit-test
|
||||
|
||||
If you want to remove all unit test files, type:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
make clean-unit-test
|
||||
|
|
|
@ -38,3 +38,4 @@ as reference to implement a similar system in any language.
|
|||
formats/index
|
||||
extending_yosys/index
|
||||
techmap
|
||||
verilog
|
||||
|
|
377
docs/source/yosys_internals/verilog.rst
Normal file
377
docs/source/yosys_internals/verilog.rst
Normal file
|
@ -0,0 +1,377 @@
|
|||
Notes on Verilog support in Yosys
|
||||
=================================
|
||||
|
||||
.. TODO:: how much of this is specific to the read_verilog and should be in :doc:`/yosys_internals/flow/verilog_frontend`?
|
||||
|
||||
Unsupported Verilog-2005 Features
|
||||
---------------------------------
|
||||
|
||||
The following Verilog-2005 features are not supported by
|
||||
Yosys and there are currently no plans to add support
|
||||
for them:
|
||||
|
||||
- Non-synthesizable language features as defined in
|
||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||
|
||||
- The ``tri``, ``triand`` and ``trior`` net types
|
||||
|
||||
- The ``config`` and ``disable`` keywords and library map files
|
||||
|
||||
|
||||
Verilog Attributes and non-standard features
|
||||
--------------------------------------------
|
||||
|
||||
- The ``full_case`` attribute on case statements is supported (also the
|
||||
non-standard ``// synopsys full_case`` directive)
|
||||
|
||||
- The ``parallel_case`` attribute on case statements is supported (also the
|
||||
non-standard ``// synopsys parallel_case`` directive)
|
||||
|
||||
- The ``// synopsys translate_off`` and ``// synopsys translate_on`` directives
|
||||
are also supported (but the use of ``` `ifdef .. `endif ``` is strongly
|
||||
recommended instead).
|
||||
|
||||
- The ``nomem2reg`` attribute on modules or arrays prohibits the automatic early
|
||||
conversion of arrays to separate registers. This is potentially dangerous.
|
||||
Usually the front-end has good reasons for converting an array to a list of
|
||||
registers. Prohibiting this step will likely result in incorrect synthesis
|
||||
results.
|
||||
|
||||
- The ``mem2reg`` attribute on modules or arrays forces the early conversion of
|
||||
arrays to separate registers.
|
||||
|
||||
- The ``nomeminit`` attribute on modules or arrays prohibits the creation of
|
||||
initialized memories. This effectively puts ``mem2reg`` on all memories that
|
||||
are written to in an ``initial`` block and are not ROMs.
|
||||
|
||||
- The ``nolatches`` attribute on modules or always-blocks prohibits the
|
||||
generation of logic-loops for latches. Instead all not explicitly assigned
|
||||
values default to x-bits. This does not affect clocked storage elements such
|
||||
as flip-flops.
|
||||
|
||||
- The ``nosync`` attribute on registers prohibits the generation of a storage
|
||||
element. The register itself will always have all bits set to 'x' (undefined).
|
||||
The variable may only be used as blocking assigned temporary variable within
|
||||
an always block. This is mostly used internally by Yosys to synthesize Verilog
|
||||
functions and access arrays.
|
||||
|
||||
- The ``nowrshmsk`` attribute on a register prohibits the generation of
|
||||
shift-and-mask type circuits for writing to bit slices of that register.
|
||||
|
||||
- The ``onehot`` attribute on wires mark them as one-hot state register. This is
|
||||
used for example for memory port sharing and set by the fsm_map pass.
|
||||
|
||||
- The ``blackbox`` attribute on modules is used to mark empty stub modules that
|
||||
have the same ports as the real thing but do not contain information on the
|
||||
internal configuration. This modules are only used by the synthesis passes to
|
||||
identify input and output ports of cells. The Verilog backend also does not
|
||||
output blackbox modules on default. `read_verilog`, unless called with
|
||||
``-noblackbox`` will automatically set the blackbox attribute on any empty
|
||||
module it reads.
|
||||
|
||||
- The ``noblackbox`` attribute set on an empty module prevents `read_verilog`
|
||||
from automatically setting the blackbox attribute on the module.
|
||||
|
||||
- The ``whitebox`` attribute on modules triggers the same behavior as
|
||||
``blackbox``, but is for whitebox modules, i.e. library modules that contain a
|
||||
behavioral model of the cell type.
|
||||
|
||||
- The ``lib_whitebox`` attribute overwrites ``whitebox`` when `read_verilog` is
|
||||
run in ``-lib`` mode. Otherwise it's automatically removed.
|
||||
|
||||
- The ``dynports`` attribute is used by the Verilog front-end to mark modules
|
||||
that have ports with a width that depends on a parameter.
|
||||
|
||||
- The ``hdlname`` attribute is used by some passes to document the original
|
||||
(HDL) name of a module when renaming a module. It should contain a single
|
||||
name, or, when describing a hierarchical name in a flattened design, multiple
|
||||
names separated by a single space character.
|
||||
|
||||
- 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 `gate_cost_equivalent` attribute on a module can be used to specify
|
||||
the estimated cost of the module as a number of basic gate instances. See
|
||||
the help message of command `keep_hierarchy` which interprets this
|
||||
attribute.
|
||||
|
||||
- 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 strings 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).
|
||||
|
||||
- Wires marked with the ``hierconn`` attribute are connected to wires with the
|
||||
same name (format ``cell_name.identifier``) when they are imported from
|
||||
sub-modules by `flatten`.
|
||||
|
||||
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
|
||||
module to mark it as a clock buffer output, and thus prevent `clkbufmap` from
|
||||
inserting another clock buffer on a net driven by such output.
|
||||
|
||||
- The ``clkbuf_sink`` attribute can be set on an input port of a module to
|
||||
request clock buffer insertion by the `clkbufmap` pass.
|
||||
|
||||
- The ``clkbuf_inv`` attribute can be set on an output port of a module with the
|
||||
value set to the name of an input port of that module. When the `clkbufmap`
|
||||
would otherwise insert a clock buffer on this output, it will instead try
|
||||
inserting the clock buffer on the input port (this is used to implement clock
|
||||
inverter cells that clock buffer insertion will "see through").
|
||||
|
||||
- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent
|
||||
automatic clock buffer insertion by `clkbufmap`. This behaviour can be
|
||||
overridden by providing a custom selection to `clkbufmap`.
|
||||
|
||||
- The ``invertible_pin`` attribute can be set on a port to mark it as invertible
|
||||
via a cell parameter. The name of the inversion parameter is specified as the
|
||||
value of this attribute. The value of the inversion parameter must be of the
|
||||
same width as the port, with 1 indicating an inverted bit and 0 indicating a
|
||||
non-inverted bit.
|
||||
|
||||
- The ``iopad_external_pin`` attribute on a blackbox module's port marks it as
|
||||
the external-facing pin of an I/O pad, and prevents `iopadmap` from inserting
|
||||
another pad cell on it.
|
||||
|
||||
- The module attribute ``abc9_lut`` is an integer attribute indicating to `abc9`
|
||||
that this module describes a LUT with an area cost of this value, and
|
||||
propagation delays described using ``specify`` statements.
|
||||
|
||||
- The module attribute ``abc9_box`` is a boolean specifying a black/white-box
|
||||
definition, with propagation delays described using ``specify`` statements,
|
||||
for use by `abc9`.
|
||||
|
||||
- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and
|
||||
carry-out (if output port) ports of a box. This information is necessary for
|
||||
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
|
||||
onto a bus port will affect only its most significant bit.
|
||||
|
||||
- The module attribute ``abc9_flop`` is a boolean marking the module as a
|
||||
flip-flop. This allows `abc9` to analyse its contents in order to perform
|
||||
sequential synthesis.
|
||||
|
||||
- The frontend sets attributes ``always_comb``, ``always_latch`` and
|
||||
``always_ff`` on processes derived from SystemVerilog style always blocks
|
||||
according to the type of the always. These are checked for correctness in
|
||||
``proc_dlatch``.
|
||||
|
||||
- The cell attribute ``wildcard_port_conns`` represents wildcard port
|
||||
connections (SystemVerilog ``.*``). These are resolved to concrete connections
|
||||
to matching wires in `hierarchy`.
|
||||
|
||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports the
|
||||
non-standard ``{* ... *}`` attribute syntax to set default attributes for
|
||||
everything that comes after the ``{* ... *}`` statement. (Reset by adding an
|
||||
empty ``{* *}`` statement.)
|
||||
|
||||
- In module parameter and port declarations, and cell port and parameter lists,
|
||||
a trailing comma is ignored. This simplifies writing Verilog code generators a
|
||||
bit in some cases.
|
||||
|
||||
- Modules can be declared with ``module mod_name(...);`` (with three dots
|
||||
instead of a list of module ports). With this syntax it is sufficient to
|
||||
simply declare a module port as 'input' or 'output' in the module body.
|
||||
|
||||
- When defining a macro with ``\`define``, all text between triple double quotes
|
||||
is interpreted as macro body, even if it contains unescaped newlines. The
|
||||
triple double quotes are removed from the macro body. For example:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
`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:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
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
|
||||
|
||||
- The ``wiretype`` attribute is added by the verilog parser for wires of a
|
||||
typedef'd type to indicate the type identifier.
|
||||
|
||||
- Various ``enum_value_{value}`` attributes are added to wires of an enumerated
|
||||
type to give a map of possible enum items to their values.
|
||||
|
||||
- The ``enum_base_type`` attribute is added to enum items to indicate which enum
|
||||
they belong to (enums -- anonymous and otherwise -- are automatically named
|
||||
with an auto-incrementing counter). Note that enums are currently not strongly
|
||||
typed.
|
||||
|
||||
- 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:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module dpitest;
|
||||
import "DPI-C" function foo:round = real my_round (real);
|
||||
parameter real r = my_round(12.345);
|
||||
endmodule
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v'
|
||||
|
||||
- Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant
|
||||
expressions as ``<size>``. If the expression is not a simple identifier, it
|
||||
must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010``
|
||||
|
||||
- The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in
|
||||
initial blocks in an unconditional context (only if/case statements on
|
||||
expressions over parameters and constant values are allowed). The intended use
|
||||
for this is synthesis-time DRC.
|
||||
|
||||
- There is limited support for converting ``specify`` .. ``endspecify``
|
||||
statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells,
|
||||
for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable
|
||||
this functionality. (By default these blocks are ignored.)
|
||||
|
||||
- The ``reprocess_after`` internal attribute is used by the Verilog frontend to
|
||||
mark cells with bindings which might depend on the specified instantiated
|
||||
module. Modules with such cells will be reprocessed during the `hierarchy`
|
||||
pass once the referenced module definition(s) become available.
|
||||
|
||||
- The ``smtlib2_module`` attribute can be set on a blackbox module to specify a
|
||||
formal model directly using SMT-LIB 2. For such a module, the
|
||||
``smtlib2_comb_expr`` attribute can be used on output ports to define their
|
||||
value using an SMT-LIB 2 expression. For example:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
(* blackbox *)
|
||||
(* smtlib2_module *)
|
||||
module submod(a, b);
|
||||
input [7:0] a;
|
||||
(* smtlib2_comb_expr = "(bvnot a)" *)
|
||||
output [7:0] b;
|
||||
endmodule
|
||||
|
||||
Non-standard or SystemVerilog features for formal verification
|
||||
--------------------------------------------------------------
|
||||
|
||||
- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
|
||||
when `read_verilog` is called with ``-formal``.
|
||||
|
||||
- The system task ``$initstate`` evaluates to 1 in the initial state and to 0
|
||||
otherwise.
|
||||
|
||||
- The system function ``$anyconst`` evaluates to any constant value. This is
|
||||
equivalent to declaring a reg as ``rand const``, but also works outside of
|
||||
checkers. (Yosys also supports ``rand const`` outside checkers.)
|
||||
|
||||
- The system function ``$anyseq`` evaluates to any value, possibly a different
|
||||
value in each cycle. This is equivalent to declaring a reg as ``rand``, but
|
||||
also works outside of checkers. (Yosys also supports ``rand`` variables
|
||||
outside checkers.)
|
||||
|
||||
- The system functions ``$allconst`` and ``$allseq`` can be used to construct
|
||||
formal exist-forall problems. Assumptions only hold if the trace satisfies the
|
||||
assumption for all ``$allconst/$allseq`` values. For assertions and cover
|
||||
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
|
||||
the property (similar to ``$anyconst/$anyseq``).
|
||||
|
||||
- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq``
|
||||
attribute (for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if
|
||||
driven by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
|
||||
|
||||
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
|
||||
supported in any clocked block.
|
||||
|
||||
- The syntax ``@($global_clock)`` can be used to create FFs that have no
|
||||
explicit clock input (``$ff`` cells). The same can be achieved by using
|
||||
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>`` is
|
||||
marked with the ``(* gclk *)`` Verilog attribute.
|
||||
|
||||
|
||||
Supported features from SystemVerilog
|
||||
-------------------------------------
|
||||
|
||||
When `read_verilog` is called with ``-sv``, it accepts some language features
|
||||
from SystemVerilog:
|
||||
|
||||
- The ``assert`` statement from SystemVerilog is supported in its most basic
|
||||
form. In module context: ``assert property (<expression>);`` and within an
|
||||
always block: ``assert(<expression>);``. It is transformed to an ``$assert``
|
||||
cell.
|
||||
|
||||
- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
|
||||
also supported. The same limitations as with the ``assert`` statement apply.
|
||||
|
||||
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
|
||||
and ``bit`` are supported.
|
||||
|
||||
- Declaring free variables with ``rand`` and ``rand const`` is supported.
|
||||
|
||||
- Checkers without a port list that do not need to be instantiated (but instead
|
||||
behave like a named block) are supported.
|
||||
|
||||
- SystemVerilog packages are supported. Once a SystemVerilog file is read into a
|
||||
design with `read_verilog`, all its packages are available to SystemVerilog
|
||||
files being read into the same design afterwards.
|
||||
|
||||
- typedefs are supported (including inside packages)
|
||||
- type casts are currently not supported
|
||||
|
||||
- enums are supported (including inside packages)
|
||||
- but are currently not strongly typed
|
||||
|
||||
- packed structs and unions are supported
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- multidimensional arrays are supported
|
||||
- array assignment of unpacked arrays is currently not supported
|
||||
- array literals are currently not supported
|
||||
|
||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
||||
ports are inputs or outputs are supported.
|
||||
|
||||
- Assignments within expressions are supported.
|
|
@ -198,11 +198,10 @@ struct Xaiger2Frontend : public Frontend {
|
|||
|
||||
int ci_counter = 0;
|
||||
for (uint32_t i = 0; i < no_boxes; i++) {
|
||||
uint32_t box_inputs, box_outputs, box_id, box_seq;
|
||||
box_inputs = read_be32(*f);
|
||||
box_outputs = read_be32(*f);
|
||||
box_id = read_be32(*f);
|
||||
box_seq = read_be32(*f);
|
||||
/* unused box_inputs = */ read_be32(*f);
|
||||
YS_MAYBE_UNUSED auto box_outputs = read_be32(*f);
|
||||
/* unused box_id = */ read_be32(*f);
|
||||
auto box_seq = read_be32(*f);
|
||||
|
||||
log("box_seq=%d boxes.size=%d\n", box_seq, (int) boxes.size());
|
||||
log_assert(box_seq < boxes.size());
|
||||
|
@ -337,11 +336,10 @@ struct Xaiger2Frontend : public Frontend {
|
|||
len, ci_num, co_num, pi_num, po_num, no_boxes);
|
||||
|
||||
for (uint32_t i = 0; i < no_boxes; i++) {
|
||||
uint32_t box_inputs, box_outputs, box_id, box_seq;
|
||||
box_inputs = read_be32(*f);
|
||||
box_outputs = read_be32(*f);
|
||||
box_id = read_be32(*f);
|
||||
box_seq = read_be32(*f);
|
||||
YS_MAYBE_UNUSED auto box_inputs = read_be32(*f);
|
||||
/* unused box_outputs = */ read_be32(*f);
|
||||
/* unused box_id = */ read_be32(*f);
|
||||
auto box_seq = read_be32(*f);
|
||||
|
||||
log("box_seq=%d boxes.size=%d\n", box_seq, (int) boxes.size());
|
||||
log_assert(box_seq < boxes.size());
|
||||
|
|
|
@ -931,7 +931,7 @@ bool AstNode::bits_only_01() const
|
|||
RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
|
||||
{
|
||||
RTLIL::State extbit = bits.back();
|
||||
while (width > int(bits.size()))
|
||||
while (width > GetSize(bits))
|
||||
bits.push_back(extbit);
|
||||
return RTLIL::Const(bits);
|
||||
}
|
||||
|
@ -939,13 +939,13 @@ RTLIL::Const AstNode::bitsAsUnsizedConst(int width)
|
|||
RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
|
||||
{
|
||||
std::vector<RTLIL::State> bits = this->bits;
|
||||
if (width >= 0 && width < int(bits.size()))
|
||||
if (width >= 0 && width < GetSize(bits))
|
||||
bits.resize(width);
|
||||
if (width >= 0 && width > int(bits.size())) {
|
||||
if (width >= 0 && width > GetSize(bits)) {
|
||||
RTLIL::State extbit = RTLIL::State::S0;
|
||||
if ((is_signed || is_unsized) && !bits.empty())
|
||||
extbit = bits.back();
|
||||
while (width > int(bits.size()))
|
||||
while (width > GetSize(bits))
|
||||
bits.push_back(extbit);
|
||||
}
|
||||
return RTLIL::Const(bits);
|
||||
|
@ -1029,7 +1029,7 @@ double AstNode::asReal(bool is_signed)
|
|||
val = const_neg(val, val, false, false, val.size());
|
||||
|
||||
double v = 0;
|
||||
for (size_t i = 0; i < val.size(); i++)
|
||||
for (auto i = 0; i < val.size(); i++)
|
||||
// IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
|
||||
// the net or the variable shall be treated as zero upon conversion.
|
||||
if (val.at(i) == RTLIL::State::S1)
|
||||
|
|
|
@ -984,7 +984,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
|
|||
// unallocated enum, ignore
|
||||
break;
|
||||
case AST_CONSTANT:
|
||||
width_hint = max(width_hint, int(bits.size()));
|
||||
width_hint = max(width_hint, GetSize(bits));
|
||||
if (!is_signed)
|
||||
sign_hint = false;
|
||||
break;
|
||||
|
|
|
@ -3493,7 +3493,7 @@ skip_dynamic_range_lvalue_expansion:;
|
|||
delete buf;
|
||||
|
||||
uint32_t result = 0;
|
||||
for (size_t i = 0; i < arg_value.size(); i++)
|
||||
for (auto i = 0; i < arg_value.size(); i++)
|
||||
if (arg_value.at(i) == RTLIL::State::S1)
|
||||
result = i + 1;
|
||||
|
||||
|
@ -4339,7 +4339,7 @@ replace_fcall_later:;
|
|||
RTLIL::Const a = children[1]->bitsAsConst(width_hint, sign_hint);
|
||||
RTLIL::Const b = children[2]->bitsAsConst(width_hint, sign_hint);
|
||||
log_assert(a.size() == b.size());
|
||||
for (size_t i = 0; i < a.size(); i++)
|
||||
for (auto i = 0; i < a.size(); i++)
|
||||
if (a[i] != b[i])
|
||||
a.bits()[i] = RTLIL::State::Sx;
|
||||
newNode = mkconst_bits(a.to_bits(), sign_hint);
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
Checklist for adding internal cell types
|
||||
========================================
|
||||
|
||||
Things to do right away:
|
||||
|
||||
- Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
|
||||
- Add to InternalCellChecker::check() in kernel/rtlil.cc
|
||||
- Add to techlibs/common/simlib.v
|
||||
- Add to techlibs/common/techmap.v
|
||||
|
||||
Things to do after finalizing the cell interface:
|
||||
|
||||
- Add support to kernel/satgen.h for the new cell type
|
||||
- Add to docs/source/CHAPTER_CellLib.rst (or just add a fixme to the bottom)
|
||||
- Maybe add support to the Verilog backend for dumping such cells as expression
|
||||
|
||||
|
||||
|
||||
Checklist for creating Yosys releases
|
||||
=====================================
|
||||
|
||||
Update the CHANGELOG file:
|
||||
|
||||
cd ~yosys
|
||||
gitk &
|
||||
vi CHANGELOG
|
||||
|
||||
|
||||
Update and check documentation:
|
||||
|
||||
cd ~yosys
|
||||
make docs
|
||||
- sanity check the figures in docs/images
|
||||
- if there are any odd things -> investigate
|
||||
|
||||
cd ~yosys
|
||||
vi README guidelines/*
|
||||
- is the information provided in those file still up to date
|
||||
|
||||
|
||||
Then with default config setting:
|
||||
|
||||
cd ~yosys
|
||||
make vgtest
|
||||
|
||||
cd ~yosys
|
||||
./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
|
||||
./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
|
||||
./yosys -p 'synth; show' tests/simple/fiedler-cooley.v
|
||||
./yosys -p 'synth_xilinx -top up3down5; show' tests/simple/fiedler-cooley.v
|
||||
|
||||
cd ~yosys/examples/cmos
|
||||
bash testbench.sh
|
||||
|
||||
cd ~yosys/examples/basys3
|
||||
bash run.sh
|
||||
|
||||
|
||||
Test building plugins with various of the standard passes:
|
||||
|
||||
yosys-config --build test.so equiv_simple.cc
|
||||
- also check the code examples in guidelines/GettingStarted
|
||||
|
||||
|
||||
And if a version of the verific library is currently available:
|
||||
|
||||
cd ~yosys
|
||||
cat frontends/verific/build_amd64.txt
|
||||
- follow instructions
|
||||
|
||||
cd frontends/verific
|
||||
../../yosys test_navre.ys
|
||||
|
||||
|
||||
Finally run all tests with "make config-{clang,gcc}":
|
||||
|
||||
cd ~yosys
|
||||
make clean
|
||||
make test
|
||||
make ystests
|
||||
make vloghtb
|
||||
make install
|
||||
|
||||
cd ~yosys-bigsim
|
||||
make clean
|
||||
make full
|
||||
|
||||
cd ~vloghammer
|
||||
make purge gen_issues gen_samples
|
||||
make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
|
||||
chromium-browser report.html
|
||||
|
||||
|
||||
Release:
|
||||
|
||||
- set YOSYS_VER to x.y.z in Makefile
|
||||
- remove "bumpversion" target from Makefile
|
||||
- update version string in CHANGELOG
|
||||
git commit -am "Yosys x.y.z"
|
||||
|
||||
- push tag to github
|
||||
- post changelog on github
|
||||
- post short release note on reddit
|
||||
|
||||
|
||||
Updating the website:
|
||||
|
||||
cd ~yosys
|
||||
make install
|
||||
|
||||
cd ~yosys-web
|
||||
make update_show
|
||||
git commit -am update
|
||||
make push
|
||||
|
||||
- Read the Docs updates handled by Jenkins on source change
|
|
@ -1,72 +0,0 @@
|
|||
Contributor Covenant Code of Conduct
|
||||
|
||||
Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at contact@yosyshq.com and/or
|
||||
claire@clairexen.net. All complaints will be reviewed and investigated and
|
||||
will result in a response that is deemed necessary and appropriate to the
|
||||
circumstances. The project team is obligated to maintain confidentiality with
|
||||
regard to the reporter of an incident. Further details of specific enforcement
|
||||
policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
Attribution
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
|
||||
available at http://contributor-covenant.org/version/1/4/
|
|
@ -1,34 +0,0 @@
|
|||
Coding Style
|
||||
============
|
||||
|
||||
|
||||
Formatting of code
|
||||
------------------
|
||||
|
||||
- Yosys code is using tabs for indentation. Tabs are 8 characters.
|
||||
|
||||
- A continuation of a statement in the following line is indented by
|
||||
two additional tabs.
|
||||
|
||||
- Lines are as long as you want them to be. A good rule of thumb is
|
||||
to break lines at about column 150.
|
||||
|
||||
- Opening braces can be put on the same or next line as the statement
|
||||
opening the block (if, switch, for, while, do). Put the opening brace
|
||||
on its own line for larger blocks, especially blocks that contains
|
||||
blank lines.
|
||||
|
||||
- Otherwise stick to the Linux Kernel Coding Style:
|
||||
https://www.kernel.org/doc/Documentation/process/coding-style.rst
|
||||
|
||||
|
||||
C++ Language
|
||||
-------------
|
||||
|
||||
Yosys is written in C++17.
|
||||
|
||||
In general Yosys uses "int" instead of "size_t". To avoid compiler
|
||||
warnings for implicit type casts, always use "GetSize(foobar)" instead
|
||||
of "foobar.size()". (GetSize() is defined in kernel/yosys.h)
|
||||
|
||||
Use range-based for loops whenever applicable.
|
|
@ -1,69 +0,0 @@
|
|||
How to add unit test
|
||||
====================
|
||||
|
||||
Unit test brings some advantages, briefly, we can list some of them (reference
|
||||
[1](https://en.wikipedia.org/wiki/Unit_testing)):
|
||||
|
||||
* Tests reduce bugs in new features;
|
||||
* Tests reduce bugs in existing features;
|
||||
* Tests are good documentation;
|
||||
* Tests reduce the cost of change;
|
||||
* Tests allow refactoring;
|
||||
|
||||
With those advantages in mind, it was required to choose a framework which fits
|
||||
well with C/C++ code. Hence, it was chosen (google test)
|
||||
[https://github.com/google/googletest], because it is largely used and it is
|
||||
relatively easy learn.
|
||||
|
||||
Install and configure google test (manually)
|
||||
--------------------------------------------
|
||||
|
||||
In this section, you will see a brief description of how to install google
|
||||
test. However, it is strongly recommended that you take a look to the official
|
||||
repository (https://github.com/google/googletest) and refers to that if you
|
||||
have any problem to install it. Follow the steps below:
|
||||
|
||||
* Install: cmake and pthread
|
||||
* Clone google test project from: https://github.com/google/googletest and
|
||||
enter in the project directory
|
||||
* Inside project directory, type:
|
||||
|
||||
```
|
||||
cmake -DBUILD_SHARED_LIBS=ON .
|
||||
make
|
||||
```
|
||||
|
||||
* After compilation, copy all "*.so" inside directory "googlemock" and
|
||||
"googlemock/gtest" to "/usr/lib/"
|
||||
* Done! Now you can compile your tests.
|
||||
|
||||
If you have any problem, go to the official repository to find help.
|
||||
|
||||
Ps.: Some distros already have googletest packed. If your distro supports it,
|
||||
you can use it instead of compile.
|
||||
|
||||
Create new unit test
|
||||
--------------------
|
||||
|
||||
If you want to add new unit tests for Yosys, just follow the steps below:
|
||||
|
||||
* Go to directory "yosys/test/unit/"
|
||||
* In this directory you can find something similar Yosys's directory structure.
|
||||
To create your unit test file you have to follow this pattern:
|
||||
fileNameToImplementUnitTest + Test.cc. E.g.: if you want to implement the
|
||||
unit test for kernel/celledges.cc, you will need to create a file like this:
|
||||
tests/unit/kernel/celledgesTest.cc;
|
||||
* Implement your unit test
|
||||
|
||||
Run unit test
|
||||
-------------
|
||||
|
||||
To compile and run all unit tests, just go to yosys root directory and type:
|
||||
```
|
||||
make unit-test
|
||||
```
|
||||
|
||||
If you want to remove all unit test files, type:
|
||||
```
|
||||
make clean-unit-test
|
||||
```
|
|
@ -1,83 +0,0 @@
|
|||
Creating the Visual Studio Template Project
|
||||
===========================================
|
||||
|
||||
1. Create an empty Visual C++ Win32 Console App project
|
||||
|
||||
Microsoft Visual Studio Express 2013 for Windows Desktop
|
||||
Open New Project Wizard (File -> New Project..)
|
||||
|
||||
Project Name: YosysVS
|
||||
Solution Name: YosysVS
|
||||
[X] Create directory for solution
|
||||
[ ] Add to source control
|
||||
|
||||
[X] Console applications
|
||||
[X] Empty Project
|
||||
[ ] SDL checks
|
||||
|
||||
2. Open YosysVS Project Properties
|
||||
|
||||
Select Configuration: All Configurations
|
||||
|
||||
C/C++ -> General -> Additional Include Directories
|
||||
Add: ..\yosys
|
||||
|
||||
C/C++ -> Preprocessor -> Preprocessor Definitions
|
||||
Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS
|
||||
|
||||
3. Resulting file system tree:
|
||||
|
||||
YosysVS/
|
||||
YosysVS/YosysVS
|
||||
YosysVS/YosysVS/YosysVS.vcxproj
|
||||
YosysVS/YosysVS/YosysVS.vcxproj.filters
|
||||
YosysVS/YosysVS.sdf
|
||||
YosysVS/YosysVS.sln
|
||||
YosysVS/YosysVS.v12.suo
|
||||
|
||||
4. Zip YosysVS as YosysVS-Tpl-v1.zip
|
||||
|
||||
Compiling with Visual Studio
|
||||
============================
|
||||
|
||||
Visual Studio builds are not directly supported by build scripts, but they are still possible.
|
||||
|
||||
1. Easy way
|
||||
|
||||
- Go to https://github.com/YosysHQ/yosys/actions/workflows/vs.yml?query=branch%3Amain
|
||||
- Click on the most recent completed run
|
||||
- In Artifacts region find vcxsrc and click on it to download
|
||||
- Unpack downloaded ZIP file
|
||||
- Open YosysVS.sln with Visual Studio
|
||||
|
||||
2. Using WSL or MSYS2
|
||||
|
||||
- Make sure to have make, python3 and git available
|
||||
- Git clone yosys repository
|
||||
- Execute ```make vcxsrc YOSYS_VER=latest```
|
||||
- File yosys-win32-vcxsrc-latest.zip will be created
|
||||
- Transfer that file to location visible by Windows application
|
||||
- Unpack ZIP
|
||||
- Open YosysVS.sln with Visual Studio
|
||||
|
||||
Cross-Building for Windows with MXE
|
||||
===================================
|
||||
|
||||
Check http://mxe.cc/#requirements and install all missing requirements.
|
||||
|
||||
As root (or other user with write access to /usr/local/src):
|
||||
|
||||
cd /usr/local/src
|
||||
git clone https://github.com/mxe/mxe.git
|
||||
cd mxe
|
||||
|
||||
make -j$(nproc) MXE_PLUGIN_DIRS="plugins/tcl.tk" \
|
||||
MXE_TARGETS="i686-w64-mingw32.static" \
|
||||
gcc tcl readline
|
||||
|
||||
Then as regular user in some directory where you build stuff:
|
||||
|
||||
git clone https://github.com/YosysHQ/yosys.git yosys-win32
|
||||
cd yosys-win32
|
||||
make config-mxe
|
||||
make -j$(nproc) mxebin
|
|
@ -33,7 +33,7 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed)
|
|||
if (arg.size() > 0 && is_signed)
|
||||
padding = arg.back();
|
||||
|
||||
while (int(arg.size()) < width)
|
||||
while (GetSize(arg) < width)
|
||||
arg.bits().push_back(padding);
|
||||
|
||||
arg.bits().resize(width);
|
||||
|
@ -45,7 +45,7 @@ static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_
|
|||
|
||||
BigInteger::Sign sign = BigInteger::positive;
|
||||
State inv_sign_bit = RTLIL::State::S1;
|
||||
size_t num_bits = val.size();
|
||||
auto num_bits = val.size();
|
||||
|
||||
if (as_signed && num_bits && val[num_bits-1] == RTLIL::State::S1) {
|
||||
inv_sign_bit = RTLIL::State::S0;
|
||||
|
@ -53,7 +53,7 @@ static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_
|
|||
num_bits--;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_bits; i++)
|
||||
for (auto i = 0; i < num_bits; i++)
|
||||
if (val[i] == RTLIL::State::S0 || val[i] == RTLIL::State::S1)
|
||||
mag.setBit(i, val[i] == inv_sign_bit);
|
||||
else if (undef_bit_pos < 0)
|
||||
|
@ -78,12 +78,12 @@ static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_b
|
|||
if (val.getSign() < 0)
|
||||
{
|
||||
mag--;
|
||||
for (int i = 0; i < result_len; i++)
|
||||
for (auto i = 0; i < result_len; i++)
|
||||
result.bits()[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < result_len; i++)
|
||||
for (auto i = 0; i < result_len; i++)
|
||||
result.bits()[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0;
|
||||
}
|
||||
}
|
||||
|
@ -132,14 +132,14 @@ static RTLIL::State logic_xnor(RTLIL::State a, RTLIL::State b)
|
|||
RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
|
||||
{
|
||||
if (result_len < 0)
|
||||
result_len = arg1.size();
|
||||
result_len = GetSize(arg1);
|
||||
|
||||
RTLIL::Const arg1_ext = arg1;
|
||||
extend_u0(arg1_ext, result_len, signed1);
|
||||
|
||||
RTLIL::Const result(RTLIL::State::Sx, result_len);
|
||||
for (size_t i = 0; i < size_t(result_len); i++) {
|
||||
if (i >= arg1_ext.size())
|
||||
for (auto i = 0; i < result_len; i++) {
|
||||
if (i >= GetSize(arg1_ext))
|
||||
result.bits()[i] = RTLIL::State::S0;
|
||||
else if (arg1_ext.bits()[i] == RTLIL::State::S0)
|
||||
result.bits()[i] = RTLIL::State::S1;
|
||||
|
@ -154,15 +154,15 @@ static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL:
|
|||
RTLIL::Const arg1, RTLIL::Const arg2, bool signed1, bool signed2, int result_len = -1)
|
||||
{
|
||||
if (result_len < 0)
|
||||
result_len = max(arg1.size(), arg2.size());
|
||||
result_len = max(GetSize(arg1), GetSize(arg2));
|
||||
|
||||
extend_u0(arg1, result_len, signed1);
|
||||
extend_u0(arg2, result_len, signed2);
|
||||
|
||||
RTLIL::Const result(RTLIL::State::Sx, result_len);
|
||||
for (size_t i = 0; i < size_t(result_len); i++) {
|
||||
RTLIL::State a = i < arg1.size() ? arg1.bits()[i] : RTLIL::State::S0;
|
||||
RTLIL::State b = i < arg2.size() ? arg2.bits()[i] : RTLIL::State::S0;
|
||||
for (auto i = 0; i < result_len; i++) {
|
||||
RTLIL::State a = i < GetSize(arg1) ? arg1.bits()[i] : RTLIL::State::S0;
|
||||
RTLIL::State b = i < GetSize(arg2) ? arg2.bits()[i] : RTLIL::State::S0;
|
||||
result.bits()[i] = logic_func(a, b);
|
||||
}
|
||||
|
||||
|
@ -193,11 +193,11 @@ static RTLIL::Const logic_reduce_wrapper(RTLIL::State initial, RTLIL::State(*log
|
|||
{
|
||||
RTLIL::State temp = initial;
|
||||
|
||||
for (size_t i = 0; i < arg1.size(); i++)
|
||||
for (auto i = 0; i < arg1.size(); i++)
|
||||
temp = logic_func(temp, arg1[i]);
|
||||
|
||||
RTLIL::Const result(temp);
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const
|
|||
BigInteger a = const2big(arg1, signed1, undef_bit_pos_a);
|
||||
RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0);
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const
|
|||
RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
|
||||
RTLIL::Const result(logic_and(bit_a, bit_b));
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const
|
|||
RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1;
|
||||
RTLIL::Const result(logic_or(bit_a, bit_b));
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
|
|||
BigInteger offset = const2big(arg2, signed2, undef_bit_pos) * direction;
|
||||
|
||||
if (result_len < 0)
|
||||
result_len = arg1.size();
|
||||
result_len = GetSize(arg1);
|
||||
|
||||
RTLIL::Const result(RTLIL::State::Sx, result_len);
|
||||
if (undef_bit_pos >= 0)
|
||||
|
@ -296,7 +296,7 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co
|
|||
BigInteger pos = BigInteger(i) + offset;
|
||||
if (pos < 0)
|
||||
result.bits()[i] = vacant_bits;
|
||||
else if (pos >= BigInteger(int(arg1.size())))
|
||||
else if (pos >= BigInteger(GetSize(arg1)))
|
||||
result.bits()[i] = sign_ext ? arg1.back() : vacant_bits;
|
||||
else
|
||||
result.bits()[i] = arg1[pos.toInt()];
|
||||
|
@ -347,7 +347,7 @@ RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
|
|||
bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos);
|
||||
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
|
|||
bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos);
|
||||
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -369,12 +369,12 @@ RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
|
|||
RTLIL::Const arg2_ext = arg2;
|
||||
RTLIL::Const result(RTLIL::State::S0, result_len);
|
||||
|
||||
int width = max(arg1_ext.size(), arg2_ext.size());
|
||||
int width = max(GetSize(arg1_ext), GetSize(arg2_ext));
|
||||
extend_u0(arg1_ext, width, signed1 && signed2);
|
||||
extend_u0(arg2_ext, width, signed1 && signed2);
|
||||
|
||||
RTLIL::State matched_status = RTLIL::State::S1;
|
||||
for (size_t i = 0; i < arg1_ext.size(); i++) {
|
||||
for (auto i = 0; i < arg1_ext.size(); i++) {
|
||||
if (arg1_ext.at(i) == RTLIL::State::S0 && arg2_ext.at(i) == RTLIL::State::S1)
|
||||
return result;
|
||||
if (arg1_ext.at(i) == RTLIL::State::S1 && arg2_ext.at(i) == RTLIL::State::S0)
|
||||
|
@ -403,11 +403,11 @@ RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2
|
|||
RTLIL::Const arg2_ext = arg2;
|
||||
RTLIL::Const result(RTLIL::State::S0, result_len);
|
||||
|
||||
int width = max(arg1_ext.size(), arg2_ext.size());
|
||||
int width = max(GetSize(arg1_ext), GetSize(arg2_ext));
|
||||
extend_u0(arg1_ext, width, signed1 && signed2);
|
||||
extend_u0(arg2_ext, width, signed1 && signed2);
|
||||
|
||||
for (size_t i = 0; i < arg1_ext.size(); i++) {
|
||||
for (auto i = 0; i < arg1_ext.size(); i++) {
|
||||
if (arg1_ext.at(i) != arg2_ext.at(i))
|
||||
return result;
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
|
|||
bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos);
|
||||
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
|
|||
bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos);
|
||||
RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0);
|
||||
|
||||
while (int(result.size()) < result_len)
|
||||
while (GetSize(result) < result_len)
|
||||
result.bits().push_back(RTLIL::State::S0);
|
||||
return result;
|
||||
}
|
||||
|
@ -452,21 +452,21 @@ RTLIL::Const RTLIL::const_add(const RTLIL::Const &arg1, const RTLIL::Const &arg2
|
|||
{
|
||||
int undef_bit_pos = -1;
|
||||
BigInteger y = const2big(arg1, signed1, undef_bit_pos) + const2big(arg2, signed2, undef_bit_pos);
|
||||
return big2const(y, result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), undef_bit_pos);
|
||||
return big2const(y, result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), undef_bit_pos);
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_sub(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
{
|
||||
int undef_bit_pos = -1;
|
||||
BigInteger y = const2big(arg1, signed1, undef_bit_pos) - const2big(arg2, signed2, undef_bit_pos);
|
||||
return big2const(y, result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), undef_bit_pos);
|
||||
return big2const(y, result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), undef_bit_pos);
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_mul(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
{
|
||||
int undef_bit_pos = -1;
|
||||
BigInteger y = const2big(arg1, signed1, undef_bit_pos) * const2big(arg2, signed2, undef_bit_pos);
|
||||
return big2const(y, result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), min(undef_bit_pos, 0));
|
||||
return big2const(y, result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), min(undef_bit_pos, 0));
|
||||
}
|
||||
|
||||
// truncating division
|
||||
|
@ -480,7 +480,7 @@ RTLIL::Const RTLIL::const_div(const RTLIL::Const &arg1, const RTLIL::Const &arg2
|
|||
bool result_neg = (a.getSign() == BigInteger::negative) != (b.getSign() == BigInteger::negative);
|
||||
a = a.getSign() == BigInteger::negative ? -a : a;
|
||||
b = b.getSign() == BigInteger::negative ? -b : b;
|
||||
return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), min(undef_bit_pos, 0));
|
||||
return big2const(result_neg ? -(a / b) : (a / b), result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), min(undef_bit_pos, 0));
|
||||
}
|
||||
|
||||
// truncating modulo
|
||||
|
@ -494,7 +494,7 @@ RTLIL::Const RTLIL::const_mod(const RTLIL::Const &arg1, const RTLIL::Const &arg2
|
|||
bool result_neg = a.getSign() == BigInteger::negative;
|
||||
a = a.getSign() == BigInteger::negative ? -a : a;
|
||||
b = b.getSign() == BigInteger::negative ? -b : b;
|
||||
return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), min(undef_bit_pos, 0));
|
||||
return big2const(result_neg ? -(a % b) : (a % b), result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), min(undef_bit_pos, 0));
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_divfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
|
@ -516,7 +516,7 @@ RTLIL::Const RTLIL::const_divfloor(const RTLIL::Const &arg1, const RTLIL::Const
|
|||
// bigint division with negative numbers is wonky, make sure we only negate at the very end
|
||||
result = -((a + b - 1) / b);
|
||||
}
|
||||
return big2const(result, result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), min(undef_bit_pos, 0));
|
||||
return big2const(result, result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), min(undef_bit_pos, 0));
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_modfloor(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
|
@ -539,7 +539,7 @@ RTLIL::Const RTLIL::const_modfloor(const RTLIL::Const &arg1, const RTLIL::Const
|
|||
} else {
|
||||
modulo = b_sign == BigInteger::negative ? truncated - b : truncated + b;
|
||||
}
|
||||
return big2const(modulo, result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), min(undef_bit_pos, 0));
|
||||
return big2const(modulo, result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), min(undef_bit_pos, 0));
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
|
||||
|
@ -590,7 +590,7 @@ RTLIL::Const RTLIL::const_pow(const RTLIL::Const &arg1, const RTLIL::Const &arg2
|
|||
y *= -1;
|
||||
}
|
||||
|
||||
return big2const(y, result_len >= 0 ? result_len : max(arg1.size(), arg2.size()), min(undef_bit_pos, 0));
|
||||
return big2const(y, result_len >= 0 ? result_len : max(GetSize(arg1), GetSize(arg2)), min(undef_bit_pos, 0));
|
||||
}
|
||||
|
||||
RTLIL::Const RTLIL::const_pos(const RTLIL::Const &arg1, const RTLIL::Const&, bool signed1, bool, int result_len)
|
||||
|
@ -626,7 +626,7 @@ RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2
|
|||
return arg2;
|
||||
|
||||
RTLIL::Const ret = arg1;
|
||||
for (int i = 0; i < ret.size(); i++)
|
||||
for (auto i = 0; i < ret.size(); i++)
|
||||
if (ret[i] != arg2[i])
|
||||
ret.bits()[i] = State::Sx;
|
||||
return ret;
|
||||
|
@ -640,7 +640,7 @@ RTLIL::Const RTLIL::const_pmux(const RTLIL::Const &arg1, const RTLIL::Const &arg
|
|||
if (!arg3.is_onehot())
|
||||
return RTLIL::Const(State::Sx, arg1.size());
|
||||
|
||||
for (int i = 0; i < arg3.size(); i++)
|
||||
for (auto i = 0; i < arg3.size(); i++)
|
||||
if (arg3[i] == State::S1)
|
||||
return RTLIL::Const(std::vector<RTLIL::State>(arg2.begin() + i*arg1.size(), arg2.begin() + (i+1)*arg1.size()));
|
||||
|
||||
|
@ -702,7 +702,7 @@ RTLIL::Const RTLIL::const_bweqx(const RTLIL::Const &arg1, const RTLIL::Const &ar
|
|||
{
|
||||
log_assert(arg2.size() == arg1.size());
|
||||
RTLIL::Const result(RTLIL::State::S0, arg1.size());
|
||||
for (int i = 0; i < arg1.size(); i++)
|
||||
for (auto i = 0; i < arg1.size(); i++)
|
||||
result.bits()[i] = arg1[i] == arg2[i] ? State::S1 : State::S0;
|
||||
|
||||
return result;
|
||||
|
@ -713,7 +713,7 @@ RTLIL::Const RTLIL::const_bwmux(const RTLIL::Const &arg1, const RTLIL::Const &ar
|
|||
log_assert(arg2.size() == arg1.size());
|
||||
log_assert(arg3.size() == arg1.size());
|
||||
RTLIL::Const result(RTLIL::State::Sx, arg1.size());
|
||||
for (int i = 0; i < arg1.size(); i++) {
|
||||
for (auto i = 0; i < arg1.size(); i++) {
|
||||
if (arg3[i] != State::Sx || arg1[i] == arg2[i])
|
||||
result.bits()[i] = arg3[i] == State::S1 ? arg2[i] : arg1[i];
|
||||
}
|
||||
|
|
|
@ -276,6 +276,8 @@ int main(int argc, char **argv)
|
|||
options.add_options("developer")
|
||||
("X,trace", "enable tracing of core data structure changes. for debugging")
|
||||
("M,randomize-pointers", "will slightly randomize allocated pointer addresses. for debugging")
|
||||
("autoidx", "start counting autoidx up from <seed>, similar effect to --hash-seed",
|
||||
cxxopts::value<uint64_t>(), "<idx>")
|
||||
("A,abort", "will call abort() at the end of the script. for debugging")
|
||||
("x,experimental", "do not print warnings for the experimental <feature>",
|
||||
cxxopts::value<std::vector<std::string>>(), "<feature>")
|
||||
|
@ -427,6 +429,10 @@ int main(int argc, char **argv)
|
|||
if (result.count("infile")) {
|
||||
frontend_files = result["infile"].as<std::vector<std::string>>();
|
||||
}
|
||||
if (result.count("autoidx")) {
|
||||
int idx = result["autoidx"].as<uint64_t>();
|
||||
autoidx = idx;
|
||||
}
|
||||
|
||||
if (log_errfile == NULL) {
|
||||
log_files.push_back(stdout);
|
||||
|
|
|
@ -228,6 +228,14 @@ struct Macc
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_simple_product()
|
||||
{
|
||||
return bit_ports.empty() &&
|
||||
ports.size() == 1 &&
|
||||
!ports[0].in_b.empty() &&
|
||||
!ports[0].do_subtract;
|
||||
}
|
||||
|
||||
Macc(RTLIL::Cell *cell = nullptr)
|
||||
{
|
||||
if (cell != nullptr)
|
||||
|
|
|
@ -1680,8 +1680,6 @@ SigSpec MemWr::decompress_en(const std::vector<int> &swizzle, SigSpec sig) {
|
|||
return res;
|
||||
}
|
||||
|
||||
using addr_t = MemContents::addr_t;
|
||||
|
||||
MemContents::MemContents(Mem *mem) :
|
||||
MemContents(ceil_log2(mem->size), mem->width)
|
||||
{
|
||||
|
@ -1758,7 +1756,7 @@ bool MemContents::_range_overlaps(std::map<addr_t, RTLIL::Const>::iterator it, a
|
|||
return !(top1 < begin_addr || top2 < _range_begin(it));
|
||||
}
|
||||
|
||||
std::map<addr_t, RTLIL::Const>::iterator MemContents::_range_at(addr_t addr) const {
|
||||
std::map<MemContents::addr_t, RTLIL::Const>::iterator MemContents::_range_at(addr_t addr) const {
|
||||
// allow addr == 1<<_addr_width (which will just return end())
|
||||
log_assert(addr <= (addr_t)(1<<_addr_width));
|
||||
// get the first range with base > addr
|
||||
|
@ -1786,7 +1784,7 @@ RTLIL::Const MemContents::operator[](addr_t addr) const {
|
|||
return _default_value;
|
||||
}
|
||||
|
||||
addr_t MemContents::count_range(addr_t begin_addr, addr_t end_addr) const {
|
||||
MemContents::addr_t MemContents::count_range(addr_t begin_addr, addr_t end_addr) const {
|
||||
addr_t count = 0;
|
||||
for(auto it = _range_at(begin_addr); _range_overlaps(it, begin_addr, end_addr); it++) {
|
||||
auto first = std::max(_range_begin(it), begin_addr);
|
||||
|
@ -1829,7 +1827,7 @@ void MemContents::clear_range(addr_t begin_addr, addr_t end_addr) {
|
|||
_values.erase(begin_it, end_it);
|
||||
}
|
||||
|
||||
std::map<addr_t, RTLIL::Const>::iterator MemContents::_reserve_range(addr_t begin_addr, addr_t end_addr) {
|
||||
std::map<MemContents::addr_t, RTLIL::Const>::iterator MemContents::_reserve_range(addr_t begin_addr, addr_t end_addr) {
|
||||
if(begin_addr >= end_addr)
|
||||
return _values.end(); // need a dummy value to return, end() is cheap
|
||||
// find the first range containing any addr >= begin_addr - 1
|
||||
|
|
|
@ -381,7 +381,7 @@ int RTLIL::Const::as_int(bool is_signed) const
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t RTLIL::Const::get_min_size(bool is_signed) const
|
||||
int RTLIL::Const::get_min_size(bool is_signed) const
|
||||
{
|
||||
if (empty()) return 0;
|
||||
|
||||
|
@ -392,7 +392,7 @@ size_t RTLIL::Const::get_min_size(bool is_signed) const
|
|||
else
|
||||
leading_bit = RTLIL::State::S0;
|
||||
|
||||
size_t idx = size();
|
||||
auto idx = size();
|
||||
while (idx > 0 && (*this)[idx -1] == leading_bit) {
|
||||
idx--;
|
||||
}
|
||||
|
@ -407,22 +407,22 @@ size_t RTLIL::Const::get_min_size(bool is_signed) const
|
|||
|
||||
void RTLIL::Const::compress(bool is_signed)
|
||||
{
|
||||
size_t idx = get_min_size(is_signed);
|
||||
auto idx = get_min_size(is_signed);
|
||||
bits().erase(bits().begin() + idx, bits().end());
|
||||
}
|
||||
|
||||
std::optional<int> RTLIL::Const::as_int_compress(bool is_signed) const
|
||||
{
|
||||
size_t size = get_min_size(is_signed);
|
||||
auto size = get_min_size(is_signed);
|
||||
if(size == 0 || size > 32)
|
||||
return std::nullopt;
|
||||
|
||||
int32_t ret = 0;
|
||||
for (size_t i = 0; i < size && i < 32; i++)
|
||||
for (auto i = 0; i < size && i < 32; i++)
|
||||
if ((*this)[i] == State::S1)
|
||||
ret |= 1 << i;
|
||||
if (is_signed && (*this)[size-1] == State::S1)
|
||||
for (size_t i = size; i < 32; i++)
|
||||
for (auto i = size; i < 32; i++)
|
||||
ret |= 1 << i;
|
||||
return ret;
|
||||
}
|
||||
|
@ -2148,6 +2148,21 @@ namespace {
|
|||
check_expected();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Checklist for adding internal cell types
|
||||
* ========================================
|
||||
* Things to do right away:
|
||||
* - Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
|
||||
* - Add to InternalCellChecker::check() in kernel/rtlil.cc
|
||||
* - Add to techlibs/common/simlib.v
|
||||
* - Add to techlibs/common/techmap.v
|
||||
*
|
||||
* Things to do after finalizing the cell interface:
|
||||
* - Add support to kernel/satgen.h for the new cell type
|
||||
* - Add to docs/source/CHAPTER_CellLib.rst (or just add a fixme to the bottom)
|
||||
* - Maybe add support to the Verilog backend for dumping such cells as expression
|
||||
*
|
||||
*/
|
||||
error(__LINE__);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -780,7 +780,7 @@ public:
|
|||
RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const;
|
||||
|
||||
// find the MSB without redundant leading bits
|
||||
size_t get_min_size(bool is_signed) const;
|
||||
int get_min_size(bool is_signed) const;
|
||||
|
||||
// compress representation to the minimum required bits
|
||||
void compress(bool is_signed = false);
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
//
|
||||
// This header is very boring. It just defines some general things that
|
||||
// belong nowhere else and includes the interesting headers.
|
||||
//
|
||||
// Find more information in the "guidelines/GettingStarted" file.
|
||||
|
||||
|
||||
#ifndef YOSYS_H
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
* mmap compatibility
|
||||
*/
|
||||
-#if defined __MINGW32__
|
||||
+#if defined __CYGWIN__ || defined __MINGW32__ || defined _MSC_VER
|
||||
+#if defined __MINGW32__ || defined _MSC_VER
|
||||
#include <limits.h>
|
||||
#define fstMmap(__addr,__len,__prot,__flags,__fd,__off) fstMmap2((__len), (__fd), (__off))
|
||||
#define fstMunmap(__addr,__len) UnmapViewOfFile((LPCVOID)__addr)
|
||||
|
|
|
@ -341,7 +341,7 @@ return(NULL);
|
|||
/*
|
||||
* mmap compatibility
|
||||
*/
|
||||
#if defined __CYGWIN__ || defined __MINGW32__ || defined _MSC_VER
|
||||
#if defined __MINGW32__ || defined _MSC_VER
|
||||
#include <limits.h>
|
||||
#define fstMmap(__addr,__len,__prot,__flags,__fd,__off) fstMmap2((__len), (__fd), (__off))
|
||||
#define fstMunmap(__addr,__len) UnmapViewOfFile((LPCVOID)__addr)
|
||||
|
|
|
@ -53,6 +53,9 @@ OBJS += passes/cmds/future.o
|
|||
OBJS += passes/cmds/box_derive.o
|
||||
OBJS += passes/cmds/example_dt.o
|
||||
OBJS += passes/cmds/portarcs.o
|
||||
|
||||
OBJS += passes/cmds/activity.o
|
||||
OBJS += passes/cmds/splitnetlist.o
|
||||
OBJS += passes/cmds/reconstructbusses.o
|
||||
|
||||
OBJS += passes/cmds/wrapcell.o
|
||||
|
|
170
passes/cmds/wrapcell.cc
Normal file
170
passes/cmds/wrapcell.cc
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) 2024 Martin Povišer <povik@cutebit.org>
|
||||
*
|
||||
* 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/celltypes.h"
|
||||
#include "backends/rtlil/rtlil_backend.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
std::optional<std::string> format(std::string fmt, const dict<IdString, Const> ¶meters)
|
||||
{
|
||||
std::stringstream result;
|
||||
|
||||
auto it = fmt.begin();
|
||||
while (it != fmt.end()) {
|
||||
if (*it == '{') {
|
||||
it++;
|
||||
auto beg = it;
|
||||
while (it != fmt.end() && *it != '}') it++;
|
||||
if (it == fmt.end()) {
|
||||
log("Unclosed curly brackets in format string '%s'\n", fmt.c_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
auto id = RTLIL::escape_id(std::string(beg, it));
|
||||
if (!parameters.count(id)) {
|
||||
log("Parameter %s referenced in format string '%s' not found\n", log_id(id), fmt.c_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
RTLIL_BACKEND::dump_const(result, parameters.at(id));
|
||||
} else {
|
||||
result << *it;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return {result.str()};
|
||||
}
|
||||
|
||||
struct WrapcellPass : Pass {
|
||||
WrapcellPass() : Pass("wrapcell", "wrap individual cells into new modules") {}
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" wrapcell -name <format> [selection]\n");
|
||||
log("\n");
|
||||
log("This command wraps the selected cells individually into modules. The name for\n");
|
||||
log("each wrapper module is derived from the template <format> by substituting\n");
|
||||
log("parameter values as specified in curly brackets. If the named module already\n");
|
||||
log("exists, it is reused.\n");
|
||||
log("\n");
|
||||
log(" -setattr <attribute-name>\n");
|
||||
log(" set the given boolean attribute on each created wrapper module\n");
|
||||
log("\n");
|
||||
log(" -formatattr <attribute-name> <format>\n");
|
||||
log(" set a string attribute on the created wrapper module by substituting\n");
|
||||
log(" parameter values into <format>\n");
|
||||
log("\n");
|
||||
log("Currently this command only supports wrapping internal cell types.\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void execute(std::vector<std::string> args, Design *d) override
|
||||
{
|
||||
log_header(d, "Executing WRAPCELL pass. (wrap selected cells)\n");
|
||||
|
||||
struct AttrRule {
|
||||
IdString name;
|
||||
std::string value_fmt;
|
||||
|
||||
AttrRule(IdString name, std::string value_fmt)
|
||||
: name(name), value_fmt(value_fmt) {}
|
||||
};
|
||||
std::vector<AttrRule> attributes;
|
||||
std::string name_fmt;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||
if (args[argidx] == "-setattr" && argidx+1 < args.size()) {
|
||||
attributes.emplace_back(RTLIL::escape_id(args[++argidx]), "");
|
||||
} else if (args[argidx] == "-formatattr" && argidx+2 < args.size()) {
|
||||
IdString id = RTLIL::escape_id(args[++argidx]);
|
||||
attributes.emplace_back(id, args[++argidx]);
|
||||
} else if (args[argidx] == "-name" && argidx+1 < args.size()) {
|
||||
name_fmt = args[++argidx];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
extra_args(args, argidx, d);
|
||||
|
||||
if (name_fmt.empty())
|
||||
log_cmd_error("Argument -name required");
|
||||
|
||||
CellTypes ct;
|
||||
ct.setup();
|
||||
|
||||
for (auto module : d->selected_modules()) {
|
||||
for (auto cell : module->selected_cells()) {
|
||||
std::optional<std::string> unescaped_name = format(name_fmt, cell->parameters);
|
||||
if (!unescaped_name)
|
||||
log_error("Formatting error when processing cell '%s' in module '%s'\n",
|
||||
log_id(cell), log_id(module));
|
||||
|
||||
IdString name = RTLIL::escape_id(unescaped_name.value());
|
||||
|
||||
if (d->module(name)) {
|
||||
cell->type = name;
|
||||
cell->parameters.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ct.cell_known(cell->type))
|
||||
log_error("Non-internal cell type '%s' on cell '%s' in module '%s' unsupported\n",
|
||||
log_id(cell->type), log_id(cell), log_id(module));
|
||||
|
||||
Module *subm = d->addModule(name);
|
||||
Cell *subcell = subm->addCell("$1", cell->type);
|
||||
for (auto conn : cell->connections()) {
|
||||
Wire *w = subm->addWire(conn.first, conn.second.size());
|
||||
if (ct.cell_output(cell->type, w->name))
|
||||
w->port_output = true;
|
||||
else
|
||||
w->port_input = true;
|
||||
subcell->setPort(conn.first, w);
|
||||
}
|
||||
subcell->parameters = cell->parameters;
|
||||
subm->fixup_ports();
|
||||
|
||||
for (auto rule : attributes) {
|
||||
if (rule.value_fmt.empty()) {
|
||||
subm->set_bool_attribute(rule.name);
|
||||
} else {
|
||||
std::optional<std::string> value = format(rule.value_fmt, cell->parameters);
|
||||
|
||||
if (!value)
|
||||
log_error("Formatting error when processing cell '%s' in module '%s'\n",
|
||||
log_id(cell), log_id(module));
|
||||
|
||||
subm->set_string_attribute(rule.name, value.value());
|
||||
}
|
||||
}
|
||||
|
||||
cell->type = name;
|
||||
cell->parameters.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
} WrapcellPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -54,7 +54,7 @@ static void implement_pattern_cache(RTLIL::Module *module, std::map<RTLIL::Const
|
|||
RTLIL::Const pattern = it.first;
|
||||
RTLIL::SigSpec eq_sig_a, eq_sig_b, or_sig;
|
||||
|
||||
for (size_t j = 0; j < pattern.size(); j++)
|
||||
for (auto j = 0; j < pattern.size(); j++)
|
||||
if (pattern[j] == RTLIL::State::S0 || pattern[j] == RTLIL::State::S1) {
|
||||
eq_sig_a.append(ctrl_in.extract(j, 1));
|
||||
eq_sig_b.append(RTLIL::SigSpec(pattern[j]));
|
||||
|
@ -198,7 +198,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
|
|||
RTLIL::Const state = fsm_data.state_table[i];
|
||||
RTLIL::SigSpec sig_a, sig_b;
|
||||
|
||||
for (size_t j = 0; j < state.size(); j++)
|
||||
for (auto j = 0; j < state.size(); j++)
|
||||
if (state[j] == RTLIL::State::S0 || state[j] == RTLIL::State::S1) {
|
||||
sig_a.append(RTLIL::SigSpec(state_wire, j));
|
||||
sig_b.append(RTLIL::SigSpec(state[j]));
|
||||
|
@ -261,7 +261,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module)
|
|||
for (size_t i = 0; i < fsm_data.state_table.size(); i++) {
|
||||
RTLIL::Const state = fsm_data.state_table[i];
|
||||
int bit_idx = -1;
|
||||
for (size_t j = 0; j < state.size(); j++)
|
||||
for (auto j = 0; j < state.size(); j++)
|
||||
if (state[j] == RTLIL::State::S1)
|
||||
bit_idx = j;
|
||||
if (bit_idx >= 0)
|
||||
|
|
|
@ -23,20 +23,80 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
struct ThresholdHierarchyKeeping {
|
||||
Design *design;
|
||||
CellCosts costs;
|
||||
dict<Module *, int> done;
|
||||
pool<Module *> in_progress;
|
||||
uint64_t threshold;
|
||||
|
||||
ThresholdHierarchyKeeping(Design *design, uint64_t threshold)
|
||||
: design(design), costs(design), threshold(threshold) {}
|
||||
|
||||
uint64_t visit(RTLIL::Module *module) {
|
||||
if (module->has_attribute(ID(gate_cost_equivalent)))
|
||||
return module->attributes[ID(gate_cost_equivalent)].as_int();
|
||||
|
||||
if (module->has_attribute(ID(keep_hierarchy)))
|
||||
return 0;
|
||||
|
||||
if (module->get_blackbox_attribute())
|
||||
log_error("Missing cost information on instanced blackbox %s\n", log_id(module));
|
||||
|
||||
if (done.count(module))
|
||||
return done.at(module);
|
||||
|
||||
if (in_progress.count(module))
|
||||
log_error("Circular hierarchy\n");
|
||||
in_progress.insert(module);
|
||||
|
||||
uint64_t size = 0;
|
||||
module->has_processes_warn();
|
||||
|
||||
for (auto cell : module->cells()) {
|
||||
if (!cell->type.isPublic()) {
|
||||
size += costs.get(cell);
|
||||
} else {
|
||||
RTLIL::Module *submodule = design->module(cell->type);
|
||||
if (!submodule)
|
||||
log_error("Hierarchy contains unknown module '%s' (instanced as %s in %s)\n",
|
||||
log_id(cell->type), log_id(cell), log_id(module));
|
||||
size += visit(submodule);
|
||||
}
|
||||
}
|
||||
|
||||
if (size > threshold) {
|
||||
log("Keeping %s (estimated size above threshold: %llu > %llu).\n", log_id(module), size, threshold);
|
||||
module->set_bool_attribute(ID::keep_hierarchy);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
in_progress.erase(module);
|
||||
done[module] = size;
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
struct KeepHierarchyPass : public Pass {
|
||||
KeepHierarchyPass() : Pass("keep_hierarchy", "add the keep_hierarchy attribute") {}
|
||||
KeepHierarchyPass() : Pass("keep_hierarchy", "selectively add the keep_hierarchy attribute") {}
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" keep_hierarchy [options]\n");
|
||||
log(" keep_hierarchy [options] [selection]\n");
|
||||
log("\n");
|
||||
log("Add the keep_hierarchy attribute.\n");
|
||||
log("\n");
|
||||
log(" -min_cost <min_cost>\n");
|
||||
log(" only add the attribute to modules estimated to have more\n");
|
||||
log(" than <min_cost> gates after simple techmapping. Intended\n");
|
||||
log(" for tuning trade-offs between quality and yosys runtime.\n");
|
||||
log(" only add the attribute to modules estimated to have more than <min_cost>\n");
|
||||
log(" gates after simple techmapping. Intended for tuning trade-offs between\n");
|
||||
log(" quality and yosys runtime.\n");
|
||||
log("\n");
|
||||
log(" When evaluating a module's cost, gates which are within a submodule\n");
|
||||
log(" which is marked with the keep_hierarchy attribute are not counted\n");
|
||||
log(" towards the upper module's cost. This applies to both when the attribute\n");
|
||||
log(" was added by this command or was pre-existing.\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override
|
||||
{
|
||||
|
@ -54,16 +114,15 @@ struct KeepHierarchyPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
CellCosts costs(design);
|
||||
if (min_cost) {
|
||||
RTLIL::Module *top = design->top_module();
|
||||
if (!top)
|
||||
log_cmd_error("'-min_cost' mode requires a single top module in the design\n");
|
||||
|
||||
for (auto module : design->selected_modules()) {
|
||||
if (min_cost) {
|
||||
unsigned int cost = costs.get(module);
|
||||
if (cost > min_cost) {
|
||||
log("Marking %s (module too big: %d > %d).\n", log_id(module), cost, min_cost);
|
||||
module->set_bool_attribute(ID::keep_hierarchy);
|
||||
}
|
||||
} else {
|
||||
ThresholdHierarchyKeeping worker(design, min_cost);
|
||||
worker.visit(top);
|
||||
} else {
|
||||
for (auto module : design->selected_modules()) {
|
||||
log("Marking %s.\n", log_id(module));
|
||||
module->set_bool_attribute(ID::keep_hierarchy);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ synth -top my_design -booth
|
|||
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/yosys.h"
|
||||
#include "kernel/macc.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
@ -207,12 +208,33 @@ struct BoothPassWorker {
|
|||
void run()
|
||||
{
|
||||
for (auto cell : module->selected_cells()) {
|
||||
if (cell->type != ID($mul))
|
||||
continue;
|
||||
SigSpec A, B, Y;
|
||||
bool is_signed;
|
||||
|
||||
if (cell->type == ID($mul)) {
|
||||
A = cell->getPort(ID::A);
|
||||
B = cell->getPort(ID::B);
|
||||
Y = cell->getPort(ID::Y);
|
||||
|
||||
log_assert(cell->getParam(ID::A_SIGNED).as_bool() == cell->getParam(ID::B_SIGNED).as_bool());
|
||||
is_signed = cell->getParam(ID::A_SIGNED).as_bool();
|
||||
} else if (cell->type == ID($macc)) {
|
||||
Macc macc;
|
||||
macc.from_cell(cell);
|
||||
|
||||
if (!macc.is_simple_product()) {
|
||||
log_debug("Not mapping cell %s: not a simple macc cell\n", log_id(cell));
|
||||
continue;
|
||||
}
|
||||
|
||||
A = macc.ports[0].in_a;
|
||||
B = macc.ports[0].in_b;
|
||||
is_signed = macc.ports[0].is_signed;
|
||||
Y = cell->getPort(ID::Y);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
SigSpec A = cell->getPort(ID::A);
|
||||
SigSpec B = cell->getPort(ID::B);
|
||||
SigSpec Y = cell->getPort(ID::Y);
|
||||
int x_sz = GetSize(A), y_sz = GetSize(B), z_sz = GetSize(Y);
|
||||
|
||||
if (x_sz < 4 || y_sz < 4 || z_sz < 8) {
|
||||
|
@ -221,9 +243,6 @@ struct BoothPassWorker {
|
|||
continue;
|
||||
}
|
||||
|
||||
log_assert(cell->getParam(ID::A_SIGNED).as_bool() == cell->getParam(ID::B_SIGNED).as_bool());
|
||||
bool is_signed = cell->getParam(ID::A_SIGNED).as_bool();
|
||||
|
||||
log("Mapping cell %s to %s Booth multiplier\n", log_id(cell), is_signed ? "signed" : "unsigned");
|
||||
|
||||
// To simplify the generator size the arguments
|
||||
|
|
|
@ -40,29 +40,15 @@ ClockGateCell icg_from_arg(std::string& name, std::string& str) {
|
|||
}
|
||||
|
||||
static std::pair<std::optional<ClockGateCell>, std::optional<ClockGateCell>>
|
||||
find_icgs(std::string filename, std::vector<std::string> const& dont_use_cells) {
|
||||
std::ifstream f;
|
||||
f.open(filename.c_str());
|
||||
if (f.fail())
|
||||
log_cmd_error("Can't open liberty file `%s': %s\n", filename.c_str(), strerror(errno));
|
||||
LibertyParser libparser(f);
|
||||
f.close();
|
||||
auto ast = libparser.ast;
|
||||
|
||||
find_icgs(std::vector<const LibertyAst *> cells, std::vector<std::string> const& dont_use_cells) {
|
||||
// We will pick the most suitable ICG absed on tie_lo count and area
|
||||
struct ICGRankable : public ClockGateCell { double area; };
|
||||
std::optional<ICGRankable> best_pos;
|
||||
std::optional<ICGRankable> best_neg;
|
||||
|
||||
if (ast->id != "library")
|
||||
log_error("Format error in liberty file.\n");
|
||||
|
||||
// This is a lot of boilerplate, isn't it?
|
||||
for (auto cell : ast->children)
|
||||
for (auto cell : cells)
|
||||
{
|
||||
if (cell->id != "cell" || cell->args.size() != 1)
|
||||
continue;
|
||||
|
||||
const LibertyAst *dn = cell->find("dont_use");
|
||||
if (dn != nullptr && dn->value == "true")
|
||||
continue;
|
||||
|
@ -223,7 +209,7 @@ struct ClockgatePass : public Pass {
|
|||
log(" cell with ports named <ce>, <clk>, <gclk>.\n");
|
||||
log(" The ICG's clock enable pin must be active high.\n");
|
||||
log(" -liberty <filename>\n");
|
||||
log(" If specified, ICGs will be selected from the liberty file\n");
|
||||
log(" If specified, ICGs will be selected from the liberty files\n");
|
||||
log(" if available. Priority is given to cells with fewer tie_lo\n");
|
||||
log(" inputs and smaller size. This removes the need to manually\n");
|
||||
log(" specify -pos or -neg and -tie_lo.\n");
|
||||
|
@ -281,7 +267,7 @@ struct ClockgatePass : public Pass {
|
|||
std::optional<ClockGateCell> pos_icg_desc;
|
||||
std::optional<ClockGateCell> neg_icg_desc;
|
||||
std::vector<std::string> tie_lo_pins;
|
||||
std::string liberty_file;
|
||||
std::vector<std::string> liberty_files;
|
||||
std::vector<std::string> dont_use_cells;
|
||||
int min_net_size = 0;
|
||||
|
||||
|
@ -291,18 +277,23 @@ struct ClockgatePass : public Pass {
|
|||
auto name = args[++argidx];
|
||||
auto rest = args[++argidx];
|
||||
pos_icg_desc = icg_from_arg(name, rest);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-neg" && argidx+2 < args.size()) {
|
||||
auto name = args[++argidx];
|
||||
auto rest = args[++argidx];
|
||||
neg_icg_desc = icg_from_arg(name, rest);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-tie_lo" && argidx+1 < args.size()) {
|
||||
tie_lo_pins.push_back(RTLIL::escape_id(args[++argidx]));
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-liberty" && argidx+1 < args.size()) {
|
||||
liberty_file = args[++argidx];
|
||||
std::string liberty_file = args[++argidx];
|
||||
rewrite_filename(liberty_file);
|
||||
liberty_files.push_back(liberty_file);
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dont_use" && argidx+1 < args.size()) {
|
||||
dont_use_cells.push_back(args[++argidx]);
|
||||
|
@ -310,13 +301,25 @@ struct ClockgatePass : public Pass {
|
|||
}
|
||||
if (args[argidx] == "-min_net_size" && argidx+1 < args.size()) {
|
||||
min_net_size = atoi(args[++argidx].c_str());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!liberty_file.empty())
|
||||
if (!liberty_files.empty()) {
|
||||
LibertyMergedCells merged;
|
||||
for (auto path : liberty_files) {
|
||||
std::ifstream f;
|
||||
f.open(path.c_str());
|
||||
if (f.fail())
|
||||
log_cmd_error("Can't open liberty file `%s': %s\n", path.c_str(), strerror(errno));
|
||||
LibertyParser p(f);
|
||||
merged.merge(p);
|
||||
f.close();
|
||||
}
|
||||
std::tie(pos_icg_desc, neg_icg_desc) =
|
||||
find_icgs(liberty_file, dont_use_cells);
|
||||
else {
|
||||
find_icgs(merged.cells, dont_use_cells);
|
||||
} else {
|
||||
for (auto pin : tie_lo_pins) {
|
||||
if (pos_icg_desc)
|
||||
pos_icg_desc->tie_lo_pins.push_back(pin);
|
||||
|
|
|
@ -229,7 +229,7 @@ static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::strin
|
|||
return false;
|
||||
}
|
||||
|
||||
static void find_cell(const LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool has_enable, bool enapol, std::vector<std::string> &dont_use_cells)
|
||||
static void find_cell(std::vector<const LibertyAst *> cells, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool has_enable, bool enapol, std::vector<std::string> &dont_use_cells)
|
||||
{
|
||||
const LibertyAst *best_cell = nullptr;
|
||||
std::map<std::string, char> best_cell_ports;
|
||||
|
@ -237,14 +237,8 @@ static void find_cell(const LibertyAst *ast, IdString cell_type, bool clkpol, bo
|
|||
bool best_cell_noninv = false;
|
||||
double best_cell_area = 0;
|
||||
|
||||
if (ast->id != "library")
|
||||
log_error("Format error in liberty file.\n");
|
||||
|
||||
for (auto cell : ast->children)
|
||||
for (auto cell : cells)
|
||||
{
|
||||
if (cell->id != "cell" || cell->args.size() != 1)
|
||||
continue;
|
||||
|
||||
const LibertyAst *dn = cell->find("dont_use");
|
||||
if (dn != nullptr && dn->value == "true")
|
||||
continue;
|
||||
|
@ -355,7 +349,7 @@ static void find_cell(const LibertyAst *ast, IdString cell_type, bool clkpol, bo
|
|||
}
|
||||
}
|
||||
|
||||
static void find_cell_sr(const LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool has_enable, bool enapol, std::vector<std::string> &dont_use_cells)
|
||||
static void find_cell_sr(std::vector<const LibertyAst *> cells, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool has_enable, bool enapol, std::vector<std::string> &dont_use_cells)
|
||||
{
|
||||
const LibertyAst *best_cell = nullptr;
|
||||
std::map<std::string, char> best_cell_ports;
|
||||
|
@ -365,14 +359,8 @@ static void find_cell_sr(const LibertyAst *ast, IdString cell_type, bool clkpol,
|
|||
|
||||
log_assert(!enapol && "set/reset cell with enable is unimplemented due to lack of cells for testing");
|
||||
|
||||
if (ast->id != "library")
|
||||
log_error("Format error in liberty file.\n");
|
||||
|
||||
for (auto cell : ast->children)
|
||||
for (auto cell : cells)
|
||||
{
|
||||
if (cell->id != "cell" || cell->args.size() != 1)
|
||||
continue;
|
||||
|
||||
const LibertyAst *dn = cell->find("dont_use");
|
||||
if (dn != nullptr && dn->value == "true")
|
||||
continue;
|
||||
|
@ -561,7 +549,7 @@ struct DfflibmapPass : public Pass {
|
|||
log(" dfflibmap [-prepare] [-map-only] [-info] [-dont_use <cell_name>] -liberty <file> [selection]\n");
|
||||
log("\n");
|
||||
log("Map internal flip-flop cells to the flip-flop cells in the technology\n");
|
||||
log("library specified in the given liberty file.\n");
|
||||
log("library specified in the given liberty files.\n");
|
||||
log("\n");
|
||||
log("This pass may add inverters as needed. Therefore it is recommended to\n");
|
||||
log("first run this pass and then map the logic paths to the target technology.\n");
|
||||
|
@ -590,11 +578,11 @@ struct DfflibmapPass : public Pass {
|
|||
log_header(design, "Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
|
||||
log_push();
|
||||
|
||||
std::string liberty_file;
|
||||
bool prepare_mode = false;
|
||||
bool map_only_mode = false;
|
||||
bool info_mode = false;
|
||||
|
||||
std::vector<std::string> liberty_files;
|
||||
std::vector<std::string> dont_use_cells;
|
||||
|
||||
size_t argidx;
|
||||
|
@ -602,8 +590,9 @@ struct DfflibmapPass : public Pass {
|
|||
{
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-liberty" && argidx+1 < args.size()) {
|
||||
liberty_file = args[++argidx];
|
||||
std::string liberty_file = args[++argidx];
|
||||
rewrite_filename(liberty_file);
|
||||
liberty_files.push_back(liberty_file);
|
||||
continue;
|
||||
}
|
||||
if (arg == "-prepare") {
|
||||
|
@ -636,41 +625,45 @@ struct DfflibmapPass : public Pass {
|
|||
if (modes > 1)
|
||||
log_cmd_error("Only one of -prepare, -map-only, or -info options should be given!\n");
|
||||
|
||||
if (liberty_file.empty())
|
||||
if (liberty_files.empty())
|
||||
log_cmd_error("Missing `-liberty liberty_file' option!\n");
|
||||
|
||||
std::ifstream f;
|
||||
f.open(liberty_file.c_str());
|
||||
if (f.fail())
|
||||
log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file.c_str(), strerror(errno));
|
||||
LibertyParser libparser(f);
|
||||
f.close();
|
||||
LibertyMergedCells merged;
|
||||
for (auto path : liberty_files) {
|
||||
std::ifstream f;
|
||||
f.open(path.c_str());
|
||||
if (f.fail())
|
||||
log_cmd_error("Can't open liberty file `%s': %s\n", path.c_str(), strerror(errno));
|
||||
LibertyParser p(f);
|
||||
merged.merge(p);
|
||||
f.close();
|
||||
}
|
||||
|
||||
find_cell(libparser.ast, ID($_DFF_N_), false, false, false, false, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_P_), true, false, false, false, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_N_), false, false, false, false, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_P_), true, false, false, false, false, false, dont_use_cells);
|
||||
|
||||
find_cell(libparser.ast, ID($_DFF_NN0_), false, true, false, false, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_NN1_), false, true, false, true, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_NP0_), false, true, true, false, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_NP1_), false, true, true, true, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_PN0_), true, true, false, false, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_PN1_), true, true, false, true, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_PP0_), true, true, true, false, false, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFF_PP1_), true, true, true, true, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_NN0_), false, true, false, false, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_NN1_), false, true, false, true, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_NP0_), false, true, true, false, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_NP1_), false, true, true, true, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_PN0_), true, true, false, false, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_PN1_), true, true, false, true, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_PP0_), true, true, true, false, false, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFF_PP1_), true, true, true, true, false, false, dont_use_cells);
|
||||
|
||||
find_cell(libparser.ast, ID($_DFFE_NN_), false, false, false, false, true, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFFE_NP_), false, false, false, false, true, true, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFFE_PN_), true, false, false, false, true, false, dont_use_cells);
|
||||
find_cell(libparser.ast, ID($_DFFE_PP_), true, false, false, false, true, true, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFFE_NN_), false, false, false, false, true, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFFE_NP_), false, false, false, false, true, true, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFFE_PN_), true, false, false, false, true, false, dont_use_cells);
|
||||
find_cell(merged.cells, ID($_DFFE_PP_), true, false, false, false, true, true, dont_use_cells);
|
||||
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_NNN_), false, false, false, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_NNP_), false, false, true, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_NPN_), false, true, false, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_NPP_), false, true, true, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_PNN_), true, false, false, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_PNP_), true, false, true, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_PPN_), true, true, false, false, false, dont_use_cells);
|
||||
find_cell_sr(libparser.ast, ID($_DFFSR_PPP_), true, true, true, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_NNN_), false, false, false, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_NNP_), false, false, true, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_NPN_), false, true, false, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_NPP_), false, true, true, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_PNN_), true, false, false, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_PNP_), true, false, true, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_PPN_), true, true, false, false, false, dont_use_cells);
|
||||
find_cell_sr(merged.cells, ID($_DFFSR_PPP_), true, true, true, false, false, dont_use_cells);
|
||||
|
||||
log(" final dff cell mappings:\n");
|
||||
logmap_all();
|
||||
|
|
|
@ -517,12 +517,12 @@ LibertyAst *LibertyParser::parse()
|
|||
|
||||
#ifndef FILTERLIB
|
||||
|
||||
void LibertyParser::error()
|
||||
void LibertyParser::error() const
|
||||
{
|
||||
log_error("Syntax error in liberty file on line %d.\n", line);
|
||||
}
|
||||
|
||||
void LibertyParser::error(const std::string &str)
|
||||
void LibertyParser::error(const std::string &str) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Syntax error in liberty file on line " << line << ".\n";
|
||||
|
@ -532,13 +532,13 @@ void LibertyParser::error(const std::string &str)
|
|||
|
||||
#else
|
||||
|
||||
void LibertyParser::error()
|
||||
void LibertyParser::error() const
|
||||
{
|
||||
fprintf(stderr, "Syntax error in liberty file on line %d.\n", line);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void LibertyParser::error(const std::string &str)
|
||||
void LibertyParser::error(const std::string &str) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Syntax error in liberty file on line " << line << ".\n";
|
||||
|
|
|
@ -86,8 +86,10 @@ namespace Yosys
|
|||
bool eval(dict<std::string, bool>& values);
|
||||
};
|
||||
|
||||
class LibertyMergedCells;
|
||||
class LibertyParser
|
||||
{
|
||||
friend class LibertyMergedCells;
|
||||
private:
|
||||
std::istream &f;
|
||||
int line;
|
||||
|
@ -98,10 +100,10 @@ namespace Yosys
|
|||
anything else is a single character.
|
||||
*/
|
||||
int lexer(std::string &str);
|
||||
|
||||
|
||||
LibertyAst *parse();
|
||||
void error();
|
||||
void error(const std::string &str);
|
||||
void error() const;
|
||||
void error(const std::string &str) const;
|
||||
|
||||
public:
|
||||
const LibertyAst *ast;
|
||||
|
@ -109,6 +111,35 @@ namespace Yosys
|
|||
LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
|
||||
~LibertyParser() { if (ast) delete ast; }
|
||||
};
|
||||
|
||||
class LibertyMergedCells
|
||||
{
|
||||
std::vector<const LibertyAst *> asts;
|
||||
|
||||
public:
|
||||
std::vector<const LibertyAst *> cells;
|
||||
void merge(LibertyParser &parser)
|
||||
{
|
||||
if (parser.ast) {
|
||||
const LibertyAst *ast = parser.ast;
|
||||
asts.push_back(ast);
|
||||
// The parser no longer owns its top level ast, but we do.
|
||||
// sketchy zone
|
||||
parser.ast = nullptr;
|
||||
if (ast->id != "library")
|
||||
parser.error("Top level entity isn't \"library\".\n");
|
||||
for (const LibertyAst *cell : ast->children)
|
||||
if (cell->id == "cell" && cell->args.size() == 1)
|
||||
cells.push_back(cell);
|
||||
}
|
||||
}
|
||||
~LibertyMergedCells()
|
||||
{
|
||||
for (auto ast : asts)
|
||||
delete ast;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1038,6 +1038,9 @@ struct TechmapPass : public Pass {
|
|||
log(" map file. Note that the Verilog frontend is also called with the\n");
|
||||
log(" '-nooverwrite' option set.\n");
|
||||
log("\n");
|
||||
log(" -dont_map <celltype>\n");
|
||||
log(" leave the given cell type unmapped by ignoring any mapping rules for it\n");
|
||||
log("\n");
|
||||
log("When a module in the map file has the 'techmap_celltype' attribute set, it will\n");
|
||||
log("match cells with a type that match the text value of this attribute. Otherwise\n");
|
||||
log("the module name will be used to match the cell. Multiple space-separated cell\n");
|
||||
|
@ -1169,6 +1172,7 @@ struct TechmapPass : public Pass {
|
|||
simplemap_get_mappers(worker.simplemap_mappers);
|
||||
|
||||
std::vector<std::string> map_files;
|
||||
std::vector<RTLIL::IdString> dont_map;
|
||||
std::string verilog_frontend = "verilog -nooverwrite -noblackbox";
|
||||
int max_iter = -1;
|
||||
|
||||
|
@ -1210,6 +1214,10 @@ struct TechmapPass : public Pass {
|
|||
worker.ignore_wb = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-dont_map" && argidx+1 < args.size()) {
|
||||
dont_map.push_back(RTLIL::escape_id(args[++argidx]));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
@ -1266,6 +1274,11 @@ struct TechmapPass : public Pass {
|
|||
celltypeMap[module_name].insert(module->name);
|
||||
}
|
||||
}
|
||||
|
||||
// Erase any rules disabled with a -dont_map argument
|
||||
for (auto type : dont_map)
|
||||
celltypeMap.erase(type);
|
||||
|
||||
log_debug("Cell type mappings to use:\n");
|
||||
for (auto &i : celltypeMap) {
|
||||
i.second.sort(RTLIL::sort_by_id_str());
|
||||
|
|
|
@ -37,3 +37,4 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v))
|
|||
$(eval $(call add_share_file,share,techlibs/common/cmp2softlogic.v))
|
||||
$(eval $(call add_share_file,share/choices,techlibs/common/choices/kogge-stone.v))
|
||||
$(eval $(call add_share_file,share/choices,techlibs/common/choices/han-carlson.v))
|
||||
$(eval $(call add_share_file,share/choices,techlibs/common/choices/sklansky.v))
|
||||
|
|
37
techlibs/common/choices/sklansky.v
Normal file
37
techlibs/common/choices/sklansky.v
Normal file
|
@ -0,0 +1,37 @@
|
|||
(* techmap_celltype = "$lcu" *)
|
||||
module _80_lcu_sklansky (P, G, CI, CO);
|
||||
parameter WIDTH = 2;
|
||||
|
||||
(* force_downto *)
|
||||
input [WIDTH-1:0] P, G;
|
||||
input CI;
|
||||
|
||||
(* force_downto *)
|
||||
output [WIDTH-1:0] CO;
|
||||
|
||||
integer i, j;
|
||||
(* force_downto *)
|
||||
reg [WIDTH-1:0] p, g;
|
||||
|
||||
wire [1023:0] _TECHMAP_DO_ = "proc; opt -fast";
|
||||
|
||||
always @* begin
|
||||
p = P;
|
||||
g = G;
|
||||
|
||||
// in almost all cases CI will be constant zero
|
||||
g[0] = g[0] | (p[0] & CI);
|
||||
|
||||
for (i = 0; i < $clog2(WIDTH); i = i + 1) begin
|
||||
// iterate in reverse so we don't confuse a result from this stage and the previous
|
||||
for (j = WIDTH - 1; j >= 0; j = j - 1) begin
|
||||
if (j & 2**i) begin
|
||||
g[j] = g[j] | p[j] & g[(j & ~(2**i - 1)) - 1];
|
||||
p[j] = p[j] & p[(j & ~(2**i - 1)) - 1];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign CO = g;
|
||||
endmodule
|
|
@ -60,7 +60,7 @@ struct QlDspSimdPass : public Pass {
|
|||
|
||||
// ..........................................
|
||||
|
||||
const size_t m_ModeBitsSize = 80;
|
||||
const int m_ModeBitsSize = 80;
|
||||
|
||||
// DSP parameters
|
||||
const std::vector<std::string> m_DspParams = {"COEFF_3", "COEFF_2", "COEFF_1", "COEFF_0"};
|
||||
|
|
|
@ -10,8 +10,11 @@ module sync_rom #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
|
|||
reg [WORD:0] data_out_r;
|
||||
reg [WORD:0] memory [0:DEPTH];
|
||||
|
||||
integer i,j = 64'hF4B1CA8127865242;
|
||||
initial
|
||||
integer i,j;
|
||||
// Initialize in initial block as a workaround for
|
||||
// https://github.com/YosysHQ/yosys/issues/4792
|
||||
initial begin
|
||||
j = 64'hF4B1CA8127865242;
|
||||
for (i = 0; i <= DEPTH; i++) begin
|
||||
// In case this ROM will be implemented in fabric: fill the memory with some data
|
||||
// uncorrelated with the address, or Yosys might see through the ruse and e.g. not
|
||||
|
@ -21,6 +24,7 @@ module sync_rom #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
|
|||
j = j ^ (j << 25);
|
||||
j = j ^ (j >> 27);
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
data_out_r <= memory[address_in];
|
||||
|
|
|
@ -10,6 +10,19 @@ endmodule
|
|||
EOF
|
||||
booth
|
||||
sat -verify -set a 0 -set b 0 -prove y 0
|
||||
design -reset
|
||||
|
||||
test_cell -s 1694091355 -n 100 -script booth_map_script.ys_ $mul
|
||||
design -reset
|
||||
test_cell -s 1694091355 -n 100 -script booth_map_script.ys_ $mul
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOF
|
||||
module top(a,b,y);
|
||||
input wire [4:0] a;
|
||||
input wire [5:0] b;
|
||||
output wire [6:0] y;
|
||||
assign y = a * b;
|
||||
endmodule
|
||||
EOF
|
||||
synth -run :fine
|
||||
# test compatibility with alumacc
|
||||
equiv_opt -assert booth
|
||||
|
|
|
@ -235,6 +235,49 @@ select -module dffe_11 -assert-count 0 t:\$_NOT_
|
|||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# test multiple liberty files to behave the same way
|
||||
design -load before
|
||||
clockgate -liberty clockgate_pos.lib -liberty clockgate_neg.lib
|
||||
|
||||
# rising edge ICGs
|
||||
select -module dffe_00 -assert-count 0 t:\\pos_small
|
||||
select -module dffe_01 -assert-count 0 t:\\pos_small
|
||||
|
||||
select -module dffe_10 -assert-count 1 t:\\pos_small
|
||||
select -module dffe_11 -assert-count 1 t:\\pos_small
|
||||
|
||||
# falling edge ICGs
|
||||
select -module dffe_00 -assert-count 1 t:\\neg_small
|
||||
select -module dffe_01 -assert-count 1 t:\\neg_small
|
||||
|
||||
select -module dffe_10 -assert-count 0 t:\\neg_small
|
||||
select -module dffe_11 -assert-count 0 t:\\neg_small
|
||||
|
||||
# and nothing else
|
||||
select -module dffe_00 -assert-count 0 t:\\pos_big
|
||||
select -module dffe_01 -assert-count 0 t:\\pos_big
|
||||
select -module dffe_10 -assert-count 0 t:\\pos_big
|
||||
select -module dffe_11 -assert-count 0 t:\\pos_big
|
||||
select -module dffe_00 -assert-count 0 t:\\pos_small_tielo
|
||||
select -module dffe_01 -assert-count 0 t:\\pos_small_tielo
|
||||
select -module dffe_10 -assert-count 0 t:\\pos_small_tielo
|
||||
select -module dffe_11 -assert-count 0 t:\\pos_small_tielo
|
||||
select -module dffe_00 -assert-count 0 t:\\neg_big
|
||||
select -module dffe_01 -assert-count 0 t:\\neg_big
|
||||
select -module dffe_10 -assert-count 0 t:\\neg_big
|
||||
select -module dffe_11 -assert-count 0 t:\\neg_big
|
||||
select -module dffe_00 -assert-count 0 t:\\neg_small_tielo
|
||||
select -module dffe_01 -assert-count 0 t:\\neg_small_tielo
|
||||
select -module dffe_10 -assert-count 0 t:\\neg_small_tielo
|
||||
select -module dffe_11 -assert-count 0 t:\\neg_small_tielo
|
||||
|
||||
# if necessary, EN is inverted, since the given ICG
|
||||
# is assumed to have an active-high EN
|
||||
select -module dffe_10 -assert-count 1 t:\$_NOT_
|
||||
select -module dffe_11 -assert-count 0 t:\$_NOT_
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
design -load before
|
||||
clockgate -liberty clockgate.lib -dont_use pos_small -dont_use neg_small
|
||||
|
||||
|
|
55
tests/techmap/clockgate_neg.lib
Normal file
55
tests/techmap/clockgate_neg.lib
Normal file
|
@ -0,0 +1,55 @@
|
|||
library(test) {
|
||||
/* Integrated clock gating cells */
|
||||
cell (neg_big) {
|
||||
area : 10;
|
||||
clock_gating_integrated_cell : latch_negedge;
|
||||
pin (GCLK) {
|
||||
clock_gate_out_pin : true;
|
||||
direction : output;
|
||||
}
|
||||
pin (CLK) {
|
||||
clock_gate_clock_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (CE) {
|
||||
clock_gate_enable_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
}
|
||||
cell (neg_small_tielo) {
|
||||
area : 1;
|
||||
clock_gating_integrated_cell : latch_negedge_precontrol;
|
||||
pin (GCLK) {
|
||||
clock_gate_out_pin : true;
|
||||
direction : output;
|
||||
}
|
||||
pin (CLK) {
|
||||
clock_gate_clock_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (CE) {
|
||||
clock_gate_enable_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (SE) {
|
||||
clock_gate_test_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
}
|
||||
cell (neg_small) {
|
||||
area : 1;
|
||||
clock_gating_integrated_cell : latch_negedge;
|
||||
pin (GCLK) {
|
||||
clock_gate_out_pin : true;
|
||||
direction : output;
|
||||
}
|
||||
pin (CLK) {
|
||||
clock_gate_clock_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (CE) {
|
||||
clock_gate_enable_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
}
|
||||
}
|
55
tests/techmap/clockgate_pos.lib
Normal file
55
tests/techmap/clockgate_pos.lib
Normal file
|
@ -0,0 +1,55 @@
|
|||
library(test) {
|
||||
/* Integrated clock gating cells */
|
||||
cell (pos_small_tielo) {
|
||||
area : 1;
|
||||
clock_gating_integrated_cell : latch_posedge_precontrol;
|
||||
pin (GCLK) {
|
||||
clock_gate_out_pin : true;
|
||||
direction : output;
|
||||
}
|
||||
pin (CLK) {
|
||||
clock_gate_clock_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (CE) {
|
||||
clock_gate_enable_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (SE) {
|
||||
clock_gate_test_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
}
|
||||
cell (pos_big) {
|
||||
area : 10;
|
||||
clock_gating_integrated_cell : latch_posedge;
|
||||
pin (GCLK) {
|
||||
clock_gate_out_pin : true;
|
||||
direction : output;
|
||||
}
|
||||
pin (CLK) {
|
||||
clock_gate_clock_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (CE) {
|
||||
clock_gate_enable_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
}
|
||||
cell (pos_small) {
|
||||
area : 1;
|
||||
clock_gating_integrated_cell : latch_posedge;
|
||||
pin (GCLK) {
|
||||
clock_gate_out_pin : true;
|
||||
direction : output;
|
||||
}
|
||||
pin (CLK) {
|
||||
clock_gate_clock_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
pin (CE) {
|
||||
clock_gate_enable_pin : true;
|
||||
direction : input;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,6 +59,16 @@ select -assert-count 1 t:dffn
|
|||
select -assert-count 4 t:dffsr
|
||||
select -assert-none t:dffn t:dffsr t:$_NOT_ %% %n t:* %i
|
||||
|
||||
design -load orig
|
||||
dfflibmap -prepare -liberty dfflibmap_dffn.lib -liberty dfflibmap_dffsr.lib
|
||||
dfflibmap -map-only -liberty dfflibmap_dffn.lib -liberty dfflibmap_dffsr.lib
|
||||
clean
|
||||
|
||||
select -assert-count 4 t:$_NOT_
|
||||
select -assert-count 1 t:dffn
|
||||
select -assert-count 4 t:dffsr
|
||||
select -assert-none t:dffn t:dffsr t:$_NOT_ %% %n t:* %i
|
||||
|
||||
design -load orig
|
||||
dfflibmap -liberty dfflibmap.lib -dont_use *ffn
|
||||
clean
|
||||
|
|
23
tests/techmap/dfflibmap_dffn.lib
Normal file
23
tests/techmap/dfflibmap_dffn.lib
Normal file
|
@ -0,0 +1,23 @@
|
|||
library(test) {
|
||||
cell (dffn) {
|
||||
area : 6;
|
||||
ff("IQ", "IQN") {
|
||||
next_state : "D";
|
||||
clocked_on : "!CLK";
|
||||
}
|
||||
pin(D) {
|
||||
direction : input;
|
||||
}
|
||||
pin(CLK) {
|
||||
direction : input;
|
||||
}
|
||||
pin(Q) {
|
||||
direction: output;
|
||||
function : "IQ";
|
||||
}
|
||||
pin(QN) {
|
||||
direction: output;
|
||||
function : "IQN";
|
||||
}
|
||||
}
|
||||
}
|
33
tests/techmap/dfflibmap_dffsr.lib
Normal file
33
tests/techmap/dfflibmap_dffsr.lib
Normal file
|
@ -0,0 +1,33 @@
|
|||
library(test) {
|
||||
cell (dffsr) {
|
||||
area : 6;
|
||||
ff("IQ", "IQN") {
|
||||
next_state : "D";
|
||||
clocked_on : "CLK";
|
||||
clear : "CLEAR";
|
||||
preset : "PRESET";
|
||||
clear_preset_var1 : L;
|
||||
clear_preset_var2 : L;
|
||||
}
|
||||
pin(D) {
|
||||
direction : input;
|
||||
}
|
||||
pin(CLK) {
|
||||
direction : input;
|
||||
}
|
||||
pin(CLEAR) {
|
||||
direction : input;
|
||||
}
|
||||
pin(PRESET) {
|
||||
direction : input;
|
||||
}
|
||||
pin(Q) {
|
||||
direction: output;
|
||||
function : "IQ";
|
||||
}
|
||||
pin(QN) {
|
||||
direction: output;
|
||||
function : "IQN";
|
||||
}
|
||||
}
|
||||
}
|
15
tests/techmap/sklansky.tcl
Normal file
15
tests/techmap/sklansky.tcl
Normal file
|
@ -0,0 +1,15 @@
|
|||
yosys -import
|
||||
|
||||
read_verilog +/choices/sklansky.v
|
||||
read_verilog -icells lcu_refined.v
|
||||
design -save init
|
||||
|
||||
for {set i 1} {$i <= 16} {incr i} {
|
||||
design -load init
|
||||
chparam -set WIDTH $i
|
||||
yosys proc
|
||||
opt_clean
|
||||
equiv_make lcu _80_lcu_sklansky equiv
|
||||
equiv_simple equiv
|
||||
equiv_status -assert equiv
|
||||
}
|
53
tests/various/keep_hierarchy.ys
Normal file
53
tests/various/keep_hierarchy.ys
Normal file
|
@ -0,0 +1,53 @@
|
|||
read_verilog <<EOF
|
||||
(* blackbox *)
|
||||
(* gate_cost_equivalent=150 *)
|
||||
module macro;
|
||||
endmodule
|
||||
|
||||
module branch1;
|
||||
macro inst1();
|
||||
macro inst2();
|
||||
macro inst3();
|
||||
endmodule
|
||||
|
||||
module branch2;
|
||||
macro inst1();
|
||||
macro inst2();
|
||||
macro inst3();
|
||||
macro inst4();
|
||||
endmodule
|
||||
|
||||
// branch3_submod on its own doesn't meet the threshold
|
||||
module branch3_submod();
|
||||
wire [2:0] y;
|
||||
wire [2:0] a;
|
||||
wire [2:0] b;
|
||||
assign y = a * b;
|
||||
endmodule
|
||||
|
||||
// on the other hand four branch3_submods do
|
||||
module branch3;
|
||||
branch3_submod inst1();
|
||||
branch3_submod inst2();
|
||||
branch3_submod inst3();
|
||||
branch3_submod inst4();
|
||||
endmodule
|
||||
|
||||
// wrapper should have zero cost when branch3 is marked
|
||||
// keep_hierarchy
|
||||
module branch3_wrapper;
|
||||
branch3 inst();
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
branch1 inst1();
|
||||
branch2 inst2();
|
||||
branch3_wrapper wrapper();
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
hierarchy -top top
|
||||
keep_hierarchy -min_cost 500
|
||||
select -assert-mod-count 2 A:keep_hierarchy
|
||||
select -assert-any A:keep_hierarchy branch2 %i
|
||||
select -assert-any A:keep_hierarchy branch3 %i
|
25
tests/various/wrapcell.ys
Normal file
25
tests/various/wrapcell.ys
Normal file
|
@ -0,0 +1,25 @@
|
|||
read_verilog <<EOF
|
||||
module top(
|
||||
input [1:0] a,
|
||||
input [2:0] b,
|
||||
output [2:0] y,
|
||||
input [2:0] a2,
|
||||
input [3:0] b2,
|
||||
output [3:0] y2,
|
||||
input [1:0] a3,
|
||||
input [2:0] b3,
|
||||
output [2:0] y3
|
||||
);
|
||||
assign y = a | (*keep*) b;
|
||||
assign y2 = a2 | (*keep*) b2;
|
||||
assign y3 = a3 | (*keep*) b3;
|
||||
endmodule
|
||||
EOF
|
||||
|
||||
wreduce
|
||||
wrapcell -setattr foo -formatattr bar w{Y_WIDTH} -name OR_{A_WIDTH}_{B_WIDTH}_{Y_WIDTH}
|
||||
select -assert-count 2 top/t:OR_2_3_3
|
||||
select -assert-count 1 top/t:OR_3_4_4
|
||||
select -assert-none top/t:OR_2_3_3 top/t:OR_3_4_4 %% top/t:* %D
|
||||
select -assert-mod-count 2 OR_2_3_3 OR_3_4_4
|
||||
select -assert-mod-count 2 A:bar=w3 A:bar=w4
|
Loading…
Reference in a new issue