mirror of
https://github.com/YosysHQ/yosys
synced 2025-12-18 02:08:33 +00:00
Merge remote-tracking branch 'origin/main' into gussmith23-rosette-backend-updates
This commit is contained in:
commit
6fe35fa46c
694 changed files with 33466 additions and 17901 deletions
|
|
@ -0,0 +1,271 @@
|
|||
Identifying the root cause of bugs
|
||||
==================================
|
||||
|
||||
This document references Yosys internals and is intended for people interested
|
||||
in solving or investigating Yosys bugs. This also applies if you are using a
|
||||
fuzzing tool; fuzzers have a tendency to find many variations of the same bug,
|
||||
so identifying the root cause is important for avoiding issue spam.
|
||||
|
||||
If you're familiar with C/C++, you might try to have a look at the source code
|
||||
of the command that's failing. Even if you can't fix the problem yourself, it
|
||||
can be very helpful for anyone else investigating if you're able to identify
|
||||
where the issue is arising.
|
||||
|
||||
|
||||
Finding the failing command
|
||||
---------------------------
|
||||
|
||||
Using the ``-L`` flag can help here, allowing you to specify a file to log to,
|
||||
such as ``yosys -L out.log -s script.ys``. Most commands will print a header
|
||||
message when they begin; something like ``2.48. Executing HIERARCHY pass
|
||||
(managing design hierarchy).`` The last header message will usually be the
|
||||
failing command. There are some commands which don't print a header message, so
|
||||
you may want to add ``echo on`` to the start of your script. The `echo` command
|
||||
echoes each command executed, along with any arguments given to it. For the
|
||||
`hierarchy` example above this might be ``yosys> hierarchy -check``.
|
||||
|
||||
.. note::
|
||||
|
||||
It may also be helpful to use the `log` command to add messages which you can
|
||||
then search for either in the terminal or the logfile. This can be quite
|
||||
useful if your script contains script-passes, like the
|
||||
:doc:`/using_yosys/synthesis/synth`, which call many sub-commands and you're
|
||||
not sure exactly which script-pass is calling the failing command.
|
||||
|
||||
|
||||
Minimizing scripts
|
||||
------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
This section is intended as **advanced usage**, and generally not necessary
|
||||
for normal bug reports.
|
||||
|
||||
If you're using a command line prompt, such as ``yosys -p 'synth_xilinx' -o
|
||||
design.json design.v``, consider converting it to a script. It's generally much
|
||||
easier to iterate over changes to a script in a file rather than one on the
|
||||
command line, as well as being better for sharing with others.
|
||||
|
||||
.. code-block:: yoscrypt
|
||||
:caption: example script, ``script.ys``, for prompt ``yosys -p 'synth_xilinx' -o design.json design.v``
|
||||
|
||||
read_verilog design.v
|
||||
synth_xilinx
|
||||
write_json design.json
|
||||
|
||||
Next up you want to remove everything *after* the error occurs. If your final
|
||||
command calls sub-commands, replace it with its contents first. In the case of
|
||||
the :doc:`/using_yosys/synthesis/synth`, as well as certain other script-passes,
|
||||
you can use the ``-run`` option to simplify this. For example we can replace
|
||||
``synth -top <top> -lut`` with the :ref:`replace_synth`. The options ``-top
|
||||
<top> -lut`` can be provided to each `synth` step, or to just the step(s) where
|
||||
it is relevant, as done here.
|
||||
|
||||
.. code-block:: yoscrypt
|
||||
:caption: example replacement script for `synth` command
|
||||
:name: replace_synth
|
||||
|
||||
synth -top <top> -run :coarse
|
||||
synth -lut -run coarse:fine
|
||||
synth -lut -run fine:check
|
||||
synth -run check:
|
||||
|
||||
Say we ran :ref:`replace_synth` and were able to remove the ``synth -run
|
||||
check:`` and still got our error, then we check the log and we see the last
|
||||
thing before the error was ``7.2. Executing MEMORY_MAP pass (converting memories
|
||||
to logic and flip-flops)``. By checking the output of ``yosys -h synth`` (or the
|
||||
`synth` help page) we can see that the `memory_map` pass is called in the
|
||||
``fine`` step. We can then update our script to the following:
|
||||
|
||||
.. code-block:: yoscrypt
|
||||
:caption: example replacement script for `synth` when `memory_map` is failing
|
||||
|
||||
synth -top <top> -run :fine
|
||||
opt -fast -full
|
||||
memory_map
|
||||
|
||||
By giving `synth` the option ``-run :fine``, we are telling it to run from the
|
||||
beginning of the script until the ``fine`` step, where we then give it the exact
|
||||
commands to run. There are some cases where the commands given in the help
|
||||
output are not an exact match for what is being run, but are instead a
|
||||
simplification. If you find that replacing the script-pass with its contents
|
||||
causes the error to disappear, or change, try calling the script-pass with
|
||||
``echo on`` to see exactly what commands are being called and what options are
|
||||
used.
|
||||
|
||||
.. warning::
|
||||
|
||||
Before continuing further, *back up your code*. The following steps can
|
||||
remove context and lead to over-minimizing scripts, hiding underlying issues.
|
||||
Check out :ref:`yosys_internals/extending_yosys/advanced_bugpoint:Why
|
||||
context matters` to learn more.
|
||||
|
||||
When a problem is occurring many steps into a script, minimizing the design at
|
||||
the start of the script isn't always enough to identify the cause of the issue.
|
||||
Each extra step of the script can lead to larger sections of the input design
|
||||
being needed for the specific problem to be preserved until it causes a crash.
|
||||
So to find the smallest possible reproducer it can sometimes be helpful to
|
||||
remove commands prior to the failure point.
|
||||
|
||||
The simplest way to do this is by writing out the design, resetting the current
|
||||
state, and reading back the design:
|
||||
|
||||
.. code-block:: yoscrypt
|
||||
|
||||
write_rtlil <design.il>; design -reset; read_rtlil <design.il>;
|
||||
|
||||
In most cases, this can be inserted immediately before the failing command while
|
||||
still producing the error, allowing you to :ref:`minimize your
|
||||
RTLIL<using_yosys/bugpoint:minimizing rtlil designs with bugpoint>` with the
|
||||
``<design.il>`` output. For our previous example with `memory_map`, if
|
||||
:ref:`map_reset` still gives the same error, then we should now be able to call
|
||||
``yosys design.il -p 'memory_map'`` to reproduce it.
|
||||
|
||||
.. code-block:: yoscrypt
|
||||
:caption: resetting the design immediately before failure
|
||||
:name: map_reset
|
||||
|
||||
synth -top <top> -run :fine
|
||||
opt -fast -full
|
||||
write_rtlil design.il; design -reset; read_rtlil design.il;
|
||||
memory_map
|
||||
|
||||
If that doesn't give the error (or doesn't give the same error), then you should
|
||||
try to move the write/reset/read earlier in the script until it does. If you
|
||||
have no idea where exactly you should put the reset, the best way is to use a
|
||||
"binary search" type approach, reducing the possible options by half after each
|
||||
attempt.
|
||||
|
||||
.. note::
|
||||
|
||||
By default, `write_rtlil` doesn't include platform specific IP blocks and
|
||||
other primitive cell models which are typically loaded with a ``read_verilog
|
||||
-lib`` command at the start of the synthesis script. You may have to
|
||||
duplicate these commands *after* the call to ``design -reset``. It is also
|
||||
possible to write out *everything* with ``select =*; write_rtlil -selected
|
||||
<design.il>``.
|
||||
|
||||
As an example, your script has 16 commands in it before failing on the 17th. If
|
||||
resetting immediately before the 17th doesn't reproduce the error, try between
|
||||
the 8th and 9th (8 is half of the total 16). If that produces the error then
|
||||
you can remove everything before the `read_rtlil` and try reset again in the
|
||||
middle of what's left, making sure to use a different name for the output file
|
||||
so that you don't overwrite what you've already got. If the error isn't
|
||||
produced then you need to go earlier still, so in this case you would do between
|
||||
the 4th and 5th (4 is half of the previous 8). Repeat this until you can't
|
||||
reduce the remaining commands any further.
|
||||
|
||||
A more conservative, but more involved, method is to remove or comment out
|
||||
commands prior to the failing command. Each command, or group of commands, can
|
||||
be disabled one at a time while checking if the error still occurs, eventually
|
||||
giving the smallest subset of commands needed to take the original input through
|
||||
to the error. The difficulty with this method is that depending on your design,
|
||||
some commands may be necessary even if they aren't needed to reproduce the
|
||||
error. For example, if your design includes ``process`` blocks, many commands
|
||||
will fail unless you run the `proc` command. While this approach can do a
|
||||
better job of maintaining context, it is often easier to *recover* the context
|
||||
after the design has been minimized for producing the error. For more on
|
||||
recovering context, checkout
|
||||
:ref:`yosys_internals/extending_yosys/advanced_bugpoint:Why context matters`.
|
||||
|
||||
|
||||
Why context matters
|
||||
-------------------
|
||||
|
||||
Sometimes when a command is raising an error, you're seeing a symptom rather
|
||||
than the underlying issue. It's possible that an earlier command may be putting
|
||||
the design in an invalid state, which isn't picked up until the error is raised.
|
||||
This is particularly true for the pre-packaged
|
||||
:doc:`/using_yosys/synthesis/synth`, which rely on a combination of generic and
|
||||
architecture specific passes. As new features are added to Yosys and more
|
||||
designs are supported, the types of cells output by a pass can grow and change;
|
||||
and sometimes this leads to a mismatch in what a pass is intended to handle.
|
||||
|
||||
If you minimized your script, and removed commands prior to the failure to get a
|
||||
smaller reproducer, try to work backwards and find which commands may have
|
||||
contributed to the design failing. From the minimized design you should have
|
||||
some understanding of the cell or cells which are producing the error; but where
|
||||
did those cells come from? The name and/or type of the cell can often point you
|
||||
in the right direction:
|
||||
|
||||
.. code-block::
|
||||
|
||||
# internal cell types start with a $
|
||||
# lowercase for word-level, uppercase for bit-level
|
||||
$and
|
||||
$_AND_
|
||||
|
||||
# cell types with $__ are typically intermediate cells used in techmapping
|
||||
$__MUL16X16
|
||||
|
||||
# cell types without a $ are either user-defined or architecture specific
|
||||
my_module
|
||||
SB_MAC16
|
||||
|
||||
# object names might give you the name of the pass that created them
|
||||
$procdff$1204
|
||||
$memory\rom$rdmux[0][0][0]$a$1550
|
||||
|
||||
# or even the line number in the Yosys source
|
||||
$auto$muxcover.cc:557:implement_best_cover$2152
|
||||
$auto$alumacc.cc:495:replace_alu$1209
|
||||
|
||||
Try running the unminimized script and search the log for the names of the
|
||||
objects in your minimized design. In the case of cells you can also search for
|
||||
the type of the cell. Remember that calling `stat` will list all the types of
|
||||
cells currently used in the design, and ``select -list =*`` will list the names
|
||||
of of all the current objects. You can add these commands to your script, or
|
||||
use an interactive terminal to run each command individually. Adding them to
|
||||
the script can be more repeatable, but if it takes a long time to run to the
|
||||
point you're interested in then an interactive shell session can give you more
|
||||
flexibility once you reach that point. You can also add a call to the `shell`
|
||||
command at any point in a script to start an interactive session at a given
|
||||
point; allowing you to script any preparation steps, then come back once it's
|
||||
done.
|
||||
|
||||
The ``--dump-design`` option
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Yosys provides the ``--dump-design`` option (or ``-P`` for short) for dumping
|
||||
the design at specific steps of the script based on the log header. If the last
|
||||
step before an error is ``7.2. Executing MEMORY_MAP pass (converting memories to
|
||||
logic and flip-flops)``, then calling Yosys with ``--dump-design 7.2:bad.il``
|
||||
will save the design *before* this command runs, in the file ``bad.il``.
|
||||
|
||||
It is also possible to use this option multiple times, e.g. ``-P2:hierarchy.il
|
||||
-P7 -P7.2:bad.il``, to get multiple dumps in the same run. This can make it
|
||||
easier to follow the design through each step to find where certain cells or
|
||||
connections are coming from. ``--dump-design ALL`` is also allowed, writing out
|
||||
the design at each log header.
|
||||
|
||||
A worked example
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Say you did all the minimization and found that an error in `synth_xilinx`
|
||||
occurs when a call to ``techmap -map +/xilinx/cells_map.v`` with
|
||||
``MIN_MUX_INPUTS`` defined parses a `$_MUX16_` with all inputs set to ``1'x``.
|
||||
You could fix the bug in ``+/xilinx/cells_map.v``, but that might only solve
|
||||
this one case while leaving other problems that haven't been found yet. So you
|
||||
step through the original script, calling `stat` after each step to find when
|
||||
the `$_MUX16_` is added.
|
||||
|
||||
You find that the `$_MUX16_` is introduced by a call to `muxcover`, but all the
|
||||
inputs are defined, so calling `techmap` now works as expected. From running
|
||||
`bugpoint` with the failing techmap you know that the cell with index ``2297``
|
||||
will fail, so you call ``select top/*$2297`` to limit to just that cell. This
|
||||
can then be saved with ``design -save pre_bug`` or ``write_rtlil -selected
|
||||
pre_bug.il``, so that you don't have to re-run all the earlier steps to get back
|
||||
here.
|
||||
|
||||
Next you step through the remaining commands and call `dump` after each to find
|
||||
when the inputs are disconnected. You find that ``opt -full`` has optimized
|
||||
away portions of the circuit, leading to `opt_expr` setting the undriven mux
|
||||
inputs to ``x``, but failing to remove the now unnecessary `$_MUX16_`. Now
|
||||
you've identified a problem in `opt_expr` that affects all of the wide muxes,
|
||||
and could happen in any synthesis flow, not just `synth_xilinx`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
This example is taken from `YosysHQ/yosys#4590
|
||||
<https://github.com/YosysHQ/yosys/issues/4590>`_ and can be reproduced with a
|
||||
version of Yosys between 0.45 and 0.51.
|
||||
|
|
@ -7,7 +7,7 @@ Contributing to Yosys
|
|||
|CONTRIBUTING|_ file.
|
||||
|
||||
.. |CONTRIBUTING| replace:: :file:`CONTRIBUTING.md`
|
||||
.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/CONTRIBUTING.md
|
||||
.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/blob/main/CONTRIBUTING.md
|
||||
|
||||
Coding Style
|
||||
------------
|
||||
|
|
@ -42,3 +42,137 @@ for implicit type casts, always use ``GetSize(foobar)`` instead of
|
|||
``foobar.size()``. (``GetSize()`` is defined in :file:`kernel/yosys.h`)
|
||||
|
||||
Use range-based for loops whenever applicable.
|
||||
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
|
||||
- use the `bug report template`_
|
||||
|
||||
.. _bug report template: https://github.com/YosysHQ/yosys/issues/new?template=bug_report.yml
|
||||
|
||||
- short title briefly describing the issue, e.g.
|
||||
|
||||
techmap of wide mux with undefined inputs raises error during synth_xilinx
|
||||
|
||||
+ tells us what's happening ("raises error")
|
||||
+ gives the command affected (`techmap`)
|
||||
+ an overview of the input design ("wide mux with undefined inputs")
|
||||
+ and some context where it was found ("during `synth_xilinx`")
|
||||
|
||||
|
||||
Reproduction Steps
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- ideally a code-block (starting and ending with triple backquotes) containing
|
||||
the minimized design (Verilog or RTLIL), followed by a code-block containing
|
||||
the minimized yosys script OR a command line call to yosys with
|
||||
code-formatting (starting and ending with single backquotes)
|
||||
|
||||
.. code-block:: markdown
|
||||
|
||||
min.v
|
||||
```verilog
|
||||
// minimized Verilog design
|
||||
```
|
||||
|
||||
min.ys
|
||||
```
|
||||
read_verilog min.v
|
||||
# minimum sequence of commands to reproduce error
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
`yosys -p ': minimum sequence of commands;' min.v`
|
||||
|
||||
- alternatively can provide a single code-block which includes the minimized
|
||||
design as a "here document" followed by the sequence of commands which
|
||||
reproduce the error
|
||||
|
||||
+ see :doc:`/using_yosys/more_scripting/load_design` for more on heredocs.
|
||||
|
||||
.. code-block:: markdown
|
||||
|
||||
```
|
||||
read_rtlil <<EOF
|
||||
# minimized RTLIL design
|
||||
EOF
|
||||
# minimum sequence of commands
|
||||
```
|
||||
|
||||
- any environment variables or command line options should also be mentioned
|
||||
- if the problem occurs for a range of values/designs, what is that range
|
||||
- if you're using an external tool, such as ``valgrind``, to detect the issue,
|
||||
what version of that tool are you using and what options are you giving it
|
||||
|
||||
.. warning::
|
||||
|
||||
Please try to avoid the use of any external plugins/tools in the reproduction
|
||||
steps if they are not directly related to the issue being raised. This
|
||||
includes frontend plugins such as GHDL or slang; use `write_rtlil` on the
|
||||
minimized design instead. This also includes tools which provide a wrapper
|
||||
around Yosys such as OpenLane; you should instead minimize your input and
|
||||
reproduction steps to just the Yosys part.
|
||||
|
||||
"Expected Behaviour"
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- if you have a similar design/script that doesn't give the error, include it
|
||||
here as a reference
|
||||
- if the bug is that an error *should* be raised but isn't, are there any other
|
||||
commands with similar error messages
|
||||
|
||||
|
||||
"Actual Behaviour"
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- any error messages go here
|
||||
- any details relevant to the crash that were found with ``--trace`` or
|
||||
``--debug`` flags
|
||||
- if you identified the point of failure in the source code, you could mention
|
||||
it here, or as a comment below
|
||||
|
||||
+ if possible, use a permalink to the source on GitHub
|
||||
+ you can browse the source repository for a certain commit with the failure
|
||||
and open the source file, select the relevant lines (click on the line
|
||||
number for the first relevant line, then while holding shift click on the
|
||||
line number for the last relevant line), click on the ``...`` that appears
|
||||
and select "Copy permalink"
|
||||
+ should look something like
|
||||
``https://github.com/YosysHQ/yosys/blob/<commit_hash>/path/to/file#L139-L147``
|
||||
+ clicking on "Preview" should reveal a code block containing the lines of
|
||||
source specified, with a link to the source file at the given commit
|
||||
|
||||
|
||||
Additional details
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- once you have created the issue, any additional details can be added as a
|
||||
comment on that issue
|
||||
- could include any additional context as to what you were doing when you first
|
||||
encountered the bug
|
||||
- was this issue discovered through the use of a fuzzer
|
||||
- if you've minimized the script, consider including the `bugpoint` script you
|
||||
used, or the original script, e.g.
|
||||
|
||||
.. code-block:: markdown
|
||||
|
||||
Minimized with
|
||||
```
|
||||
read_verilog design.v
|
||||
# original sequence of commands prior to error
|
||||
bugpoint -script <failure.ys> -grep "<string>"
|
||||
write_rtlil min.il
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
Minimized from
|
||||
`yosys -p ': original sequence of commands to produce error;' design.v`
|
||||
|
||||
- if you're able to, it may also help to share the original un-minimized design
|
||||
|
||||
+ if the design is too big for a comment, consider turning it into a `Gist`_
|
||||
|
||||
.. _Gist: https://gist.github.com/
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Writing extensions
|
|||
.. todo:: update to use :file:`/code_examples/extensions/test*.log`
|
||||
|
||||
This chapter contains some bits and pieces of information about programming
|
||||
yosys extensions. Don't be afraid to ask questions on the YosysHQ Slack.
|
||||
yosys extensions. Don't be afraid to ask questions on the YosysHQ Discourse.
|
||||
|
||||
.. todo:: mention coding guide
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ of interest for developers looking to customise Yosys builds.
|
|||
extensions
|
||||
build_verific
|
||||
functional_ir
|
||||
advanced_bugpoint
|
||||
contributing
|
||||
test_suites
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,72 @@
|
|||
Testing Yosys
|
||||
=============
|
||||
|
||||
.. TODO:: more about the included test suite and how to add tests
|
||||
.. todo:: adding tests (makefile-tests vs seed-tests)
|
||||
|
||||
Running the included test suite
|
||||
-------------------------------
|
||||
|
||||
The Yosys source comes with a test suite to avoid regressions and keep
|
||||
everything working as expected. Tests can be run by calling ``make test`` from
|
||||
the root Yosys directory.
|
||||
|
||||
Functional tests
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Testing functional backends (see
|
||||
:doc:`/yosys_internals/extending_yosys/functional_ir`) has a few requirements in
|
||||
addition to those listed in :ref:`getting_started/installation:Build
|
||||
prerequisites`:
|
||||
|
||||
.. tab:: Ubuntu
|
||||
|
||||
.. code:: console
|
||||
|
||||
sudo apt-get install racket
|
||||
raco pkg install rosette
|
||||
pip install pytest-xdist pytest-xdist-gnumake
|
||||
|
||||
.. tab:: macOS
|
||||
|
||||
.. code:: console
|
||||
|
||||
brew install racket
|
||||
raco pkg install rosette
|
||||
pip install pytest-xdist pytest-xdist-gnumake
|
||||
|
||||
If you don't have one of the :ref:`getting_started/installation:CAD suite(s)`
|
||||
installed, you should also install Z3 `following their
|
||||
instructions <https://github.com/Z3Prover/z3>`_.
|
||||
|
||||
Then, set the :makevar:`ENABLE_FUNCTIONAL_TESTS` make variable when calling
|
||||
``make test`` and the functional tests will be run as well.
|
||||
|
||||
Unit tests
|
||||
~~~~~~~~~~
|
||||
|
||||
Running the unit tests requires the following additional packages:
|
||||
|
||||
.. tab:: Ubuntu
|
||||
|
||||
.. code:: console
|
||||
|
||||
sudo apt-get install libgtest-dev
|
||||
|
||||
.. tab:: macOS
|
||||
|
||||
No additional requirements.
|
||||
|
||||
Unit tests can be run with ``make unit-test``.
|
||||
|
||||
Docs tests
|
||||
~~~~~~~~~~
|
||||
|
||||
There are some additional tests for checking examples included in the
|
||||
documentation, which can be run by calling ``make test`` from the
|
||||
:file:`yosys/docs` sub-directory (or ``make -C docs test`` from the root). This
|
||||
also includes checking some macro commands to ensure that descriptions of them
|
||||
are kept up to date, and is mostly intended for CI.
|
||||
|
||||
|
||||
Automatic testing
|
||||
-----------------
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ be found in :file:`frontends/verilog/verilog_lexer.l` in the Yosys source tree.
|
|||
The lexer does little more than identifying all keywords and literals recognised
|
||||
by the Yosys Verilog frontend.
|
||||
|
||||
The lexer keeps track of the current location in the Verilog source code using
|
||||
some global variables. These variables are used by the constructor of AST nodes
|
||||
to annotate each node with the source code location it originated from.
|
||||
The lexer keeps track of the current location in the Verilog source code with
|
||||
a ``VerilogLexer::out_loc`` and uses it to construct parser-defined
|
||||
symbol objects.
|
||||
|
||||
Finally the lexer identifies and handles special comments such as "``// synopsys
|
||||
translate_off``" and "``// synopsys full_case``". (It is recommended to use
|
||||
|
|
@ -178,21 +178,22 @@ properties:
|
|||
|
||||
- | Source code location
|
||||
| Each ``AST::AstNode`` is automatically annotated with the current source
|
||||
code location by the ``AST::AstNode`` constructor. It is stored in the
|
||||
``std::string filename`` and ``int linenum`` member variables.
|
||||
code location by the ``AST::AstNode`` constructor. The ``location`` type
|
||||
is a manual reimplementation of the bison-provided location type. This
|
||||
type is defined at ``frontends/verilog/verilog_location.h``.
|
||||
|
||||
The ``AST::AstNode`` constructor can be called with up to two child nodes that
|
||||
are automatically added to the list of child nodes for the new object. This
|
||||
The ``AST::AstNode`` constructor can be called with up to 4 child nodes. This
|
||||
simplifies the creation of AST nodes for simple expressions a bit. For example
|
||||
the bison code for parsing multiplications:
|
||||
|
||||
.. code:: none
|
||||
:number-lines:
|
||||
:number-lines:
|
||||
|
||||
basic_expr '*' attr basic_expr {
|
||||
$$ = new AstNode(AST_MUL, $1, $4);
|
||||
append_attr($$, $3);
|
||||
} |
|
||||
basic_expr TOK_ASTER attr basic_expr {
|
||||
$$ = std::make_unique<AstNode>(AST_MUL, std::move($1), std::move($4));
|
||||
SET_AST_NODE_LOC($$.get(), @1, @4);
|
||||
append_attr($$.get(), $3);
|
||||
} |
|
||||
|
||||
The generated AST data structure is then passed directly to the AST frontend
|
||||
that performs the actual conversion to RTLIL.
|
||||
|
|
@ -204,7 +205,7 @@ tree respectively.
|
|||
Transforming AST to RTLIL
|
||||
-------------------------
|
||||
|
||||
The AST Frontend converts a set of modules in AST representation to modules in
|
||||
The AST frontend converts a set of modules in AST representation to modules in
|
||||
RTLIL representation and adds them to the current design. This is done in two
|
||||
steps: simplification and RTLIL generation.
|
||||
|
||||
|
|
@ -626,7 +627,7 @@ pass and the passes it launches:
|
|||
| This pass replaces the ``RTLIL::SyncRule``\ s to d-type flip-flops (with
|
||||
asynchronous resets if necessary).
|
||||
|
||||
- | `proc_dff`
|
||||
- | `proc_memwr`
|
||||
| This pass replaces the ``RTLIL::MemWriteAction``\ s with `$memwr` cells.
|
||||
|
||||
- | `proc_clean`
|
||||
|
|
|
|||
|
|
@ -194,17 +194,18 @@ RTLIL::SigSpec
|
|||
|
||||
A "signal" is everything that can be applied to a cell port. I.e.
|
||||
|
||||
- | Any constant value of arbitrary bit-width
|
||||
- | A bit from a wire (``RTLIL::SigBit``)
|
||||
| 1em For example: ``mywire[24]``
|
||||
|
||||
- | A range of bits from a wire (wire variant of ``RTLIL::SigChunk``)
|
||||
| 1em For example: ``mywire, mywire[15:8]``
|
||||
|
||||
- | Any constant value of arbitrary bit-width (``std::vector<RTLIL::State>>`` variant of ``RTLIL::SigChunk``)
|
||||
| 1em For example: ``1337, 16'b0000010100111001, 1'b1, 1'bx``
|
||||
|
||||
- | All bits of a wire or a selection of bits from a wire
|
||||
| 1em For example: ``mywire, mywire[24], mywire[15:8]``
|
||||
|
||||
- | Concatenations of the above
|
||||
| 1em For example: ``{16'd1337, mywire[15:8]}``
|
||||
|
||||
The ``RTLIL::SigSpec`` data type is used to represent signals. The
|
||||
``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||
The ``RTLIL::SigSpec`` data type is used to represent signals.
|
||||
It contains a single ``RTLIL::SigChunk`` or a vector of ``RTLIL::SigBit``.
|
||||
The ``RTLIL::Cell`` object contains one ``RTLIL::SigSpec`` for each cell port.
|
||||
|
||||
In addition, connections between wires are represented using a pair of
|
||||
``RTLIL::SigSpec`` objects. Such pairs are needed in different locations.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ The main characteristics are:
|
|||
all compilers, standard libraries and architectures.
|
||||
|
||||
In addition to ``dict<K, T>`` and ``pool<T>`` there is also an ``idict<K>`` that
|
||||
creates a bijective map from ``K`` to the integers. For example:
|
||||
creates a bijective map from ``K`` to incrementing integers. For example:
|
||||
|
||||
::
|
||||
|
||||
|
|
@ -45,9 +45,9 @@ creates a bijective map from ``K`` to the integers. For example:
|
|||
log("%d\n", si("world")); // will print 43
|
||||
log("%d\n", si.at("world")); // will print 43
|
||||
log("%d\n", si.at("dummy")); // will throw exception
|
||||
log("%s\n", si[42].c_str())); // will print hello
|
||||
log("%s\n", si[43].c_str())); // will print world
|
||||
log("%s\n", si[44].c_str())); // will throw exception
|
||||
log("%s\n", si[42])); // will print hello
|
||||
log("%s\n", si[43])); // will print world
|
||||
log("%s\n", si[44])); // will throw exception
|
||||
|
||||
It is not possible to remove elements from an idict.
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ Previously, the interface to implement hashing on custom types was just
|
|||
independently and then ad-hoc combined with the hash function with some xorshift
|
||||
operations thrown in to mix bits together somewhat. A plugin can stay compatible
|
||||
with both versions prior and after the break by implementing both interfaces
|
||||
based on the existance and value of `YS_HASHING_VERSION`.
|
||||
based on the existance and value of ``YS_HASHING_VERSION``.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: Example hash compatibility wrapper
|
||||
|
|
|
|||
|
|
@ -38,5 +38,4 @@ as reference to implement a similar system in any language.
|
|||
formats/index
|
||||
extending_yosys/index
|
||||
techmap
|
||||
verilog
|
||||
hashing
|
||||
|
|
|
|||
|
|
@ -1,377 +0,0 @@
|
|||
Notes on Verilog support in Yosys
|
||||
=================================
|
||||
|
||||
.. TODO:: how much of this is specific to the read_verilog and should be in :doc:`/yosys_internals/flow/verilog_frontend`?
|
||||
|
||||
Unsupported Verilog-2005 Features
|
||||
---------------------------------
|
||||
|
||||
The following Verilog-2005 features are not supported by
|
||||
Yosys and there are currently no plans to add support
|
||||
for them:
|
||||
|
||||
- Non-synthesizable language features as defined in
|
||||
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
|
||||
|
||||
- The ``tri``, ``triand`` and ``trior`` net types
|
||||
|
||||
- The ``config`` and ``disable`` keywords and library map files
|
||||
|
||||
|
||||
Verilog Attributes and non-standard features
|
||||
--------------------------------------------
|
||||
|
||||
- The ``full_case`` attribute on case statements is supported (also the
|
||||
non-standard ``// synopsys full_case`` directive)
|
||||
|
||||
- The ``parallel_case`` attribute on case statements is supported (also the
|
||||
non-standard ``// synopsys parallel_case`` directive)
|
||||
|
||||
- The ``// synopsys translate_off`` and ``// synopsys translate_on`` directives
|
||||
are also supported (but the use of ``` `ifdef .. `endif ``` is strongly
|
||||
recommended instead).
|
||||
|
||||
- The ``nomem2reg`` attribute on modules or arrays prohibits the automatic early
|
||||
conversion of arrays to separate registers. This is potentially dangerous.
|
||||
Usually the front-end has good reasons for converting an array to a list of
|
||||
registers. Prohibiting this step will likely result in incorrect synthesis
|
||||
results.
|
||||
|
||||
- The ``mem2reg`` attribute on modules or arrays forces the early conversion of
|
||||
arrays to separate registers.
|
||||
|
||||
- The ``nomeminit`` attribute on modules or arrays prohibits the creation of
|
||||
initialized memories. This effectively puts ``mem2reg`` on all memories that
|
||||
are written to in an ``initial`` block and are not ROMs.
|
||||
|
||||
- The ``nolatches`` attribute on modules or always-blocks prohibits the
|
||||
generation of logic-loops for latches. Instead all not explicitly assigned
|
||||
values default to x-bits. This does not affect clocked storage elements such
|
||||
as flip-flops.
|
||||
|
||||
- The ``nosync`` attribute on registers prohibits the generation of a storage
|
||||
element. The register itself will always have all bits set to 'x' (undefined).
|
||||
The variable may only be used as blocking assigned temporary variable within
|
||||
an always block. This is mostly used internally by Yosys to synthesize Verilog
|
||||
functions and access arrays.
|
||||
|
||||
- The ``nowrshmsk`` attribute on a register prohibits the generation of
|
||||
shift-and-mask type circuits for writing to bit slices of that register.
|
||||
|
||||
- The ``onehot`` attribute on wires mark them as one-hot state register. This is
|
||||
used for example for memory port sharing and set by the fsm_map pass.
|
||||
|
||||
- The ``blackbox`` attribute on modules is used to mark empty stub modules that
|
||||
have the same ports as the real thing but do not contain information on the
|
||||
internal configuration. This modules are only used by the synthesis passes to
|
||||
identify input and output ports of cells. The Verilog backend also does not
|
||||
output blackbox modules on default. `read_verilog`, unless called with
|
||||
``-noblackbox`` will automatically set the blackbox attribute on any empty
|
||||
module it reads.
|
||||
|
||||
- The ``noblackbox`` attribute set on an empty module prevents `read_verilog`
|
||||
from automatically setting the blackbox attribute on the module.
|
||||
|
||||
- The ``whitebox`` attribute on modules triggers the same behavior as
|
||||
``blackbox``, but is for whitebox modules, i.e. library modules that contain a
|
||||
behavioral model of the cell type.
|
||||
|
||||
- The ``lib_whitebox`` attribute overwrites ``whitebox`` when `read_verilog` is
|
||||
run in ``-lib`` mode. Otherwise it's automatically removed.
|
||||
|
||||
- The ``dynports`` attribute is used by the Verilog front-end to mark modules
|
||||
that have ports with a width that depends on a parameter.
|
||||
|
||||
- The ``hdlname`` attribute is used by some passes to document the original
|
||||
(HDL) name of a module when renaming a module. It should contain a single
|
||||
name, or, when describing a hierarchical name in a flattened design, multiple
|
||||
names separated by a single space character.
|
||||
|
||||
- The ``keep`` attribute on cells and wires is used to mark objects that should
|
||||
never be removed by the optimizer. This is used for example for cells that
|
||||
have hidden connections that are not part of the netlist, such as IO pads.
|
||||
Setting the ``keep`` attribute on a module has the same effect as setting it
|
||||
on all instances of the module.
|
||||
|
||||
- The ``keep_hierarchy`` attribute on cells and modules keeps the `flatten`
|
||||
command from flattening the indicated cells and modules.
|
||||
|
||||
- The `gate_cost_equivalent` attribute on a module can be used to specify
|
||||
the estimated cost of the module as a number of basic gate instances. See
|
||||
the help message of command `keep_hierarchy` which interprets this
|
||||
attribute.
|
||||
|
||||
- The ``init`` attribute on wires is set by the frontend when a register is
|
||||
initialized "FPGA-style" with ``reg foo = val``. It can be used during
|
||||
synthesis to add the necessary reset logic.
|
||||
|
||||
- The ``top`` attribute on a module marks this module as the top of the design
|
||||
hierarchy. The `hierarchy` command sets this attribute when called with
|
||||
``-top``. Other commands, such as `flatten` and various backends use this
|
||||
attribute to determine the top module.
|
||||
|
||||
- The ``src`` attribute is set on cells and wires created by to the string
|
||||
``<hdl-file-name>:<line-number>`` by the HDL front-end and is then carried
|
||||
through the synthesis. When entities are combined, a new \|-separated string
|
||||
is created that contains all the strings from the original entities.
|
||||
|
||||
- The ``defaultvalue`` attribute is used to store default values for module
|
||||
inputs. The attribute is attached to the input wire by the HDL front-end when
|
||||
the input is declared with a default value.
|
||||
|
||||
- The ``parameter`` and ``localparam`` attributes are used to mark wires that
|
||||
represent module parameters or localparams (when the HDL front-end is run in
|
||||
``-pwires`` mode).
|
||||
|
||||
- Wires marked with the ``hierconn`` attribute are connected to wires with the
|
||||
same name (format ``cell_name.identifier``) when they are imported from
|
||||
sub-modules by `flatten`.
|
||||
|
||||
- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox
|
||||
module to mark it as a clock buffer output, and thus prevent `clkbufmap` from
|
||||
inserting another clock buffer on a net driven by such output.
|
||||
|
||||
- The ``clkbuf_sink`` attribute can be set on an input port of a module to
|
||||
request clock buffer insertion by the `clkbufmap` pass.
|
||||
|
||||
- The ``clkbuf_inv`` attribute can be set on an output port of a module with the
|
||||
value set to the name of an input port of that module. When the `clkbufmap`
|
||||
would otherwise insert a clock buffer on this output, it will instead try
|
||||
inserting the clock buffer on the input port (this is used to implement clock
|
||||
inverter cells that clock buffer insertion will "see through").
|
||||
|
||||
- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent
|
||||
automatic clock buffer insertion by `clkbufmap`. This behaviour can be
|
||||
overridden by providing a custom selection to `clkbufmap`.
|
||||
|
||||
- The ``invertible_pin`` attribute can be set on a port to mark it as invertible
|
||||
via a cell parameter. The name of the inversion parameter is specified as the
|
||||
value of this attribute. The value of the inversion parameter must be of the
|
||||
same width as the port, with 1 indicating an inverted bit and 0 indicating a
|
||||
non-inverted bit.
|
||||
|
||||
- The ``iopad_external_pin`` attribute on a blackbox module's port marks it as
|
||||
the external-facing pin of an I/O pad, and prevents `iopadmap` from inserting
|
||||
another pad cell on it.
|
||||
|
||||
- The module attribute ``abc9_lut`` is an integer attribute indicating to `abc9`
|
||||
that this module describes a LUT with an area cost of this value, and
|
||||
propagation delays described using ``specify`` statements.
|
||||
|
||||
- The module attribute ``abc9_box`` is a boolean specifying a black/white-box
|
||||
definition, with propagation delays described using ``specify`` statements,
|
||||
for use by `abc9`.
|
||||
|
||||
- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and
|
||||
carry-out (if output port) ports of a box. This information is necessary for
|
||||
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
|
||||
onto a bus port will affect only its most significant bit.
|
||||
|
||||
- The module attribute ``abc9_flop`` is a boolean marking the module as a
|
||||
flip-flop. This allows `abc9` to analyse its contents in order to perform
|
||||
sequential synthesis.
|
||||
|
||||
- The frontend sets attributes ``always_comb``, ``always_latch`` and
|
||||
``always_ff`` on processes derived from SystemVerilog style always blocks
|
||||
according to the type of the always. These are checked for correctness in
|
||||
``proc_dlatch``.
|
||||
|
||||
- The cell attribute ``wildcard_port_conns`` represents wildcard port
|
||||
connections (SystemVerilog ``.*``). These are resolved to concrete connections
|
||||
to matching wires in `hierarchy`.
|
||||
|
||||
- In addition to the ``(* ... *)`` attribute syntax, Yosys supports the
|
||||
non-standard ``{* ... *}`` attribute syntax to set default attributes for
|
||||
everything that comes after the ``{* ... *}`` statement. (Reset by adding an
|
||||
empty ``{* *}`` statement.)
|
||||
|
||||
- In module parameter and port declarations, and cell port and parameter lists,
|
||||
a trailing comma is ignored. This simplifies writing Verilog code generators a
|
||||
bit in some cases.
|
||||
|
||||
- Modules can be declared with ``module mod_name(...);`` (with three dots
|
||||
instead of a list of module ports). With this syntax it is sufficient to
|
||||
simply declare a module port as 'input' or 'output' in the module body.
|
||||
|
||||
- When defining a macro with ``\`define``, all text between triple double quotes
|
||||
is interpreted as macro body, even if it contains unescaped newlines. The
|
||||
triple double quotes are removed from the macro body. For example:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
`define MY_MACRO(a, b) """
|
||||
assign a = 23;
|
||||
assign b = 42;
|
||||
"""
|
||||
|
||||
- The attribute ``via_celltype`` can be used to implement a Verilog task or
|
||||
function by instantiating the specified cell type. The value is the name of
|
||||
the cell type to use. For functions the name of the output port can be
|
||||
specified by appending it to the cell type separated by a whitespace. The body
|
||||
of the task or function is unused in this case and can be used to specify a
|
||||
behavioral model of the cell type for simulation. For example:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module my_add3(A, B, C, Y);
|
||||
parameter WIDTH = 8;
|
||||
input [WIDTH-1:0] A, B, C;
|
||||
output [WIDTH-1:0] Y;
|
||||
...
|
||||
endmodule
|
||||
|
||||
module top;
|
||||
...
|
||||
(* via_celltype = "my_add3 Y" *)
|
||||
(* via_celltype_defparam_WIDTH = 32 *)
|
||||
function [31:0] add3;
|
||||
input [31:0] A, B, C;
|
||||
begin
|
||||
add3 = A + B + C;
|
||||
end
|
||||
endfunction
|
||||
...
|
||||
endmodule
|
||||
|
||||
- The ``wiretype`` attribute is added by the verilog parser for wires of a
|
||||
typedef'd type to indicate the type identifier.
|
||||
|
||||
- Various ``enum_value_{value}`` attributes are added to wires of an enumerated
|
||||
type to give a map of possible enum items to their values.
|
||||
|
||||
- The ``enum_base_type`` attribute is added to enum items to indicate which enum
|
||||
they belong to (enums -- anonymous and otherwise -- are automatically named
|
||||
with an auto-incrementing counter). Note that enums are currently not strongly
|
||||
typed.
|
||||
|
||||
- A limited subset of DPI-C functions is supported. The plugin mechanism (see
|
||||
``help plugin``) can be used to load .so files with implementations of DPI-C
|
||||
routines. As a non-standard extension it is possible to specify a plugin alias
|
||||
using the ``<alias>:`` syntax. For example:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
module dpitest;
|
||||
import "DPI-C" function foo:round = real my_round (real);
|
||||
parameter real r = my_round(12.345);
|
||||
endmodule
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v'
|
||||
|
||||
- Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant
|
||||
expressions as ``<size>``. If the expression is not a simple identifier, it
|
||||
must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010``
|
||||
|
||||
- The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in
|
||||
initial blocks in an unconditional context (only if/case statements on
|
||||
expressions over parameters and constant values are allowed). The intended use
|
||||
for this is synthesis-time DRC.
|
||||
|
||||
- There is limited support for converting ``specify`` .. ``endspecify``
|
||||
statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells,
|
||||
for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable
|
||||
this functionality. (By default these blocks are ignored.)
|
||||
|
||||
- The ``reprocess_after`` internal attribute is used by the Verilog frontend to
|
||||
mark cells with bindings which might depend on the specified instantiated
|
||||
module. Modules with such cells will be reprocessed during the `hierarchy`
|
||||
pass once the referenced module definition(s) become available.
|
||||
|
||||
- The ``smtlib2_module`` attribute can be set on a blackbox module to specify a
|
||||
formal model directly using SMT-LIB 2. For such a module, the
|
||||
``smtlib2_comb_expr`` attribute can be used on output ports to define their
|
||||
value using an SMT-LIB 2 expression. For example:
|
||||
|
||||
.. code-block:: verilog
|
||||
|
||||
(* blackbox *)
|
||||
(* smtlib2_module *)
|
||||
module submod(a, b);
|
||||
input [7:0] a;
|
||||
(* smtlib2_comb_expr = "(bvnot a)" *)
|
||||
output [7:0] b;
|
||||
endmodule
|
||||
|
||||
Non-standard or SystemVerilog features for formal verification
|
||||
--------------------------------------------------------------
|
||||
|
||||
- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
|
||||
when `read_verilog` is called with ``-formal``.
|
||||
|
||||
- The system task ``$initstate`` evaluates to 1 in the initial state and to 0
|
||||
otherwise.
|
||||
|
||||
- The system function ``$anyconst`` evaluates to any constant value. This is
|
||||
equivalent to declaring a reg as ``rand const``, but also works outside of
|
||||
checkers. (Yosys also supports ``rand const`` outside checkers.)
|
||||
|
||||
- The system function ``$anyseq`` evaluates to any value, possibly a different
|
||||
value in each cycle. This is equivalent to declaring a reg as ``rand``, but
|
||||
also works outside of checkers. (Yosys also supports ``rand`` variables
|
||||
outside checkers.)
|
||||
|
||||
- The system functions ``$allconst`` and ``$allseq`` can be used to construct
|
||||
formal exist-forall problems. Assumptions only hold if the trace satisfies the
|
||||
assumption for all ``$allconst/$allseq`` values. For assertions and cover
|
||||
statements it is sufficient if just one ``$allconst/$allseq`` value triggers
|
||||
the property (similar to ``$anyconst/$anyseq``).
|
||||
|
||||
- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq``
|
||||
attribute (for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if
|
||||
driven by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
|
||||
|
||||
- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
|
||||
supported in any clocked block.
|
||||
|
||||
- The syntax ``@($global_clock)`` can be used to create FFs that have no
|
||||
explicit clock input (``$ff`` cells). The same can be achieved by using
|
||||
``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>`` is
|
||||
marked with the ``(* gclk *)`` Verilog attribute.
|
||||
|
||||
|
||||
Supported features from SystemVerilog
|
||||
-------------------------------------
|
||||
|
||||
When `read_verilog` is called with ``-sv``, it accepts some language features
|
||||
from SystemVerilog:
|
||||
|
||||
- The ``assert`` statement from SystemVerilog is supported in its most basic
|
||||
form. In module context: ``assert property (<expression>);`` and within an
|
||||
always block: ``assert(<expression>);``. It is transformed to an ``$assert``
|
||||
cell.
|
||||
|
||||
- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
|
||||
also supported. The same limitations as with the ``assert`` statement apply.
|
||||
|
||||
- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
|
||||
and ``bit`` are supported.
|
||||
|
||||
- Declaring free variables with ``rand`` and ``rand const`` is supported.
|
||||
|
||||
- Checkers without a port list that do not need to be instantiated (but instead
|
||||
behave like a named block) are supported.
|
||||
|
||||
- SystemVerilog packages are supported. Once a SystemVerilog file is read into a
|
||||
design with `read_verilog`, all its packages are available to SystemVerilog
|
||||
files being read into the same design afterwards.
|
||||
|
||||
- typedefs are supported (including inside packages)
|
||||
- type casts are currently not supported
|
||||
|
||||
- enums are supported (including inside packages)
|
||||
- but are currently not strongly typed
|
||||
|
||||
- packed structs and unions are supported
|
||||
- arrays of packed structs/unions are currently not supported
|
||||
- structure literals are currently not supported
|
||||
|
||||
- multidimensional arrays are supported
|
||||
- array assignment of unpacked arrays is currently not supported
|
||||
- array literals are currently not supported
|
||||
|
||||
- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether
|
||||
ports are inputs or outputs are supported.
|
||||
|
||||
- Assignments within expressions are supported.
|
||||
Loading…
Add table
Add a link
Reference in a new issue