mirror of https://github.com/YosysHQ/yosys.git
Tidy/reflow some things
This commit is contained in:
parent
2c75b103d6
commit
4b40372446
|
@ -189,13 +189,13 @@ values for the global asynchronous reset in an FPGA implementation. This design
|
||||||
can not be expressed in BLIF as it is. Instead we need to use a synthesis script
|
can not be expressed in BLIF as it is. Instead we need to use a synthesis script
|
||||||
that transforms this form to synchronous resets that can be expressed in BLIF.
|
that transforms this form to synchronous resets that can be expressed in BLIF.
|
||||||
|
|
||||||
(Note that there is no problem if this coding techniques are used to
|
(Note that there is no problem if this coding techniques are used to model ROM,
|
||||||
model ROM, where the register is initialized using this syntax but is
|
where the register is initialized using this syntax but is never updated
|
||||||
never updated otherwise.)
|
otherwise.)
|
||||||
|
|
||||||
:numref:`amber23.ys` shows the synthesis script for the Amber23 core. In line 17
|
:numref:`amber23.ys` shows the synthesis script for the Amber23 core. In line 17
|
||||||
the add command is used to add a 1-bit wide global input signal with the name
|
the add command is used to add a 1-bit wide global input signal with the name
|
||||||
globrst. That means that an input with that name is added to each module in the
|
``globrst``. That means that an input with that name is added to each module in the
|
||||||
design hierarchy and then all module instantiations are altered so that this new
|
design hierarchy and then all module instantiations are altered so that this new
|
||||||
signal is connected throughout the whole design hierarchy.
|
signal is connected throughout the whole design hierarchy.
|
||||||
|
|
||||||
|
@ -235,18 +235,18 @@ signal is connected throughout the whole design hierarchy.
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
In line 18 the proc command is called. But in this script the signal
|
In line 18 the ``proc`` command is called. But in this script the signal name
|
||||||
name globrst is passed to the command as a global reset signal for
|
globrst is passed to the command as a global reset signal for resetting the
|
||||||
resetting the registers to their assigned initial values.
|
registers to their assigned initial values.
|
||||||
|
|
||||||
Finally in line 19 the techmap command is used to replace all instances of
|
Finally in line 19 the techmap command is used to replace all instances of
|
||||||
flip-flops with asynchronous resets with flip-flops with synchronous resets. The
|
flip-flops with asynchronous resets with flip-flops with synchronous resets. The
|
||||||
map file used for this is shown in :numref:`adff2dff.v`. Note how the
|
map file used for this is shown in :numref:`adff2dff.v`. Note how the
|
||||||
techmap_celltype attribute is used in line 1 to tell the techmap command which
|
``techmap_celltype`` attribute is used in line 1 to tell the techmap command
|
||||||
cells to replace in the design, how the \_TECHMAP_FAIL\_ wire in lines 15 and 16
|
which cells to replace in the design, how the ``_TECHMAP_FAIL_`` wire in lines
|
||||||
(which evaluates to a constant value) determines if the parameter set is
|
15 and 16 (which evaluates to a constant value) determines if the parameter set
|
||||||
compatible with this replacement circuit, and how the \_TECHMAP_DO\_ wire in
|
is compatible with this replacement circuit, and how the ``_TECHMAP_DO_`` wire
|
||||||
line 13 provides a mini synthesis-script to be used to process this cell.
|
in line 13 provides a mini synthesis-script to be used to process this cell.
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
:caption: Test program for the Amber23 CPU (Sieve of Eratosthenes). Compiled
|
:caption: Test program for the Amber23 CPU (Sieve of Eratosthenes). Compiled
|
||||||
|
@ -298,39 +298,36 @@ format as well.
|
||||||
|
|
||||||
.. _ABC: https://github.com/berkeley-abc/abc
|
.. _ABC: https://github.com/berkeley-abc/abc
|
||||||
|
|
||||||
The only thing left to write about the simulation itself is that it
|
The only thing left to write about the simulation itself is that it probably was
|
||||||
probably was one of the most energy inefficient and time consuming ways
|
one of the most energy inefficient and time consuming ways of successfully
|
||||||
of successfully calculating the first 31 primes the author has ever
|
calculating the first 31 primes the author has ever conducted.
|
||||||
conducted.
|
|
||||||
|
|
||||||
Limitations
|
Limitations
|
||||||
===========
|
===========
|
||||||
|
|
||||||
At the time of this writing Yosys does not support multi-dimensional
|
At the time of this writing Yosys does not support multi-dimensional memories,
|
||||||
memories, does not support writing to individual bits of array elements,
|
does not support writing to individual bits of array elements, does not support
|
||||||
does not support initialization of arrays with $readmemb and $readmemh,
|
initialization of arrays with ``$readmemb`` and ``$readmemh``, and has only
|
||||||
and has only limited support for tristate logic, to name just a few
|
limited support for tristate logic, to name just a few limitations.
|
||||||
limitations.
|
|
||||||
|
|
||||||
That being said, Yosys can synthesize an overwhelming majority of
|
That being said, Yosys can synthesize an overwhelming majority of real-world
|
||||||
real-world Verilog RTL code. The remaining cases can usually be modified
|
Verilog RTL code. The remaining cases can usually be modified to be compatible
|
||||||
to be compatible with Yosys quite easily.
|
with Yosys quite easily.
|
||||||
|
|
||||||
The various designs in yosys-bigsim are a good place to look for
|
The various designs in yosys-bigsim are a good place to look for examples of
|
||||||
examples of what is within the capabilities of Yosys.
|
what is within the capabilities of Yosys.
|
||||||
|
|
||||||
Conclusion
|
Conclusion
|
||||||
==========
|
==========
|
||||||
|
|
||||||
Yosys is a feature-rich Verilog-2005 synthesis tool. It has many uses,
|
Yosys is a feature-rich Verilog-2005 synthesis tool. It has many uses, but one
|
||||||
but one is to provide an easy gateway from high-level Verilog code to
|
is to provide an easy gateway from high-level Verilog code to low-level logic
|
||||||
low-level logic circuits.
|
circuits.
|
||||||
|
|
||||||
The command line option -S can be used to quickly synthesize Verilog
|
The command line option ``-S`` can be used to quickly synthesize Verilog code to
|
||||||
code to BLIF files without a hassle.
|
BLIF files without a hassle.
|
||||||
|
|
||||||
With custom synthesis scripts it becomes possible to easily perform
|
With custom synthesis scripts it becomes possible to easily perform high-level
|
||||||
high-level optimizations, such as re-encoding FSMs. In some extreme
|
optimizations, such as re-encoding FSMs. In some extreme cases, such as the
|
||||||
cases, such as the Amber23 ARMv2 CPU, the more advanced Yosys features
|
Amber23 ARMv2 CPU, the more advanced Yosys features can be used to change a
|
||||||
can be used to change a design to fit a certain need without actually
|
design to fit a certain need without actually touching the RTL code.
|
||||||
touching the RTL code.
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ simply be abbreviated using the last part.
|
||||||
Usually all interactive work is done with one module selected using the ``cd``
|
Usually all interactive work is done with one module selected using the ``cd``
|
||||||
command. But it is also possible to work from the design-context (``cd ..``). In
|
command. But it is also possible to work from the design-context (``cd ..``). In
|
||||||
this case all object names must be prefixed with ``<module_name>/``. For example
|
this case all object names must be prefixed with ``<module_name>/``. For example
|
||||||
``a*/b\*`` would refer to all objects whose names start with ``b`` from all
|
``a*/b*`` would refer to all objects whose names start with ``b`` from all
|
||||||
modules whose names start with ``a``.
|
modules whose names start with ``a``.
|
||||||
|
|
||||||
The ``dump`` command can be used to print all information about an object. For
|
The ``dump`` command can be used to print all information about an object. For
|
||||||
|
@ -416,7 +416,7 @@ will select all ``$add ``cells that have the ``foo`` attribute set:
|
||||||
|
|
||||||
select t:$add a:foo %i
|
select t:$add a:foo %i
|
||||||
|
|
||||||
The listing in :numref:`sumprod` uses the Yosys non-standard ``{... \*}`` syntax
|
The listing in :numref:`sumprod` uses the Yosys non-standard ``{... *}`` syntax
|
||||||
to set the attribute ``sumstuff`` on all cells generated by the first assign
|
to set the attribute ``sumstuff`` on all cells generated by the first assign
|
||||||
statement. (This works on arbitrary large blocks of Verilog code an can be used
|
statement. (This works on arbitrary large blocks of Verilog code an can be used
|
||||||
to mark portions of code for analysis.)
|
to mark portions of code for analysis.)
|
||||||
|
@ -467,7 +467,7 @@ be a bit dull. So there is a shortcut for that: the number of iterations can be
|
||||||
appended to the action. So for example the action ``%ci3`` is identical to
|
appended to the action. So for example the action ``%ci3`` is identical to
|
||||||
performing the ``%ci`` action three times.
|
performing the ``%ci`` action three times.
|
||||||
|
|
||||||
The action ``%ci\*`` performs the ``%ci`` action over and over again until it
|
The action ``%ci*`` performs the ``%ci`` action over and over again until it
|
||||||
has no effect anymore.
|
has no effect anymore.
|
||||||
|
|
||||||
.. figure:: ../../images/011/select_prod.*
|
.. figure:: ../../images/011/select_prod.*
|
||||||
|
|
|
@ -43,15 +43,15 @@ directories:
|
||||||
simulation results of the synthesized design to the original sources to
|
simulation results of the synthesized design to the original sources to
|
||||||
logic equivalence checking of entire CPU cores.
|
logic equivalence checking of entire CPU cores.
|
||||||
|
|
||||||
The top-level Makefile includes frontends/\*/Makefile.inc,
|
The top-level Makefile includes ``frontends/*/Makefile.inc``,
|
||||||
passes/\*/Makefile.inc and backends/\*/Makefile.inc. So when extending Yosys it
|
``passes/*/Makefile.inc`` and ``backends/*/Makefile.inc``. So when extending
|
||||||
is enough to create a new directory in frontends/, passes/ or backends/ with
|
Yosys it is enough to create a new directory in ``frontends/``, ``passes/`` or
|
||||||
your sources and a Makefile.inc. The Yosys kernel automatically detects all
|
``backends/`` with your sources and a ``Makefile.inc``. The Yosys kernel
|
||||||
commands linked with Yosys. So it is not needed to add additional commands to a
|
automatically detects all commands linked with Yosys. So it is not needed to add
|
||||||
central list of commands.
|
additional commands to a central list of commands.
|
||||||
|
|
||||||
Good starting points for reading example source code to learn how to write
|
Good starting points for reading example source code to learn how to write
|
||||||
passes are passes/opt/opt_rmdff.cc and passes/opt/opt_merge.cc.
|
passes are ``passes/opt/opt_rmdff.cc`` and ``passes/opt/opt_merge.cc``.
|
||||||
|
|
||||||
See the top-level README file for a quick Getting Started guide and build
|
See the top-level README file for a quick Getting Started guide and build
|
||||||
instructions. The Yosys build is based solely on Makefiles.
|
instructions. The Yosys build is based solely on Makefiles.
|
||||||
|
|
|
@ -99,14 +99,14 @@ Selections intro
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Most commands can operate not only on the entire design but also specifically on
|
Most commands can operate not only on the entire design but also specifically on
|
||||||
selected parts of the design. For example the command dump will print all
|
selected parts of the design. For example the command ``dump`` will print all
|
||||||
selected objects in the current design while dump foobar will only print the
|
selected objects in the current design while ``dump foobar`` will only print the
|
||||||
module foobar and dump \* will print the entire design regardless of the current
|
module ``foobar`` and ``dump *`` will print the entire design regardless of the
|
||||||
selection.
|
current selection.
|
||||||
|
|
||||||
.. code:: yoscrypt
|
.. code:: yoscrypt
|
||||||
|
|
||||||
dump */t:$add %x:+[A] \*/w:\* %i
|
dump */t:$add %x:+[A] */w:* %i
|
||||||
|
|
||||||
The selection mechanism is very powerful. For example the command above will
|
The selection mechanism is very powerful. For example the command above will
|
||||||
print all wires that are connected to the ``\A`` port of a ``$add`` cell.
|
print all wires that are connected to the ``\A`` port of a ``$add`` cell.
|
||||||
|
|
|
@ -50,15 +50,6 @@ What you can do with Yosys
|
||||||
- Perform all kinds of operations on netlist (RTL, Logic, Gate)
|
- Perform all kinds of operations on netlist (RTL, Logic, Gate)
|
||||||
- Perform logic optimizations and gate mapping with ABC
|
- Perform logic optimizations and gate mapping with ABC
|
||||||
|
|
||||||
Things you can't do
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
- Process high-level languages such as C/C++/SystemC
|
|
||||||
- Create physical layouts (place&route)
|
|
||||||
+ Check out `nextpnr`_ for that
|
|
||||||
|
|
||||||
.. _nextpnr: https://github.com/YosysHQ/nextpnr
|
|
||||||
|
|
||||||
Typical applications for Yosys
|
Typical applications for Yosys
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -71,12 +62,21 @@ Typical applications for Yosys
|
||||||
- Framework for building custom flows (Not limited to synthesis but also formal
|
- Framework for building custom flows (Not limited to synthesis but also formal
|
||||||
verification, reverse engineering, ...)
|
verification, reverse engineering, ...)
|
||||||
|
|
||||||
|
Things you can't do
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
- Process high-level languages such as C/C++/SystemC
|
||||||
|
- Create physical layouts (place&route)
|
||||||
|
+ Check out `nextpnr`_ for that
|
||||||
|
|
||||||
|
.. _nextpnr: https://github.com/YosysHQ/nextpnr
|
||||||
|
|
||||||
Benefits of open source HDL synthesis
|
Benefits of open source HDL synthesis
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
- Cost (also applies to ``free as in free beer`` solutions):
|
- Cost (also applies to ``free as in free beer`` solutions):
|
||||||
|
|
||||||
Today the cost for a mask set in $\unit[180]{nm}$ technology is far less than
|
Today the cost for a mask set in 180nm technology is far less than
|
||||||
the cost for the design tools needed to design the mask layouts. Open Source
|
the cost for the design tools needed to design the mask layouts. Open Source
|
||||||
ASIC flows are an important enabler for ASIC-level Open Source Hardware.
|
ASIC flows are an important enabler for ASIC-level Open Source Hardware.
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ identifies cells with identical inputs and replaces them with a single instance
|
||||||
of the cell.
|
of the cell.
|
||||||
|
|
||||||
The option ``-nomux`` can be used to disable resource sharing for multiplexer
|
The option ``-nomux`` can be used to disable resource sharing for multiplexer
|
||||||
cells (``$mux`` and ``$pmux.`` This can be useful as it prevents multiplexer
|
cells (``$mux`` and ``$pmux``.) This can be useful as it prevents multiplexer
|
||||||
trees to be merged, which might prevent ``opt_muxtree`` to identify possible
|
trees to be merged, which might prevent ``opt_muxtree`` to identify possible
|
||||||
optimizations.
|
optimizations.
|
||||||
|
|
||||||
|
|
|
@ -19,54 +19,53 @@ Transforming Verilog to AST
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
The Verilog frontend converts the Verilog sources to an internal AST
|
The Verilog frontend converts the Verilog sources to an internal AST
|
||||||
representation that closely resembles the structure of the original
|
representation that closely resembles the structure of the original Verilog
|
||||||
Verilog code. The Verilog frontend consists of three components, the
|
code. The Verilog frontend consists of three components, the Preprocessor, the
|
||||||
Preprocessor, the Lexer and the Parser.
|
Lexer and the Parser.
|
||||||
|
|
||||||
The source code to the Verilog frontend can be found in
|
The source code to the Verilog frontend can be found in ``frontends/verilog/``
|
||||||
frontends/verilog/ in the Yosys source tree.
|
in the Yosys source tree.
|
||||||
|
|
||||||
The Verilog preprocessor
|
The Verilog preprocessor
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The Verilog preprocessor scans over the Verilog source code and
|
The Verilog preprocessor scans over the Verilog source code and interprets some
|
||||||
interprets some of the Verilog compiler directives such as
|
of the Verilog compiler directives such as :literal:`\`include`,
|
||||||
:literal:`\`include`, :literal:`\`define` and :literal:`\`ifdef`.
|
:literal:`\`define` and :literal:`\`ifdef`.
|
||||||
|
|
||||||
It is implemented as a C++ function that is passed a file descriptor as
|
It is implemented as a C++ function that is passed a file descriptor as input
|
||||||
input and returns the pre-processed Verilog code as a ``std::string``.
|
and returns the pre-processed Verilog code as a ``std::string``.
|
||||||
|
|
||||||
The source code to the Verilog Preprocessor can be found in
|
The source code to the Verilog Preprocessor can be found in
|
||||||
frontends/verilog/preproc.cc in the Yosys source tree.
|
``frontends/verilog/preproc.cc`` in the Yosys source tree.
|
||||||
|
|
||||||
The Verilog lexer
|
The Verilog lexer
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The Verilog Lexer is written using the lexer generator flex . Its source
|
The Verilog Lexer is written using the lexer generator flex. Its source code
|
||||||
code can be found in frontends/verilog/verilog_lexer.l in the Yosys
|
can be found in ``frontends/verilog/verilog_lexer.l`` in the Yosys source tree.
|
||||||
source tree. The lexer does little more than identifying all keywords
|
The lexer does little more than identifying all keywords and literals recognised
|
||||||
and literals recognised by the Yosys Verilog frontend.
|
by the Yosys Verilog frontend.
|
||||||
|
|
||||||
The lexer keeps track of the current location in the Verilog source code
|
The lexer keeps track of the current location in the Verilog source code
|
||||||
using some global variables. These variables are used by the constructor
|
using some global variables. These variables are used by the constructor
|
||||||
of AST nodes to annotate each node with the source code location it
|
of AST nodes to annotate each node with the source code location it
|
||||||
originated from.
|
originated from.
|
||||||
|
|
||||||
Finally the lexer identifies and handles special comments such as
|
Finally the lexer identifies and handles special comments such as "``// synopsys
|
||||||
"``// synopsys translate_off``" and "``// synopsys full_case``". (It is
|
translate_off``" and "``// synopsys full_case``". (It is recommended to use
|
||||||
recommended to use :literal:`\`ifdef` constructs instead of the
|
:literal:`\`ifdef` constructs instead of the Synsopsys translate_on/off comments
|
||||||
Synsopsys translate_on/off comments and attributes such as
|
and attributes such as ``(* full_case *)`` over "``// synopsys full_case``"
|
||||||
``(* full_case *)`` over "``// synopsys full_case``" whenever possible.)
|
whenever possible.)
|
||||||
|
|
||||||
The Verilog parser
|
The Verilog parser
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The Verilog Parser is written using the parser generator bison . Its
|
The Verilog Parser is written using the parser generator bison. Its source code
|
||||||
source code can be found in frontends/verilog/verilog_parser.y in the
|
can be found in ``frontends/verilog/verilog_parser.y`` in the Yosys source tree.
|
||||||
Yosys source tree.
|
|
||||||
|
|
||||||
It generates an AST using the ``AST::AstNode`` data structure defined in
|
It generates an AST using the ``AST::AstNode`` data structure defined in
|
||||||
frontends/ast/ast.h. An ``AST::AstNode`` object has the following
|
``frontends/ast/ast.h``. An ``AST::AstNode`` object has the following
|
||||||
properties:
|
properties:
|
||||||
|
|
||||||
.. list-table:: AST node types with their corresponding Verilog constructs.
|
.. list-table:: AST node types with their corresponding Verilog constructs.
|
||||||
|
@ -152,35 +151,32 @@ properties:
|
||||||
|
|
||||||
- | The node type
|
- | The node type
|
||||||
| This enum (``AST::AstNodeType``) specifies the role of the node.
|
| This enum (``AST::AstNodeType``) specifies the role of the node.
|
||||||
:numref:`Table %s <tab:Verilog_AstNodeType>`
|
:numref:`Table %s <tab:Verilog_AstNodeType>` contains a list of all node
|
||||||
contains a list of all node types.
|
types.
|
||||||
|
|
||||||
- | The child nodes
|
- | The child nodes
|
||||||
| This is a list of pointers to all children in the abstract syntax
|
| This is a list of pointers to all children in the abstract syntax tree.
|
||||||
tree.
|
|
||||||
|
|
||||||
- | Attributes
|
- | Attributes
|
||||||
| As almost every AST node might have Verilog attributes assigned to
|
| As almost every AST node might have Verilog attributes assigned to it, the
|
||||||
it, the ``AST::AstNode`` has direct support for attributes. Note
|
``AST::AstNode`` has direct support for attributes. Note that the attribute
|
||||||
that the attribute values are again AST nodes.
|
values are again AST nodes.
|
||||||
|
|
||||||
- | Node content
|
- | Node content
|
||||||
| Each node might have additional content data. A series of member
|
| Each node might have additional content data. A series of member variables
|
||||||
variables exist to hold such data. For example the member
|
exist to hold such data. For example the member ``std::string str`` can
|
||||||
``std::string str`` can hold a string value and is used e.g. in the
|
hold a string value and is used e.g. in the ``AST_IDENTIFIER`` node type to
|
||||||
AST_IDENTIFIER node type to store the identifier name.
|
store the identifier name.
|
||||||
|
|
||||||
- | Source code location
|
- | Source code location
|
||||||
| Each ``AST::AstNode`` is automatically annotated with the current
|
| Each ``AST::AstNode`` is automatically annotated with the current source
|
||||||
source code location by the ``AST::AstNode`` constructor. It is
|
code location by the ``AST::AstNode`` constructor. It is stored in the
|
||||||
stored in the ``std::string filename`` and ``int linenum`` member
|
``std::string filename`` and ``int linenum`` member variables.
|
||||||
variables.
|
|
||||||
|
|
||||||
The ``AST::AstNode`` constructor can be called with up to two child
|
The ``AST::AstNode`` constructor can be called with up to two child nodes that
|
||||||
nodes that are automatically added to the list of child nodes for the
|
are automatically added to the list of child nodes for the new object. This
|
||||||
new object. This simplifies the creation of AST nodes for simple
|
simplifies the creation of AST nodes for simple expressions a bit. For example
|
||||||
expressions a bit. For example the bison code for parsing
|
the bison code for parsing multiplications:
|
||||||
multiplications:
|
|
||||||
|
|
||||||
.. code:: none
|
.. code:: none
|
||||||
:number-lines:
|
:number-lines:
|
||||||
|
@ -190,49 +186,50 @@ multiplications:
|
||||||
append_attr($$, $3);
|
append_attr($$, $3);
|
||||||
} |
|
} |
|
||||||
|
|
||||||
The generated AST data structure is then passed directly to the AST
|
The generated AST data structure is then passed directly to the AST frontend
|
||||||
frontend that performs the actual conversion to RTLIL.
|
that performs the actual conversion to RTLIL.
|
||||||
|
|
||||||
Note that the Yosys command ``read_verilog`` provides the options ``-yydebug``
|
Note that the Yosys command ``read_verilog`` provides the options ``-yydebug``
|
||||||
and ``-dump_ast`` that can be used to print the parse tree or abstract
|
and ``-dump_ast`` that can be used to print the parse tree or abstract syntax
|
||||||
syntax tree respectively.
|
tree respectively.
|
||||||
|
|
||||||
Transforming AST to RTLIL
|
Transforming AST to RTLIL
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The AST Frontend converts a set of modules in AST representation to
|
The AST Frontend converts a set of modules in AST representation to modules in
|
||||||
modules in RTLIL representation and adds them to the current design.
|
RTLIL representation and adds them to the current design. This is done in two
|
||||||
This is done in two steps: simplification and RTLIL generation.
|
steps: simplification and RTLIL generation.
|
||||||
|
|
||||||
The source code to the AST frontend can be found in ``frontends/ast/`` in
|
The source code to the AST frontend can be found in ``frontends/ast/`` in the
|
||||||
the Yosys source tree.
|
Yosys source tree.
|
||||||
|
|
||||||
AST simplification
|
AST simplification
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A full-featured AST is too complex to be transformed into RTLIL
|
A full-featured AST is too complex to be transformed into RTLIL directly.
|
||||||
directly. Therefore it must first be brought into a simpler form. This
|
Therefore it must first be brought into a simpler form. This is done by calling
|
||||||
is done by calling the ``AST::AstNode::simplify()`` method of all
|
the ``AST::AstNode::simplify()`` method of all ``AST_MODULE`` nodes in the AST.
|
||||||
AST_MODULE nodes in the AST. This initiates a recursive process that
|
This initiates a recursive process that performs the following transformations
|
||||||
performs the following transformations on the AST data structure:
|
on the AST data structure:
|
||||||
|
|
||||||
- Inline all task and function calls.
|
- Inline all task and function calls.
|
||||||
|
|
||||||
- Evaluate all ``generate``-statements and unroll all ``for``-loops.
|
- Evaluate all ``generate``-statements and unroll all ``for``-loops.
|
||||||
|
|
||||||
- Perform const folding where it is necessary (e.g. in the value part
|
- Perform const folding where it is necessary (e.g. in the value part of
|
||||||
of AST_PARAMETER, AST_LOCALPARAM, AST_PARASET and AST_RANGE nodes).
|
``AST_PARAMETER``, ``AST_LOCALPARAM``, ``AST_PARASET`` and ``AST_RANGE``
|
||||||
|
nodes).
|
||||||
|
|
||||||
- Replace AST_PRIMITIVE nodes with appropriate AST_ASSIGN nodes.
|
- Replace ``AST_PRIMITIVE`` nodes with appropriate ``AST_ASSIGN`` nodes.
|
||||||
|
|
||||||
- Replace dynamic bit ranges in the left-hand-side of assignments with
|
- Replace dynamic bit ranges in the left-hand-side of assignments with
|
||||||
AST_CASE nodes with AST_COND children for each possible case.
|
``AST_CASE`` nodes with ``AST_COND`` children for each possible case.
|
||||||
|
|
||||||
- Detect array access patterns that are too complicated for the
|
- Detect array access patterns that are too complicated for the
|
||||||
RTLIL::Memory abstraction and replace them with a set of signals and
|
``RTLIL::Memory`` abstraction and replace them with a set of signals and
|
||||||
cases for all reads and/or writes.
|
cases for all reads and/or writes.
|
||||||
|
|
||||||
- Otherwise replace array accesses with AST_MEMRD and AST_MEMWR nodes.
|
- Otherwise replace array accesses with ``AST_MEMRD`` and ``AST_MEMWR`` nodes.
|
||||||
|
|
||||||
In addition to these transformations, the simplifier also annotates the
|
In addition to these transformations, the simplifier also annotates the
|
||||||
AST with additional information that is needed for the RTLIL generator,
|
AST with additional information that is needed for the RTLIL generator,
|
||||||
|
@ -242,70 +239,66 @@ namely:
|
||||||
folded but (when a constant value is found) are also written to
|
folded but (when a constant value is found) are also written to
|
||||||
member variables in the AST_RANGE node.
|
member variables in the AST_RANGE node.
|
||||||
|
|
||||||
- All identifiers are resolved and all AST_IDENTIFIER nodes are
|
- All identifiers are resolved and all ``AST_IDENTIFIER`` nodes are annotated
|
||||||
annotated with a pointer to the AST node that contains the
|
with a pointer to the AST node that contains the declaration of the
|
||||||
declaration of the identifier. If no declaration has been found, an
|
identifier. If no declaration has been found, an ``AST_AUTOWIRE`` node is
|
||||||
AST_AUTOWIRE node is created and used for the annotation.
|
created and used for the annotation.
|
||||||
|
|
||||||
This produces an AST that is fairly easy to convert to the RTLIL format.
|
This produces an AST that is fairly easy to convert to the RTLIL format.
|
||||||
|
|
||||||
Generating RTLIL
|
Generating RTLIL
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
After AST simplification, the ``AST::AstNode::genRTLIL()`` method of
|
After AST simplification, the ``AST::AstNode::genRTLIL()`` method of each
|
||||||
each AST_MODULE node in the AST is called. This initiates a recursive
|
``AST_MODULE`` node in the AST is called. This initiates a recursive process
|
||||||
process that generates equivalent RTLIL data for the AST data.
|
that generates equivalent RTLIL data for the AST data.
|
||||||
|
|
||||||
The ``AST::AstNode::genRTLIL()`` method returns an ``RTLIL::SigSpec``
|
The ``AST::AstNode::genRTLIL()`` method returns an ``RTLIL::SigSpec`` structure.
|
||||||
structure. For nodes that represent expressions (operators, constants,
|
For nodes that represent expressions (operators, constants, signals, etc.), the
|
||||||
signals, etc.), the cells needed to implement the calculation described
|
cells needed to implement the calculation described by the expression are
|
||||||
by the expression are created and the resulting signal is returned. That
|
created and the resulting signal is returned. That way it is easy to generate
|
||||||
way it is easy to generate the circuits for large expressions using
|
the circuits for large expressions using depth-first recursion. For nodes that
|
||||||
depth-first recursion. For nodes that do not represent an expression
|
do not represent an expression (such as ``AST_CELL``), the corresponding circuit
|
||||||
(such as AST_CELL), the corresponding circuit is generated and an empty
|
is generated and an empty ``RTLIL::SigSpec`` is returned.
|
||||||
``RTLIL::SigSpec`` is returned.
|
|
||||||
|
|
||||||
Synthesizing Verilog always blocks
|
Synthesizing Verilog always blocks
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
For behavioural Verilog code (code utilizing ``always``- and
|
For behavioural Verilog code (code utilizing ``always``- and ``initial``-blocks)
|
||||||
``initial``-blocks) it is necessary to also generate ``RTLIL::Process``
|
it is necessary to also generate ``RTLIL::Process`` objects. This is done in the
|
||||||
objects. This is done in the following way:
|
following way:
|
||||||
|
|
||||||
Whenever ``AST::AstNode::genRTLIL()`` encounters an ``always``- or
|
Whenever ``AST::AstNode::genRTLIL()`` encounters an ``always``- or
|
||||||
``initial``-block, it creates an instance of
|
``initial``-block, it creates an instance of ``AST_INTERNAL::ProcessGenerator``.
|
||||||
``AST_INTERNAL::ProcessGenerator``. This object then generates the
|
This object then generates the ``RTLIL::Process`` object for the block. It also
|
||||||
``RTLIL::Process`` object for the block. It also calls
|
calls ``AST::AstNode::genRTLIL()`` for all right-hand-side expressions contained
|
||||||
``AST::AstNode::genRTLIL()`` for all right-hand-side expressions
|
within the block.
|
||||||
contained within the block.
|
|
||||||
|
|
||||||
First the ``AST_INTERNAL::ProcessGenerator`` creates a list of all
|
First the ``AST_INTERNAL::ProcessGenerator`` creates a list of all signals
|
||||||
signals assigned within the block. It then creates a set of temporary
|
assigned within the block. It then creates a set of temporary signals using the
|
||||||
signals using the naming scheme $\ <number> \\\ <original_name> for each
|
naming scheme ``$ <number> \ <original_name>`` for each of the assigned signals.
|
||||||
of the assigned signals.
|
|
||||||
|
|
||||||
Then an ``RTLIL::Process`` is created that assigns all intermediate
|
Then an ``RTLIL::Process`` is created that assigns all intermediate values for
|
||||||
values for each left-hand-side signal to the temporary signal in its
|
each left-hand-side signal to the temporary signal in its
|
||||||
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree.
|
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree.
|
||||||
|
|
||||||
Finally a ``RTLIL::SyncRule`` is created for the ``RTLIL::Process`` that
|
Finally a ``RTLIL::SyncRule`` is created for the ``RTLIL::Process`` that assigns
|
||||||
assigns the temporary signals for the final values to the actual
|
the temporary signals for the final values to the actual signals.
|
||||||
signals.
|
|
||||||
|
|
||||||
A process may also contain memory writes. A ``RTLIL::MemWriteAction`` is
|
A process may also contain memory writes. A ``RTLIL::MemWriteAction`` is created
|
||||||
created for each of them.
|
for each of them.
|
||||||
|
|
||||||
Calls to ``AST::AstNode::genRTLIL()`` are generated for right hand sides
|
Calls to ``AST::AstNode::genRTLIL()`` are generated for right hand sides as
|
||||||
as needed. When blocking assignments are used,
|
needed. When blocking assignments are used, ``AST::AstNode::genRTLIL()`` is
|
||||||
``AST::AstNode::genRTLIL()`` is configured using global variables to use
|
configured using global variables to use the temporary signals that hold the
|
||||||
the temporary signals that hold the correct intermediate values whenever
|
correct intermediate values whenever one of the previously assigned signals is
|
||||||
one of the previously assigned signals is used in an expression.
|
used in an expression.
|
||||||
|
|
||||||
Unfortunately the generation of a correct
|
Unfortunately the generation of a correct
|
||||||
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree for behavioural code is a
|
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree for behavioural code is a
|
||||||
non-trivial task. The AST frontend solves the problem using the approach
|
non-trivial task. The AST frontend solves the problem using the approach
|
||||||
described on the following pages. The following example illustrates what
|
described on the following pages. The following example illustrates what the
|
||||||
the algorithm is supposed to do. Consider the following Verilog code:
|
algorithm is supposed to do. Consider the following Verilog code:
|
||||||
|
|
||||||
.. code:: verilog
|
.. code:: verilog
|
||||||
:number-lines:
|
:number-lines:
|
||||||
|
@ -325,9 +318,8 @@ the algorithm is supposed to do. Consider the following Verilog code:
|
||||||
out1 = out1 ^ out2;
|
out1 = out1 ^ out2;
|
||||||
end
|
end
|
||||||
|
|
||||||
This is translated by the Verilog and AST frontends into the following
|
This is translated by the Verilog and AST frontends into the following RTLIL
|
||||||
RTLIL code (attributes, cell parameters and wire declarations not
|
code (attributes, cell parameters and wire declarations not included):
|
||||||
included):
|
|
||||||
|
|
||||||
.. code:: RTLIL
|
.. code:: RTLIL
|
||||||
:number-lines:
|
:number-lines:
|
||||||
|
@ -372,47 +364,47 @@ included):
|
||||||
update \out3 $0\out3[0:0]
|
update \out3 $0\out3[0:0]
|
||||||
end
|
end
|
||||||
|
|
||||||
Note that the two operators are translated into separate cells outside
|
Note that the two operators are translated into separate cells outside the
|
||||||
the generated process. The signal ``out1`` is assigned using blocking
|
generated process. The signal ``out1`` is assigned using blocking assignments
|
||||||
assignments and therefore ``out1`` has been replaced with a different
|
and therefore ``out1`` has been replaced with a different signal in all
|
||||||
signal in all expressions after the initial assignment. The signal
|
expressions after the initial assignment. The signal ``out2`` is assigned using
|
||||||
``out2`` is assigned using nonblocking assignments and therefore is not
|
nonblocking assignments and therefore is not substituted on the right-hand-side
|
||||||
substituted on the right-hand-side expressions.
|
expressions.
|
||||||
|
|
||||||
The ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree must be interpreted
|
The ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree must be interpreted the
|
||||||
the following way:
|
following way:
|
||||||
|
|
||||||
- On each case level (the body of the process is the root case), first
|
- On each case level (the body of the process is the root case), first the
|
||||||
the actions on this level are evaluated and then the switches within
|
actions on this level are evaluated and then the switches within the case are
|
||||||
the case are evaluated. (Note that the last assignment on line 13 of
|
evaluated. (Note that the last assignment on line 13 of the Verilog code has
|
||||||
the Verilog code has been moved to the beginning of the RTLIL process
|
been moved to the beginning of the RTLIL process to line 13 of the RTLIL
|
||||||
to line 13 of the RTLIL listing.)
|
listing.)
|
||||||
|
|
||||||
I.e. the special cases deeper in the switch hierarchy override the
|
I.e. the special cases deeper in the switch hierarchy override the defaults
|
||||||
defaults on the upper levels. The assignments in lines 12 and 22 of
|
on the upper levels. The assignments in lines 12 and 22 of the RTLIL code
|
||||||
the RTLIL code serve as an example for this.
|
serve as an example for this.
|
||||||
|
|
||||||
Note that in contrast to this, the order within the
|
Note that in contrast to this, the order within the ``RTLIL::SwitchRule``
|
||||||
``RTLIL::SwitchRule`` objects within a ``RTLIL::CaseRule`` is
|
objects within a ``RTLIL::CaseRule`` is preserved with respect to the
|
||||||
preserved with respect to the original AST and Verilog code.
|
original AST and Verilog code.
|
||||||
|
|
||||||
- The whole ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree describes an
|
- The whole ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree describes an
|
||||||
asynchronous circuit. I.e. the decision tree formed by the switches
|
asynchronous circuit. I.e. the decision tree formed by the switches can be
|
||||||
can be seen independently for each assigned signal. Whenever one
|
seen independently for each assigned signal. Whenever one assigned signal
|
||||||
assigned signal changes, all signals that depend on the changed
|
changes, all signals that depend on the changed signals are to be updated.
|
||||||
signals are to be updated. For example the assignments in lines 16
|
For example the assignments in lines 16 and 18 in the RTLIL code in fact
|
||||||
and 18 in the RTLIL code in fact influence the assignment in line 12,
|
influence the assignment in line 12, even though they are in the "wrong
|
||||||
even though they are in the "wrong order".
|
order".
|
||||||
|
|
||||||
The only synchronous part of the process is in the ``RTLIL::SyncRule``
|
The only synchronous part of the process is in the ``RTLIL::SyncRule`` object
|
||||||
object generated at line 35 in the RTLIL code. The sync rule is the only
|
generated at line 35 in the RTLIL code. The sync rule is the only part of the
|
||||||
part of the process where the original signals are assigned. The
|
process where the original signals are assigned. The synchronization event from
|
||||||
synchronization event from the original Verilog code has been translated
|
the original Verilog code has been translated into the synchronization type
|
||||||
into the synchronization type (posedge) and signal (\\clock) for the
|
(posedge) and signal (``\clock``) for the ``RTLIL::SyncRule`` object. In the
|
||||||
``RTLIL::SyncRule`` object. In the case of this simple example the
|
case of this simple example the ``RTLIL::SyncRule`` object is later simply
|
||||||
``RTLIL::SyncRule`` object is later simply transformed into a set of
|
transformed into a set of d-type flip-flops and the
|
||||||
d-type flip-flops and the ``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree
|
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree to a decision tree using
|
||||||
to a decision tree using multiplexers.
|
multiplexers.
|
||||||
|
|
||||||
In more complex examples (e.g. asynchronous resets) the part of the
|
In more complex examples (e.g. asynchronous resets) the part of the
|
||||||
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree that describes the
|
``RTLIL::CaseRule``/``RTLIL::SwitchRule`` tree that describes the
|
||||||
|
@ -426,64 +418,62 @@ The ``AST_INTERNAL::ProcessGenerator`` uses the following internal state
|
||||||
variables:
|
variables:
|
||||||
|
|
||||||
- | ``subst_rvalue_from`` and ``subst_rvalue_to``
|
- | ``subst_rvalue_from`` and ``subst_rvalue_to``
|
||||||
| These two variables hold the replacement pattern that should be
|
| These two variables hold the replacement pattern that should be used by
|
||||||
used by ``AST::AstNode::genRTLIL()`` for signals with blocking
|
``AST::AstNode::genRTLIL()`` for signals with blocking assignments. After
|
||||||
assignments. After initialization of
|
initialization of ``AST_INTERNAL::ProcessGenerator`` these two variables are
|
||||||
``AST_INTERNAL::ProcessGenerator`` these two variables are empty.
|
empty.
|
||||||
|
|
||||||
- | ``subst_lvalue_from`` and ``subst_lvalue_to``
|
- | ``subst_lvalue_from`` and ``subst_lvalue_to``
|
||||||
| These two variables contain the mapping from left-hand-side signals
|
| These two variables contain the mapping from left-hand-side signals (``\
|
||||||
(\\\ <name>) to the current temporary signal for the same thing
|
<name>``) to the current temporary signal for the same thing (initially
|
||||||
(initially $0\\\ <name>).
|
``$0\ <name>``).
|
||||||
|
|
||||||
- | ``current_case``
|
- | ``current_case``
|
||||||
| A pointer to a ``RTLIL::CaseRule`` object. Initially this is the
|
| A pointer to a ``RTLIL::CaseRule`` object. Initially this is the root case
|
||||||
root case of the generated ``RTLIL::Process``.
|
of the generated ``RTLIL::Process``.
|
||||||
|
|
||||||
As the algorithm runs these variables are continuously modified as well
|
As the algorithm runs these variables are continuously modified as well as
|
||||||
as pushed to the stack and later restored to their earlier values by
|
pushed to the stack and later restored to their earlier values by popping from
|
||||||
popping from the stack.
|
the stack.
|
||||||
|
|
||||||
On startup the ProcessGenerator generates a new ``RTLIL::Process``
|
On startup the ProcessGenerator generates a new ``RTLIL::Process`` object with
|
||||||
object with an empty root case and initializes its state variables as
|
an empty root case and initializes its state variables as described above. Then
|
||||||
described above. Then the ``RTLIL::SyncRule`` objects are created using
|
the ``RTLIL::SyncRule`` objects are created using the synchronization events
|
||||||
the synchronization events from the AST_ALWAYS node and the initial
|
from the AST_ALWAYS node and the initial values of ``subst_lvalue_from`` and
|
||||||
values of ``subst_lvalue_from`` and ``subst_lvalue_to``. Then the AST
|
``subst_lvalue_to``. Then the AST for this process is evaluated recursively.
|
||||||
for this process is evaluated recursively.
|
|
||||||
|
|
||||||
During this recursive evaluation, three different relevant types of AST
|
During this recursive evaluation, three different relevant types of AST nodes
|
||||||
nodes can be discovered: AST_ASSIGN_LE (nonblocking assignments),
|
can be discovered: ``AST_ASSIGN_LE`` (nonblocking assignments),
|
||||||
AST_ASSIGN_EQ (blocking assignments) and AST_CASE (``if`` or ``case``
|
``AST_ASSIGN_EQ`` (blocking assignments) and ``AST_CASE`` (``if`` or ``case``
|
||||||
statement).
|
statement).
|
||||||
|
|
||||||
Handling of nonblocking assignments
|
Handling of nonblocking assignments
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
When an AST_ASSIGN_LE node is discovered, the following actions are
|
When an ``AST_ASSIGN_LE`` node is discovered, the following actions are
|
||||||
performed by the ProcessGenerator:
|
performed by the ProcessGenerator:
|
||||||
|
|
||||||
- The left-hand-side is evaluated using ``AST::AstNode::genRTLIL()``
|
- The left-hand-side is evaluated using ``AST::AstNode::genRTLIL()`` and mapped
|
||||||
and mapped to a temporary signal name using ``subst_lvalue_from`` and
|
to a temporary signal name using ``subst_lvalue_from`` and
|
||||||
``subst_lvalue_to``.
|
``subst_lvalue_to``.
|
||||||
|
|
||||||
- The right-hand-side is evaluated using ``AST::AstNode::genRTLIL()``.
|
- The right-hand-side is evaluated using ``AST::AstNode::genRTLIL()``. For this
|
||||||
For this call, the values of ``subst_rvalue_from`` and
|
call, the values of ``subst_rvalue_from`` and ``subst_rvalue_to`` are used to
|
||||||
``subst_rvalue_to`` are used to map blocking-assigned signals
|
map blocking-assigned signals correctly.
|
||||||
correctly.
|
|
||||||
|
|
||||||
- Remove all assignments to the same left-hand-side as this assignment
|
- Remove all assignments to the same left-hand-side as this assignment from the
|
||||||
from the ``current_case`` and all cases within it.
|
``current_case`` and all cases within it.
|
||||||
|
|
||||||
- Add the new assignment to the ``current_case``.
|
- Add the new assignment to the ``current_case``.
|
||||||
|
|
||||||
Handling of blocking assignments
|
Handling of blocking assignments
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
When an AST_ASSIGN_EQ node is discovered, the following actions are
|
When an ``AST_ASSIGN_EQ`` node is discovered, the following actions are
|
||||||
performed by the ProcessGenerator:
|
performed by the ProcessGenerator:
|
||||||
|
|
||||||
- Perform all the steps that would be performed for a nonblocking
|
- Perform all the steps that would be performed for a nonblocking assignment
|
||||||
assignment (see above).
|
(see above).
|
||||||
|
|
||||||
- Remove the found left-hand-side (before lvalue mapping) from
|
- Remove the found left-hand-side (before lvalue mapping) from
|
||||||
``subst_rvalue_from`` and also remove the respective bits from
|
``subst_rvalue_from`` and also remove the respective bits from
|
||||||
|
@ -496,36 +486,33 @@ performed by the ProcessGenerator:
|
||||||
Handling of cases and if-statements
|
Handling of cases and if-statements
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
When an AST_CASE node is discovered, the following actions are performed
|
When an ``AST_CASE`` node is discovered, the following actions are performed by
|
||||||
by the ProcessGenerator:
|
the ProcessGenerator:
|
||||||
|
|
||||||
- The values of ``subst_rvalue_from``, ``subst_rvalue_to``,
|
- The values of ``subst_rvalue_from``, ``subst_rvalue_to``,
|
||||||
``subst_lvalue_from`` and ``subst_lvalue_to`` are pushed to the
|
``subst_lvalue_from`` and ``subst_lvalue_to`` are pushed to the stack.
|
||||||
stack.
|
|
||||||
|
|
||||||
- A new ``RTLIL::SwitchRule`` object is generated, the selection
|
- A new ``RTLIL::SwitchRule`` object is generated, the selection expression is
|
||||||
expression is evaluated using ``AST::AstNode::genRTLIL()`` (with the
|
evaluated using ``AST::AstNode::genRTLIL()`` (with the use of
|
||||||
use of ``subst_rvalue_from`` and ``subst_rvalue_to``) and added to
|
``subst_rvalue_from`` and ``subst_rvalue_to``) and added to the
|
||||||
the ``RTLIL::SwitchRule`` object and the object is added to the
|
``RTLIL::SwitchRule`` object and the object is added to the ``current_case``.
|
||||||
``current_case``.
|
|
||||||
|
|
||||||
- All lvalues assigned to within the AST_CASE node using blocking
|
- All lvalues assigned to within the ``AST_CASE`` node using blocking
|
||||||
assignments are collected and saved in the local variable
|
assignments are collected and saved in the local variable
|
||||||
``this_case_eq_lvalue``.
|
``this_case_eq_lvalue``.
|
||||||
|
|
||||||
- New temporary signals are generated for all signals in
|
- New temporary signals are generated for all signals in
|
||||||
``this_case_eq_lvalue`` and stored in ``this_case_eq_ltemp``.
|
``this_case_eq_lvalue`` and stored in ``this_case_eq_ltemp``.
|
||||||
|
|
||||||
- The signals in ``this_case_eq_lvalue`` are mapped using
|
- The signals in ``this_case_eq_lvalue`` are mapped using ``subst_rvalue_from``
|
||||||
``subst_rvalue_from`` and ``subst_rvalue_to`` and the resulting set
|
and ``subst_rvalue_to`` and the resulting set of signals is stored in
|
||||||
of signals is stored in ``this_case_eq_rvalue``.
|
``this_case_eq_rvalue``.
|
||||||
|
|
||||||
Then the following steps are performed for each AST_COND node within the
|
Then the following steps are performed for each ``AST_COND`` node within the
|
||||||
AST_CASE node:
|
``AST_CASE`` node:
|
||||||
|
|
||||||
- Set ``subst_rvalue_from``, ``subst_rvalue_to``, ``subst_lvalue_from``
|
- Set ``subst_rvalue_from``, ``subst_rvalue_to``, ``subst_lvalue_from`` and
|
||||||
and ``subst_lvalue_to`` to the values that have been pushed to the
|
``subst_lvalue_to`` to the values that have been pushed to the stack.
|
||||||
stack.
|
|
||||||
|
|
||||||
- Remove ``this_case_eq_lvalue`` from
|
- Remove ``this_case_eq_lvalue`` from
|
||||||
``subst_lvalue_from``/``subst_lvalue_to``.
|
``subst_lvalue_from``/``subst_lvalue_to``.
|
||||||
|
@ -535,33 +522,30 @@ AST_CASE node:
|
||||||
|
|
||||||
- Push the value of ``current_case``.
|
- Push the value of ``current_case``.
|
||||||
|
|
||||||
- Create a new ``RTLIL::CaseRule``. Set ``current_case`` to the new
|
- Create a new ``RTLIL::CaseRule``. Set ``current_case`` to the new object and
|
||||||
object and add the new object to the ``RTLIL::SwitchRule`` created
|
add the new object to the ``RTLIL::SwitchRule`` created above.
|
||||||
above.
|
|
||||||
|
|
||||||
- Add an assignment from ``this_case_eq_rvalue`` to
|
- Add an assignment from ``this_case_eq_rvalue`` to ``this_case_eq_ltemp`` to
|
||||||
``this_case_eq_ltemp`` to the new ``current_case``.
|
the new ``current_case``.
|
||||||
|
|
||||||
- Evaluate the compare value for this case using
|
- Evaluate the compare value for this case using
|
||||||
``AST::AstNode::genRTLIL()`` (with the use of ``subst_rvalue_from``
|
``AST::AstNode::genRTLIL()`` (with the use of ``subst_rvalue_from``
|
||||||
and ``subst_rvalue_to``) modify the new ``current_case`` accordingly.
|
and ``subst_rvalue_to``) modify the new ``current_case`` accordingly.
|
||||||
|
|
||||||
- Recursion into the children of the AST_COND node.
|
- Recursion into the children of the ``AST_COND`` node.
|
||||||
|
|
||||||
- Restore ``current_case`` by popping the old value from the stack.
|
- Restore ``current_case`` by popping the old value from the stack.
|
||||||
|
|
||||||
Finally the following steps are performed:
|
Finally the following steps are performed:
|
||||||
|
|
||||||
- The values of ``subst_rvalue_from``, ``subst_rvalue_to``,
|
- The values of ``subst_rvalue_from``, ``subst_rvalue_to``,
|
||||||
``subst_lvalue_from`` and ``subst_lvalue_to`` are popped from the
|
``subst_lvalue_from`` and ``subst_lvalue_to`` are popped from the stack.
|
||||||
stack.
|
|
||||||
|
|
||||||
- The signals from ``this_case_eq_lvalue`` are removed from the
|
- The signals from ``this_case_eq_lvalue`` are removed from the
|
||||||
``subst_rvalue_from``/``subst_rvalue_to``-pair.
|
``subst_rvalue_from``/``subst_rvalue_to``-pair.
|
||||||
|
|
||||||
- The value of ``this_case_eq_lvalue`` is appended to
|
- The value of ``this_case_eq_lvalue`` is appended to ``subst_rvalue_from`` and
|
||||||
``subst_rvalue_from`` and the value of ``this_case_eq_ltemp`` is
|
the value of ``this_case_eq_ltemp`` is appended to ``subst_rvalue_to``.
|
||||||
appended to ``subst_rvalue_to``.
|
|
||||||
|
|
||||||
- Map the signals in ``this_case_eq_lvalue`` using
|
- Map the signals in ``this_case_eq_lvalue`` using
|
||||||
``subst_lvalue_from``/``subst_lvalue_to``.
|
``subst_lvalue_from``/``subst_lvalue_to``.
|
||||||
|
@ -569,37 +553,35 @@ Finally the following steps are performed:
|
||||||
- Remove all assignments to signals in ``this_case_eq_lvalue`` in
|
- Remove all assignments to signals in ``this_case_eq_lvalue`` in
|
||||||
``current_case`` and all cases within it.
|
``current_case`` and all cases within it.
|
||||||
|
|
||||||
- Add an assignment from ``this_case_eq_ltemp`` to
|
- Add an assignment from ``this_case_eq_ltemp`` to ``this_case_eq_lvalue`` to
|
||||||
``this_case_eq_lvalue`` to ``current_case``.
|
``current_case``.
|
||||||
|
|
||||||
Further analysis of the algorithm for cases and if-statements
|
Further analysis of the algorithm for cases and if-statements
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
With respect to nonblocking assignments the algorithm is easy: later
|
With respect to nonblocking assignments the algorithm is easy: later assignments
|
||||||
assignments invalidate earlier assignments. For each signal assigned
|
invalidate earlier assignments. For each signal assigned using nonblocking
|
||||||
using nonblocking assignments exactly one temporary variable is
|
assignments exactly one temporary variable is generated (with the ``$0``-prefix)
|
||||||
generated (with the $0-prefix) and this variable is used for all
|
and this variable is used for all assignments of the variable.
|
||||||
assignments of the variable.
|
|
||||||
|
|
||||||
Note how all the ``_eq_``-variables become empty when no blocking
|
Note how all the ``_eq_``-variables become empty when no blocking assignments
|
||||||
assignments are used and many of the steps in the algorithm can then be
|
are used and many of the steps in the algorithm can then be ignored as a result
|
||||||
ignored as a result of this.
|
of this.
|
||||||
|
|
||||||
For a variable with blocking assignments the algorithm shows the
|
For a variable with blocking assignments the algorithm shows the following
|
||||||
following behaviour: First a new temporary variable is created. This new
|
behaviour: First a new temporary variable is created. This new temporary
|
||||||
temporary variable is then registered as the assignment target for all
|
variable is then registered as the assignment target for all assignments for
|
||||||
assignments for this variable within the cases for this AST_CASE node.
|
this variable within the cases for this ``AST_CASE`` node. Then for each case
|
||||||
Then for each case the new temporary variable is first assigned the old
|
the new temporary variable is first assigned the old temporary variable. This
|
||||||
temporary variable. This assignment is overwritten if the variable is
|
assignment is overwritten if the variable is actually assigned in this case and
|
||||||
actually assigned in this case and is kept as a default value otherwise.
|
is kept as a default value otherwise.
|
||||||
|
|
||||||
This yields an ``RTLIL::CaseRule`` that assigns the new temporary
|
This yields an ``RTLIL::CaseRule`` that assigns the new temporary variable in
|
||||||
variable in all branches. So when all cases have been processed a final
|
all branches. So when all cases have been processed a final assignment is added
|
||||||
assignment is added to the containing block that assigns the new
|
to the containing block that assigns the new temporary variable to the old one.
|
||||||
temporary variable to the old one. Note how this step always overrides a
|
Note how this step always overrides a previous assignment to the old temporary
|
||||||
previous assignment to the old temporary variable. Other than
|
variable. Other than nonblocking assignments, the old assignment could still
|
||||||
nonblocking assignments, the old assignment could still have an effect
|
have an effect somewhere in the design, as there have been calls to
|
||||||
somewhere in the design, as there have been calls to
|
|
||||||
``AST::AstNode::genRTLIL()`` with a
|
``AST::AstNode::genRTLIL()`` with a
|
||||||
``subst_rvalue_from``/ ``subst_rvalue_to``-tuple that contained the
|
``subst_rvalue_from``/ ``subst_rvalue_to``-tuple that contained the
|
||||||
right-hand-side of the old assignment.
|
right-hand-side of the old assignment.
|
||||||
|
@ -607,60 +589,63 @@ right-hand-side of the old assignment.
|
||||||
The proc pass
|
The proc pass
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
The ProcessGenerator converts a behavioural model in AST representation
|
The ProcessGenerator converts a behavioural model in AST representation to a
|
||||||
to a behavioural model in ``RTLIL::Process`` representation. The actual
|
behavioural model in ``RTLIL::Process`` representation. The actual conversion
|
||||||
conversion from a behavioural model to an RTL representation is
|
from a behavioural model to an RTL representation is performed by the ``proc``
|
||||||
performed by the proc pass and the passes it launches:
|
pass and the passes it launches:
|
||||||
|
|
||||||
- | proc_clean and proc_rmdead
|
- | proc_clean and proc_rmdead
|
||||||
| These two passes just clean up the ``RTLIL::Process`` structure.
|
| These two passes just clean up the ``RTLIL::Process`` structure. The
|
||||||
The proc_clean pass removes empty parts (eg. empty assignments)
|
``proc_clean`` pass removes empty parts (eg. empty assignments) from the
|
||||||
from the process and proc_rmdead detects and removes unreachable
|
process and ``proc_rmdead`` detects and removes unreachable branches from
|
||||||
branches from the process's decision trees.
|
the process's decision trees.
|
||||||
|
|
||||||
- | proc_arst
|
- | proc_arst
|
||||||
| This pass detects processes that describe d-type flip-flops with
|
| This pass detects processes that describe d-type flip-flops with
|
||||||
asynchronous resets and rewrites the process to better reflect what
|
asynchronous resets and rewrites the process to better reflect what they
|
||||||
they are modelling: Before this pass, an asynchronous reset has two
|
are modelling: Before this pass, an asynchronous reset has two
|
||||||
edge-sensitive sync rules and one top-level for the reset path.
|
edge-sensitive sync rules and one top-level ``RTLIL::SwitchRule`` for the
|
||||||
After this pass the sync rule for the reset is level-sensitive and
|
reset path. After this pass the sync rule for the reset is level-sensitive
|
||||||
the top-level has been removed.
|
and the top-level ``RTLIL::SwitchRule`` has been removed.
|
||||||
|
|
||||||
- | proc_mux
|
- | proc_mux
|
||||||
| This pass converts the /-tree to a tree of multiplexers per written
|
| This pass converts the ``RTLIL::CaseRule``/ ``RTLIL::SwitchRule``-tree to a
|
||||||
signal. After this, the structure only contains the s that describe
|
tree of multiplexers per written signal. After this, the ``RTLIL::Process``
|
||||||
the output registers.
|
structure only contains the ``RTLIL::SyncRule`` s that describe the output
|
||||||
|
registers.
|
||||||
|
|
||||||
- | proc_dff
|
- | proc_dff
|
||||||
| This pass replaces the s to d-type flip-flops (with asynchronous
|
| This pass replaces the ``RTLIL::SyncRule`` s to d-type flip-flops (with
|
||||||
resets if necessary).
|
asynchronous resets if necessary).
|
||||||
|
|
||||||
- | proc_dff
|
- | proc_dff
|
||||||
| This pass replaces the s with $memwr cells.
|
| This pass replaces the ``RTLIL::MemWriteAction`` s with ``$memwr`` cells.
|
||||||
|
|
||||||
- | proc_clean
|
- | proc_clean
|
||||||
| A final call to proc_clean removes the now empty objects.
|
| A final call to ``proc_clean`` removes the now empty ``RTLIL::Process``
|
||||||
|
objects.
|
||||||
|
|
||||||
Performing these last processing steps in passes instead of in the
|
Performing these last processing steps in passes instead of in the Verilog
|
||||||
Verilog frontend has two important benefits:
|
frontend has two important benefits:
|
||||||
|
|
||||||
First it improves the transparency of the process. Everything that
|
First it improves the transparency of the process. Everything that happens in a
|
||||||
happens in a separate pass is easier to debug, as the RTLIL data
|
separate pass is easier to debug, as the RTLIL data structures can be easily
|
||||||
structures can be easily investigated before and after each of the
|
investigated before and after each of the steps.
|
||||||
steps.
|
|
||||||
|
|
||||||
Second it improves flexibility. This scheme can easily be extended to
|
Second it improves flexibility. This scheme can easily be extended to support
|
||||||
support other types of storage-elements, such as sr-latches or
|
other types of storage-elements, such as sr-latches or d-latches, without having
|
||||||
d-latches, without having to extend the actual Verilog frontend.
|
to extend the actual Verilog frontend.
|
||||||
|
|
||||||
Synthesizing Verilog arrays
|
Synthesizing Verilog arrays
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
Add some information on the generation of $memrd and $memwr cells and
|
.. TODO: these
|
||||||
|
|
||||||
|
Add some information on the generation of ``$memrd`` and ``$memwr`` cells and
|
||||||
how they are processed in the memory pass.
|
how they are processed in the memory pass.
|
||||||
|
|
||||||
Synthesizing parametric designs
|
Synthesizing parametric designs
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
Add some information on the ``RTLIL::Module::derive()`` method and how
|
Add some information on the ``RTLIL::Module::derive()`` method and how it is
|
||||||
it is used to synthesize parametric modules via the hierarchy pass.
|
used to synthesize parametric modules via the hierarchy pass.
|
||||||
|
|
|
@ -816,17 +816,17 @@ techlibs/common/simcells.v in the Yosys source tree.
|
||||||
============== ============== =========
|
============== ============== =========
|
||||||
|
|
||||||
|
|
||||||
Tables \ :numref:`%s <tab:CellLib_gates>`, :numref:`%s
|
Tables :numref:`%s <tab:CellLib_gates>`, :numref:`%s <tab:CellLib_gates_dffe>`,
|
||||||
<tab:CellLib_gates_dffe>`, :numref:`%s <tab:CellLib_gates_adff>`, :numref:`%s
|
:numref:`%s <tab:CellLib_gates_adff>`, :numref:`%s <tab:CellLib_gates_adffe>`,
|
||||||
<tab:CellLib_gates_adffe>`, :numref:`%s <tab:CellLib_gates_dffsr>`, :numref:`%s
|
:numref:`%s <tab:CellLib_gates_dffsr>`, :numref:`%s <tab:CellLib_gates_dffsre>`,
|
||||||
<tab:CellLib_gates_dffsre>`, :numref:`%s <tab:CellLib_gates_adlatch>`,
|
:numref:`%s <tab:CellLib_gates_adlatch>`, :numref:`%s
|
||||||
:numref:`%s <tab:CellLib_gates_dlatchsr>` and :numref:`%s
|
<tab:CellLib_gates_dlatchsr>` and :numref:`%s <tab:CellLib_gates_sr>` list all
|
||||||
<tab:CellLib_gates_sr>` list all cell types used for gate level logic. The cell
|
cell types used for gate level logic. The cell types ``$_BUF_``, ``$_NOT_``,
|
||||||
types ``$_BUF_``, ``$_NOT_``, ``$_AND_``, ``$_NAND_``, ``$_ANDNOT_``, ``$_OR_``,
|
``$_AND_``, ``$_NAND_``, ``$_ANDNOT_``, ``$_OR_``, ``$_NOR_``, ``$_ORNOT_``,
|
||||||
``$_NOR_``, ``$_ORNOT_``, ``$_XOR_``, ``$_XNOR_``, ``$_AOI3_``, ``$_OAI3_``,
|
``$_XOR_``, ``$_XNOR_``, ``$_AOI3_``, ``$_OAI3_``, ``$_AOI4_``, ``$_OAI4_``,
|
||||||
``$_AOI4_``, ``$_OAI4_``, ``$_MUX_``, ``$_MUX4_``, ``$_MUX8_``, ``$_MUX16_`` and
|
``$_MUX_``, ``$_MUX4_``, ``$_MUX8_``, ``$_MUX16_`` and ``$_NMUX_`` are used to
|
||||||
``$_NMUX_`` are used to model combinatorial logic. The cell type ``$_TBUF_`` is
|
model combinatorial logic. The cell type ``$_TBUF_`` is used to model tristate
|
||||||
used to model tristate logic.
|
logic.
|
||||||
|
|
||||||
The ``$_MUX4_``, ``$_MUX8_`` and ``$_MUX16_`` cells are used to model wide
|
The ``$_MUX4_``, ``$_MUX8_`` and ``$_MUX16_`` cells are used to model wide
|
||||||
muxes, and correspond to the following Verilog code:
|
muxes, and correspond to the following Verilog code:
|
||||||
|
|
|
@ -6,21 +6,21 @@ representation. The only exception are the high-level frontends that use the AST
|
||||||
representation as an intermediate step before generating RTLIL data.
|
representation as an intermediate step before generating RTLIL data.
|
||||||
|
|
||||||
In order to avoid reinventing names for the RTLIL classes, they are simply
|
In order to avoid reinventing names for the RTLIL classes, they are simply
|
||||||
referred to by their full C++ name, i.e. including the RTLIL:: namespace prefix,
|
referred to by their full C++ name, i.e. including the ``RTLIL::`` namespace prefix,
|
||||||
in this document.
|
in this document.
|
||||||
|
|
||||||
:numref:`Figure %s <fig:Overview_RTLIL>` shows a simplified Entity-Relationship
|
:numref:`Figure %s <fig:Overview_RTLIL>` shows a simplified Entity-Relationship
|
||||||
Diagram (ER Diagram) of RTLIL. In :math:`1:N` relationships the arrow points
|
Diagram (ER Diagram) of RTLIL. In :math:`1:N` relationships the arrow points
|
||||||
from the :math:`N` side to the :math:`1`. For example one RTLIL::Design contains
|
from the :math:`N` side to the :math:`1`. For example one ``RTLIL::Design`` contains
|
||||||
:math:`N` (zero to many) instances of RTLIL::Module. A two-pointed arrow
|
:math:`N` (zero to many) instances of ``RTLIL::Module`` . A two-pointed arrow
|
||||||
indicates a :math:`1:1` relationship.
|
indicates a :math:`1:1` relationship.
|
||||||
|
|
||||||
The RTLIL::Design is the root object of the RTLIL data structure. There is
|
The ``RTLIL::Design`` is the root object of the RTLIL data structure. There is
|
||||||
always one "current design" in memory which passes operate on, frontends add
|
always one "current design" in memory which passes operate on, frontends add
|
||||||
data to and backends convert to exportable formats. But in some cases passes
|
data to and backends convert to exportable formats. But in some cases passes
|
||||||
internally generate additional RTLIL::Design objects. For example when a pass is
|
internally generate additional ``RTLIL::Design`` objects. For example when a pass is
|
||||||
reading an auxiliary Verilog file such as a cell library, it might create an
|
reading an auxiliary Verilog file such as a cell library, it might create an
|
||||||
additional RTLIL::Design object and call the Verilog frontend with this other
|
additional ``RTLIL::Design`` object and call the Verilog frontend with this other
|
||||||
object to parse the cell library.
|
object to parse the cell library.
|
||||||
|
|
||||||
.. figure:: ../../../images/overview_rtlil.*
|
.. figure:: ../../../images/overview_rtlil.*
|
||||||
|
@ -29,23 +29,23 @@ object to parse the cell library.
|
||||||
|
|
||||||
Simplified RTLIL Entity-Relationship Diagram
|
Simplified RTLIL Entity-Relationship Diagram
|
||||||
|
|
||||||
There is only one active RTLIL::Design object that is used by all frontends,
|
There is only one active ``RTLIL::Design`` object that is used by all frontends,
|
||||||
passes and backends called by the user, e.g. using a synthesis script. The
|
passes and backends called by the user, e.g. using a synthesis script. The
|
||||||
RTLIL::Design then contains zero to many RTLIL::Module objects. This corresponds
|
``RTLIL::Design`` then contains zero to many ``RTLIL::Module`` objects. This corresponds
|
||||||
to modules in Verilog or entities in VHDL. Each module in turn contains objects
|
to modules in Verilog or entities in VHDL. Each module in turn contains objects
|
||||||
from three different categories:
|
from three different categories:
|
||||||
|
|
||||||
- RTLIL::Cell and RTLIL::Wire objects represent classical netlist data.
|
- ``RTLIL::Cell`` and ``RTLIL::Wire`` objects represent classical netlist data.
|
||||||
|
|
||||||
- RTLIL::Process objects represent the decision trees (if-then-else statements,
|
- ``RTLIL::Process`` objects represent the decision trees (if-then-else statements,
|
||||||
etc.) and synchronization declarations (clock signals and sensitivity) from
|
etc.) and synchronization declarations (clock signals and sensitivity) from
|
||||||
Verilog always and VHDL process blocks.
|
Verilog always and VHDL process blocks.
|
||||||
|
|
||||||
- RTLIL::Memory objects represent addressable memories (arrays).
|
- ``RTLIL::Memory`` objects represent addressable memories (arrays).
|
||||||
|
|
||||||
Usually the output of the synthesis procedure is a netlist, i.e. all
|
Usually the output of the synthesis procedure is a netlist, i.e. all
|
||||||
RTLIL::Process and RTLIL::Memory objects must be replaced by RTLIL::Cell and
|
``RTLIL::Process`` and ``RTLIL::Memory`` objects must be replaced by ``RTLIL::Cell`` and
|
||||||
RTLIL::Wire objects by synthesis passes.
|
``RTLIL::Wire`` objects by synthesis passes.
|
||||||
|
|
||||||
All features of the HDL that cannot be mapped directly to these RTLIL classes
|
All features of the HDL that cannot be mapped directly to these RTLIL classes
|
||||||
must be transformed to an RTLIL-compatible representation by the HDL frontend.
|
must be transformed to an RTLIL-compatible representation by the HDL frontend.
|
||||||
|
@ -63,19 +63,22 @@ a backslash (\) or a dollar sign ($).
|
||||||
|
|
||||||
Identifiers starting with a backslash are public visible identifiers. Usually
|
Identifiers starting with a backslash are public visible identifiers. Usually
|
||||||
they originate from one of the HDL input files. For example the signal name
|
they originate from one of the HDL input files. For example the signal name
|
||||||
"\\sig42" is most likely a signal that was declared using the name "sig42" in an
|
``\sig42`` is most likely a signal that was declared using the name ``sig42`` in
|
||||||
HDL input file. On the other hand the signal name "$sig42" is an auto-generated
|
an HDL input file. On the other hand the signal name ``$sig42`` is an
|
||||||
signal name. The backends convert all identifiers that start with a dollar sign
|
auto-generated signal name. The backends convert all identifiers that start with
|
||||||
to identifiers that do not collide with identifiers that start with a backslash.
|
a dollar sign to identifiers that do not collide with identifiers that start
|
||||||
|
with a backslash.
|
||||||
|
|
||||||
This has three advantages:
|
This has three advantages:
|
||||||
|
|
||||||
- First, it is impossible that an auto-generated identifier collides with an
|
- First, it is impossible that an auto-generated identifier collides with an
|
||||||
identifier that was provided by the user.
|
identifier that was provided by the user.
|
||||||
|
|
||||||
|
.. TODO: does opt_rmunused (still?) exist?
|
||||||
|
|
||||||
- Second, the information about which identifiers were originally provided by
|
- Second, the information about which identifiers were originally provided by
|
||||||
the user is always available which can help guide some optimizations. For
|
the user is always available which can help guide some optimizations. For
|
||||||
example the "opt_rmunused" tries to preserve signals with a user-provided
|
example the ``opt_rmunused`` tries to preserve signals with a user-provided
|
||||||
name but doesn't hesitate to delete signals that have auto-generated names
|
name but doesn't hesitate to delete signals that have auto-generated names
|
||||||
when they just duplicate other signals.
|
when they just duplicate other signals.
|
||||||
|
|
||||||
|
@ -98,25 +101,25 @@ All RTLIL identifiers are case sensitive.
|
||||||
|
|
||||||
Some transformations, such as flattening, may have to change identifiers
|
Some transformations, such as flattening, may have to change identifiers
|
||||||
provided by the user to avoid name collisions. When that happens, attribute
|
provided by the user to avoid name collisions. When that happens, attribute
|
||||||
"hdlname" is attached to the object with the changed identifier. This attribute
|
``hdlname`` is attached to the object with the changed identifier. This
|
||||||
contains one name (if emitted directly by the frontend, or is a result of
|
attribute contains one name (if emitted directly by the frontend, or is a result
|
||||||
disambiguation) or multiple names separated by spaces (if a result of
|
of disambiguation) or multiple names separated by spaces (if a result of
|
||||||
flattening). All names specified in the "hdlname" attribute are public and do
|
flattening). All names specified in the ``hdlname`` attribute are public and do
|
||||||
not include the leading "\".
|
not include the leading ``\``.
|
||||||
|
|
||||||
RTLIL::Design and RTLIL::Module
|
RTLIL::Design and RTLIL::Module
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
The RTLIL::Design object is basically just a container for RTLIL::Module
|
The ``RTLIL::Design`` object is basically just a container for ``RTLIL::Module``
|
||||||
objects. In addition to a list of RTLIL::Module objects the RTLIL::Design also
|
objects. In addition to a list of ``RTLIL::Module`` objects the
|
||||||
keeps a list of selected objects, i.e. the objects that passes should operate
|
``RTLIL::Design`` also keeps a list of selected objects, i.e. the objects that
|
||||||
on. In most cases the whole design is selected and therefore passes operate on
|
passes should operate on. In most cases the whole design is selected and
|
||||||
the whole design. But this mechanism can be useful for more complex synthesis
|
therefore passes operate on the whole design. But this mechanism can be useful
|
||||||
jobs in which only parts of the design should be affected by certain passes.
|
for more complex synthesis jobs in which only parts of the design should be
|
||||||
|
affected by certain passes.
|
||||||
|
|
||||||
Besides the objects shown in the ER diagram in :numref:`Fig. %s
|
Besides the objects shown in the :ref:`ER diagram <fig:Overview_RTLIL>` above,
|
||||||
<fig:Overview_RTLIL>` an RTLIL::Module object contains the following additional
|
an ``RTLIL::Module`` object contains the following additional properties:
|
||||||
properties:
|
|
||||||
|
|
||||||
- The module name
|
- The module name
|
||||||
- A list of attributes
|
- A list of attributes
|
||||||
|
@ -132,7 +135,7 @@ script but not by others.
|
||||||
Verilog and VHDL both support parametric modules (known as "generic entities" in
|
Verilog and VHDL both support parametric modules (known as "generic entities" in
|
||||||
VHDL). The RTLIL format does not support parametric modules itself. Instead each
|
VHDL). The RTLIL format does not support parametric modules itself. Instead each
|
||||||
module contains a callback function into the AST frontend to generate a
|
module contains a callback function into the AST frontend to generate a
|
||||||
parametrized variation of the RTLIL::Module as needed. This callback then
|
parametrized variation of the ``RTLIL::Module`` as needed. This callback then
|
||||||
returns the auto-generated name of the parametrized variation of the module. (A
|
returns the auto-generated name of the parametrized variation of the module. (A
|
||||||
hash over the parameters and the module name is used to prohibit the same
|
hash over the parameters and the module name is used to prohibit the same
|
||||||
parametrized variation from being generated twice. For modules with only a few
|
parametrized variation from being generated twice. For modules with only a few
|
||||||
|
@ -144,14 +147,14 @@ hash string.)
|
||||||
RTLIL::Cell and RTLIL::Wire
|
RTLIL::Cell and RTLIL::Wire
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
A module contains zero to many RTLIL::Cell and RTLIL::Wire objects. Objects of
|
A module contains zero to many ``RTLIL::Cell`` and ``RTLIL::Wire`` objects.
|
||||||
these types are used to model netlists. Usually the goal of all synthesis
|
Objects of these types are used to model netlists. Usually the goal of all
|
||||||
efforts is to convert all modules to a state where the functionality of the
|
synthesis efforts is to convert all modules to a state where the functionality
|
||||||
module is implemented only by cells from a given cell library and wires to
|
of the module is implemented only by cells from a given cell library and wires
|
||||||
connect these cells with each other. Note that module ports are just wires with
|
to connect these cells with each other. Note that module ports are just wires
|
||||||
a special property.
|
with a special property.
|
||||||
|
|
||||||
An RTLIL::Wire object has the following properties:
|
An ``RTLIL::Wire`` object has the following properties:
|
||||||
|
|
||||||
- The wire name
|
- The wire name
|
||||||
- A list of attributes
|
- A list of attributes
|
||||||
|
@ -174,15 +177,16 @@ the lowest or the highest bit index. In RTLIL, bit 0 always corresponds to LSB;
|
||||||
however, information from the HDL frontend is preserved so that the bus will be
|
however, information from the HDL frontend is preserved so that the bus will be
|
||||||
correctly indexed in error messages, backend output, constraint files, etc.
|
correctly indexed in error messages, backend output, constraint files, etc.
|
||||||
|
|
||||||
An RTLIL::Cell object has the following properties:
|
An ``RTLIL::Cell`` object has the following properties:
|
||||||
|
|
||||||
- The cell name and type
|
- The cell name and type
|
||||||
- A list of attributes
|
- A list of attributes
|
||||||
- A list of parameters (for parametric cells)
|
- A list of parameters (for parametric cells)
|
||||||
- Cell ports and the connections of ports to wires and constants
|
- Cell ports and the connections of ports to wires and constants
|
||||||
|
|
||||||
The connections of ports to wires are coded by assigning an RTLIL::SigSpec to
|
The connections of ports to wires are coded by assigning an ``RTLIL::SigSpec`` to
|
||||||
each cell port. The RTLIL::SigSpec data type is described in the next section.
|
each cell port. The ``RTLIL::SigSpec`` data type is described in the next
|
||||||
|
section.
|
||||||
|
|
||||||
.. _sec:rtlil_sigspec:
|
.. _sec:rtlil_sigspec:
|
||||||
|
|
||||||
|
@ -200,12 +204,12 @@ A "signal" is everything that can be applied to a cell port. I.e.
|
||||||
- | Concatenations of the above
|
- | Concatenations of the above
|
||||||
| 1em For example: ``{16'd1337, mywire[15:8]}``
|
| 1em For example: ``{16'd1337, mywire[15:8]}``
|
||||||
|
|
||||||
The RTLIL::SigSpec data type is used to represent signals. The RTLIL::Cell
|
The ``RTLIL::SigSpec`` data type is used to represent signals. The ``RTLIL::Cell``
|
||||||
object contains one RTLIL::SigSpec for each cell port.
|
object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||||
|
|
||||||
In addition, connections between wires are represented using a pair of
|
In addition, connections between wires are represented using a pair of
|
||||||
RTLIL::SigSpec objects. Such pairs are needed in different locations. Therefore
|
``RTLIL::SigSpec`` objects. Such pairs are needed in different locations.
|
||||||
the type name RTLIL::SigSig was defined for such a pair.
|
Therefore the type name ``RTLIL::SigSig`` was defined for such a pair.
|
||||||
|
|
||||||
.. _sec:rtlil_process:
|
.. _sec:rtlil_process:
|
||||||
|
|
||||||
|
@ -213,9 +217,9 @@ RTLIL::Process
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
When a high-level HDL frontend processes behavioural code it splits it up into
|
When a high-level HDL frontend processes behavioural code it splits it up into
|
||||||
data path logic (e.g. the expression a + b is replaced by the output of an adder
|
data path logic (e.g. the expression ``a + b`` is replaced by the output of an
|
||||||
that takes a and b as inputs) and an RTLIL::Process that models the control
|
adder that takes a and b as inputs) and an ``RTLIL::Process`` that models the
|
||||||
logic of the behavioural code. Let's consider a simple example:
|
control logic of the behavioural code. Let's consider a simple example:
|
||||||
|
|
||||||
.. code:: verilog
|
.. code:: verilog
|
||||||
:number-lines:
|
:number-lines:
|
||||||
|
@ -230,9 +234,9 @@ logic of the behavioural code. Let's consider a simple example:
|
||||||
q <= d;
|
q <= d;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
In this example there is no data path and therefore the RTLIL::Module generated
|
In this example there is no data path and therefore the ``RTLIL::Module`` generated
|
||||||
by the frontend only contains a few RTLIL::Wire objects and an RTLIL::Process.
|
by the frontend only contains a few ``RTLIL::Wire`` objects and an ``RTLIL::Process`` .
|
||||||
The RTLIL::Process in RTLIL syntax:
|
The ``RTLIL::Process`` in RTLIL syntax:
|
||||||
|
|
||||||
.. code:: RTLIL
|
.. code:: RTLIL
|
||||||
:number-lines:
|
:number-lines:
|
||||||
|
@ -255,34 +259,37 @@ The RTLIL::Process in RTLIL syntax:
|
||||||
update \q $0\q[0:0]
|
update \q $0\q[0:0]
|
||||||
end
|
end
|
||||||
|
|
||||||
This RTLIL::Process contains two RTLIL::SyncRule objects, two RTLIL::SwitchRule
|
This ``RTLIL::Process`` contains two ``RTLIL::SyncRule`` objects, two
|
||||||
objects and five RTLIL::CaseRule objects. The wire $0\q[0:0] is an automatically
|
``RTLIL::SwitchRule`` objects and five ``RTLIL::CaseRule`` objects. The wire
|
||||||
created wire that holds the next value of \\q. The lines :math:`2 \dots 12`
|
``$0\q[0:0]`` is an automatically created wire that holds the next value of
|
||||||
describe how $0\q[0:0] should be calculated. The lines :math:`13 \dots 16`
|
``\q``. The lines 2..12 describe how ``$0\q[0:0]`` should be calculated. The
|
||||||
describe how the value of $0\q[0:0] is used to update \\q.
|
lines 13..16 describe how the value of ``$0\q[0:0]`` is used to update ``\q``.
|
||||||
|
|
||||||
An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and
|
An ``RTLIL::Process`` is a container for zero or more ``RTLIL::SyncRule``
|
||||||
exactly one RTLIL::CaseRule object, which is called the root case.
|
objects and exactly one ``RTLIL::CaseRule`` object, which is called the root
|
||||||
|
case.
|
||||||
|
|
||||||
An RTLIL::SyncRule object contains an (optional) synchronization condition
|
An ``RTLIL::SyncRule`` object contains an (optional) synchronization condition
|
||||||
(signal and edge-type), zero or more assignments (RTLIL::SigSig), and zero or
|
(signal and edge-type), zero or more assignments (``RTLIL::SigSig``), and zero
|
||||||
more memory writes (RTLIL::MemWriteAction). The always synchronization condition
|
or more memory writes (``RTLIL::MemWriteAction``). The always synchronization
|
||||||
is used to break combinatorial loops when a latch should be inferred instead.
|
condition is used to break combinatorial loops when a latch should be inferred
|
||||||
|
instead.
|
||||||
|
|
||||||
An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig)
|
An ``RTLIL::CaseRule`` is a container for zero or more assignments
|
||||||
and zero or more RTLIL::SwitchRule objects. An RTLIL::SwitchRule objects is a
|
(``RTLIL::SigSig``) and zero or more ``RTLIL::SwitchRule`` objects. An
|
||||||
container for zero or more RTLIL::CaseRule objects.
|
``RTLIL::SwitchRule`` objects is a container for zero or more
|
||||||
|
``RTLIL::CaseRule`` objects.
|
||||||
|
|
||||||
In the above example the lines :math:`2 \dots 12` are the root case. Here
|
In the above example the lines 2..12 are the root case. Here ``$0\q[0:0]`` is
|
||||||
$0\q[0:0] is first assigned the old value \\q as default value (line 2). The
|
first assigned the old value ``\q`` as default value (line 2). The root case
|
||||||
root case also contains an RTLIL::SwitchRule object (lines :math:`3 \dots 12`).
|
also contains an ``RTLIL::SwitchRule`` object (lines 3..12). Such an object is
|
||||||
Such an object is very similar to the C switch statement as it uses a control
|
very similar to the C switch statement as it uses a control signal (``\reset``
|
||||||
signal (\\reset in this case) to determine which of its cases should be active.
|
in this case) to determine which of its cases should be active. The
|
||||||
The RTLIL::SwitchRule object then contains one RTLIL::CaseRule object per case.
|
``RTLIL::SwitchRule`` object then contains one ``RTLIL::CaseRule`` object per
|
||||||
In this example there is a case [1]_ for \\reset == 1 that causes $0\q[0:0] to
|
case. In this example there is a case [1]_ for ``\reset == 1`` that causes
|
||||||
be set (lines 4 and 5) and a default case that in turn contains a switch that
|
``$0\q[0:0]`` to be set (lines 4 and 5) and a default case that in turn contains
|
||||||
sets $0\q[0:0] to the value of \\d if \\enable is active (lines :math:`6 \dots
|
a switch that sets ``$0\q[0:0]`` to the value of ``\d`` if ``\enable`` is active
|
||||||
11`).
|
(lines 6..11).
|
||||||
|
|
||||||
A case can specify zero or more compare values that will determine whether it
|
A case can specify zero or more compare values that will determine whether it
|
||||||
matches. Each of the compare values must be the exact same width as the control
|
matches. Each of the compare values must be the exact same width as the control
|
||||||
|
@ -299,8 +306,8 @@ violated, the behavior is undefined. These attributes are useful when an
|
||||||
invariant invisible to the synthesizer causes the control signal to never take
|
invariant invisible to the synthesizer causes the control signal to never take
|
||||||
certain bit patterns.
|
certain bit patterns.
|
||||||
|
|
||||||
The lines :math:`13 \dots 16` then cause \\q to be updated whenever there is a
|
The lines 13..16 then cause ``\q`` to be updated whenever there is a positive
|
||||||
positive clock edge on \\clock or \\reset.
|
clock edge on ``\clock`` or ``\reset``.
|
||||||
|
|
||||||
In order to generate such a representation, the language frontend must be able
|
In order to generate such a representation, the language frontend must be able
|
||||||
to handle blocking and nonblocking assignments correctly. However, the language
|
to handle blocking and nonblocking assignments correctly. However, the language
|
||||||
|
@ -313,8 +320,8 @@ trees before further processing them.
|
||||||
|
|
||||||
One of the first actions performed on a design in RTLIL representation in most
|
One of the first actions performed on a design in RTLIL representation in most
|
||||||
synthesis scripts is identifying asynchronous resets. This is usually done using
|
synthesis scripts is identifying asynchronous resets. This is usually done using
|
||||||
the proc_arst pass. This pass transforms the above example to the following
|
the ``proc_arst`` pass. This pass transforms the above example to the following
|
||||||
RTLIL::Process:
|
``RTLIL::Process``:
|
||||||
|
|
||||||
.. code:: RTLIL
|
.. code:: RTLIL
|
||||||
:number-lines:
|
:number-lines:
|
||||||
|
@ -332,9 +339,9 @@ RTLIL::Process:
|
||||||
update \q 1'0
|
update \q 1'0
|
||||||
end
|
end
|
||||||
|
|
||||||
This pass has transformed the outer RTLIL::SwitchRule into a modified
|
This pass has transformed the outer ``RTLIL::SwitchRule`` into a modified
|
||||||
RTLIL::SyncRule object for the \\reset signal. Further processing converts the
|
``RTLIL::SyncRule`` object for the ``\reset`` signal. Further processing converts the
|
||||||
RTLIL::Process into e.g. a d-type flip-flop with asynchronous reset and a
|
``RTLIL::Process`` into e.g. a d-type flip-flop with asynchronous reset and a
|
||||||
multiplexer for the enable signal:
|
multiplexer for the enable signal:
|
||||||
|
|
||||||
.. code:: RTLIL
|
.. code:: RTLIL
|
||||||
|
@ -358,11 +365,11 @@ multiplexer for the enable signal:
|
||||||
connect \Y $0\q[0:0]
|
connect \Y $0\q[0:0]
|
||||||
end
|
end
|
||||||
|
|
||||||
Different combinations of passes may yield different results. Note that $adff
|
Different combinations of passes may yield different results. Note that
|
||||||
and $mux are internal cell types that still need to be mapped to cell types from
|
``$adff`` and ``$mux`` are internal cell types that still need to be mapped to
|
||||||
the target cell library.
|
cell types from the target cell library.
|
||||||
|
|
||||||
Some passes refuse to operate on modules that still contain RTLIL::Process
|
Some passes refuse to operate on modules that still contain ``RTLIL::Process``
|
||||||
objects as the presence of these objects in a module increases the complexity.
|
objects as the presence of these objects in a module increases the complexity.
|
||||||
Therefore the passes to translate processes to a netlist of cells are usually
|
Therefore the passes to translate processes to a netlist of cells are usually
|
||||||
called early in a synthesis script. The proc pass calls a series of other passes
|
called early in a synthesis script. The proc pass calls a series of other passes
|
||||||
|
@ -374,7 +381,7 @@ synthesis tasks.
|
||||||
RTLIL::Memory
|
RTLIL::Memory
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
For every array (memory) in the HDL code an RTLIL::Memory object is created. A
|
For every array (memory) in the HDL code an ``RTLIL::Memory`` object is created. A
|
||||||
memory object has the following properties:
|
memory object has the following properties:
|
||||||
|
|
||||||
- The memory name
|
- The memory name
|
||||||
|
@ -382,27 +389,28 @@ memory object has the following properties:
|
||||||
- The width of an addressable word
|
- The width of an addressable word
|
||||||
- The size of the memory in number of words
|
- The size of the memory in number of words
|
||||||
|
|
||||||
All read accesses to the memory are transformed to $memrd cells and all write
|
All read accesses to the memory are transformed to ``$memrd`` cells and all
|
||||||
accesses to $memwr cells by the language frontend. These cells consist of
|
write accesses to ``$memwr`` cells by the language frontend. These cells consist
|
||||||
independent read- and write-ports to the memory. Memory initialization is
|
of independent read- and write-ports to the memory. Memory initialization is
|
||||||
transformed to $meminit cells by the language frontend. The ``\MEMID`` parameter
|
transformed to ``$meminit`` cells by the language frontend. The ``\MEMID``
|
||||||
on these cells is used to link them together and to the RTLIL::Memory object
|
parameter on these cells is used to link them together and to the
|
||||||
they belong to.
|
``RTLIL::Memory`` object they belong to.
|
||||||
|
|
||||||
The rationale behind using separate cells for the individual ports versus
|
The rationale behind using separate cells for the individual ports versus
|
||||||
creating a large multiport memory cell right in the language frontend is that
|
creating a large multiport memory cell right in the language frontend is that
|
||||||
the separate $memrd and $memwr cells can be consolidated using resource sharing.
|
the separate ``$memrd`` and ``$memwr`` cells can be consolidated using resource
|
||||||
As resource sharing is a non-trivial optimization problem where different
|
sharing. As resource sharing is a non-trivial optimization problem where
|
||||||
synthesis tasks can have different requirements it lends itself to do the
|
different synthesis tasks can have different requirements it lends itself to do
|
||||||
optimisation in separate passes and merge the RTLIL::Memory objects and $memrd
|
the optimisation in separate passes and merge the ``RTLIL::Memory`` objects and
|
||||||
and $memwr cells to multiport memory blocks after resource sharing is completed.
|
``$memrd`` and ``$memwr`` cells to multiport memory blocks after resource
|
||||||
|
sharing is completed.
|
||||||
|
|
||||||
The memory pass performs this conversion and can (depending on the options
|
The memory pass performs this conversion and can (depending on the options
|
||||||
passed to it) transform the memories directly to d-type flip-flops and address
|
passed to it) transform the memories directly to d-type flip-flops and address
|
||||||
logic or yield multiport memory blocks (represented using $mem cells).
|
logic or yield multiport memory blocks (represented using ``$mem`` cells).
|
||||||
|
|
||||||
See :ref:`sec:memcells` for details about the memory cell types.
|
See :ref:`sec:memcells` for details about the memory cell types.
|
||||||
|
|
||||||
.. [1]
|
.. [1]
|
||||||
The syntax 1'1 in the RTLIL code specifies a constant with a length of one
|
The syntax ``1'1`` in the RTLIL code specifies a constant with a length of
|
||||||
bit (the first "1"), and this bit is a one (the second "1").
|
one bit (the first ``1``), and this bit is a one (the second ``1``).
|
||||||
|
|
Loading…
Reference in New Issue