mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-27 10:55:51 +00:00
Docs: Reflow line length
This commit is contained in:
parent
829e02ec5b
commit
40ba92e956
20 changed files with 782 additions and 785 deletions
|
@ -2,13 +2,12 @@ Synthesis starter
|
|||
-----------------
|
||||
|
||||
This page will be a guided walkthrough of the prepackaged iCE40 FPGA synthesis
|
||||
script - `synth_ice40`. We will take a simple design through each
|
||||
step, looking at the commands being called and what they do to the design. While
|
||||
`synth_ice40` is specific to the iCE40 platform, most of the operations
|
||||
we will be discussing are common across the majority of FPGA synthesis scripts.
|
||||
Thus, this document will provide a good foundational understanding of how
|
||||
synthesis in Yosys is performed, regardless of the actual architecture being
|
||||
used.
|
||||
script - `synth_ice40`. We will take a simple design through each step, looking
|
||||
at the commands being called and what they do to the design. While `synth_ice40`
|
||||
is specific to the iCE40 platform, most of the operations we will be discussing
|
||||
are common across the majority of FPGA synthesis scripts. Thus, this document
|
||||
will provide a good foundational understanding of how synthesis in Yosys is
|
||||
performed, regardless of the actual architecture being used.
|
||||
|
||||
.. seealso:: Advanced usage docs for
|
||||
:doc:`/using_yosys/synthesis/synth`
|
||||
|
@ -105,10 +104,10 @@ Since we're just getting started, let's instead begin with :yoscrypt:`hierarchy
|
|||
|
||||
.. note::
|
||||
|
||||
`hierarchy` should always be the first command after the design has
|
||||
been read. By specifying the top module, `hierarchy` will also set
|
||||
the ``(* top *)`` attribute on it. This is used by other commands that need
|
||||
to know which module is the top.
|
||||
`hierarchy` should always be the first command after the design has been
|
||||
read. By specifying the top module, `hierarchy` will also set the ``(* top
|
||||
*)`` attribute on it. This is used by other commands that need to know which
|
||||
module is the top.
|
||||
|
||||
.. use doscon for a console-like display that supports the `yosys> [command]` format.
|
||||
|
||||
|
@ -129,20 +128,20 @@ Our ``addr_gen`` circuit now looks like this:
|
|||
|
||||
Simple operations like ``addr + 1`` and ``addr == MAX_DATA-1`` can be extracted
|
||||
from our ``always @`` block in :ref:`addr_gen-v`. This gives us the highlighted
|
||||
`$add` and `$eq` cells we see. But control logic (like the ``if .. else``)
|
||||
and memory elements (like the ``addr <= 0``) are not so straightforward. These
|
||||
get put into "processes", shown in the schematic as ``PROC``. Note how the
|
||||
second line refers to the line numbers of the start/end of the corresponding
|
||||
``always @`` block. In the case of an ``initial`` block, we instead see the
|
||||
``PROC`` referring to line 0.
|
||||
`$add` and `$eq` cells we see. But control logic (like the ``if .. else``) and
|
||||
memory elements (like the ``addr <= 0``) are not so straightforward. These get
|
||||
put into "processes", shown in the schematic as ``PROC``. Note how the second
|
||||
line refers to the line numbers of the start/end of the corresponding ``always
|
||||
@`` block. In the case of an ``initial`` block, we instead see the ``PROC``
|
||||
referring to line 0.
|
||||
|
||||
To handle these, let us now introduce the next command: :doc:`/cmd/proc`.
|
||||
`proc` is a macro command like `synth_ice40`. Rather than
|
||||
modifying the design directly, it instead calls a series of other commands. In
|
||||
the case of `proc`, these sub-commands work to convert the behavioral
|
||||
logic of processes into multiplexers and registers. Let's see what happens when
|
||||
we run it. For now, we will call :yoscrypt:`proc -noopt` to prevent some
|
||||
automatic optimizations which would normally happen.
|
||||
To handle these, let us now introduce the next command: :doc:`/cmd/proc`. `proc`
|
||||
is a macro command like `synth_ice40`. Rather than modifying the design
|
||||
directly, it instead calls a series of other commands. In the case of `proc`,
|
||||
these sub-commands work to convert the behavioral logic of processes into
|
||||
multiplexers and registers. Let's see what happens when we run it. For now, we
|
||||
will call :yoscrypt:`proc -noopt` to prevent some automatic optimizations which
|
||||
would normally happen.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/addr_gen_proc.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -151,19 +150,18 @@ automatic optimizations which would normally happen.
|
|||
``addr_gen`` module after :yoscrypt:`proc -noopt`
|
||||
|
||||
There are now a few new cells from our ``always @``, which have been
|
||||
highlighted. The ``if`` statements are now modeled with `$mux` cells, while
|
||||
the register uses an `$adff` cell. If we look at the terminal output we can
|
||||
also see all of the different ``proc_*`` commands being called. We will look at
|
||||
each of these in more detail in :doc:`/using_yosys/synthesis/proc`.
|
||||
highlighted. The ``if`` statements are now modeled with `$mux` cells, while the
|
||||
register uses an `$adff` cell. If we look at the terminal output we can also
|
||||
see all of the different ``proc_*`` commands being called. We will look at each
|
||||
of these in more detail in :doc:`/using_yosys/synthesis/proc`.
|
||||
|
||||
Notice how in the top left of :ref:`addr_gen_proc` we have a floating wire,
|
||||
generated from the initial assignment of 0 to the ``addr`` wire. However, this
|
||||
initial assignment is not synthesizable, so this will need to be cleaned up
|
||||
before we can generate the physical hardware. We can do this now by calling
|
||||
`clean`. We're also going to call `opt_expr` now, which would
|
||||
normally be called at the end of `proc`. We can call both commands at
|
||||
the same time by separating them with a colon and space: :yoscrypt:`opt_expr;
|
||||
clean`.
|
||||
`clean`. We're also going to call `opt_expr` now, which would normally be
|
||||
called at the end of `proc`. We can call both commands at the same time by
|
||||
separating them with a colon and space: :yoscrypt:`opt_expr; clean`.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/addr_gen_clean.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -171,24 +169,24 @@ clean`.
|
|||
|
||||
``addr_gen`` module after :yoscrypt:`opt_expr; clean`
|
||||
|
||||
You may also notice that the highlighted `$eq` cell input of ``255`` has
|
||||
changed to ``8'11111111``. Constant values are presented in the format
|
||||
You may also notice that the highlighted `$eq` cell input of ``255`` has changed
|
||||
to ``8'11111111``. Constant values are presented in the format
|
||||
``<bit_width>'<bits>``, with 32-bit values instead using the decimal number.
|
||||
This indicates that the constant input has been reduced from 32-bit wide to
|
||||
8-bit wide. This is a side-effect of running `opt_expr`, which
|
||||
performs constant folding and simple expression rewriting. For more on why
|
||||
this happens, refer to :doc:`/using_yosys/synthesis/opt` and the :ref:`section
|
||||
on opt_expr <adv_opt_expr>`.
|
||||
8-bit wide. This is a side-effect of running `opt_expr`, which performs
|
||||
constant folding and simple expression rewriting. For more on why this
|
||||
happens, refer to :doc:`/using_yosys/synthesis/opt` and the :ref:`section on
|
||||
opt_expr <adv_opt_expr>`.
|
||||
|
||||
.. note::
|
||||
|
||||
:doc:`/cmd/clean` can also be called with two semicolons after any command,
|
||||
for example we could have called :yoscrypt:`opt_expr;;` instead of
|
||||
:yoscrypt:`opt_expr; clean`. You may notice some scripts will end each line
|
||||
with ``;;``. It is beneficial to run `clean` before inspecting
|
||||
intermediate products to remove disconnected parts of the circuit which have
|
||||
been left over, and in some cases can reduce the processing required in
|
||||
subsequent commands.
|
||||
with ``;;``. It is beneficial to run `clean` before inspecting intermediate
|
||||
products to remove disconnected parts of the circuit which have been left
|
||||
over, and in some cases can reduce the processing required in subsequent
|
||||
commands.
|
||||
|
||||
.. todo:: consider a brief glossary for terms like adff
|
||||
|
||||
|
@ -202,8 +200,8 @@ The full example
|
|||
|
||||
Let's now go back and check on our full design by using :yoscrypt:`hierarchy
|
||||
-check -top fifo`. By passing the ``-check`` option there we are also telling
|
||||
the `hierarchy` command that if the design includes any non-blackbox
|
||||
modules without an implementation it should return an error.
|
||||
the `hierarchy` command that if the design includes any non-blackbox modules
|
||||
without an implementation it should return an error.
|
||||
|
||||
Note that if we tried to run this command now then we would get an error. This
|
||||
is because we already removed all of the modules other than ``addr_gen``. We
|
||||
|
@ -221,13 +219,12 @@ could restart our shell session, but instead let's use two new commands:
|
|||
Notice how this time we didn't see any of those ``$abstract`` modules? That's
|
||||
because when we ran ``yosys fifo.v``, the first command Yosys called was
|
||||
:yoscrypt:`read_verilog -defer fifo.v`. The ``-defer`` option there tells
|
||||
`read_verilog` only read the abstract syntax tree and defer actual
|
||||
compilation to a later `hierarchy` command. This is useful in cases
|
||||
where the default parameters of modules yield invalid code which is not
|
||||
synthesizable. This is why Yosys defers compilation automatically and is one of
|
||||
the reasons why hierarchy should always be the first command after loading the
|
||||
design. If we know that our design won't run into this issue, we can skip the
|
||||
``-defer``.
|
||||
`read_verilog` only read the abstract syntax tree and defer actual compilation
|
||||
to a later `hierarchy` command. This is useful in cases where the default
|
||||
parameters of modules yield invalid code which is not synthesizable. This is why
|
||||
Yosys defers compilation automatically and is one of the reasons why hierarchy
|
||||
should always be the first command after loading the design. If we know that
|
||||
our design won't run into this issue, we can skip the ``-defer``.
|
||||
|
||||
.. todo:: `hierarchy` failure modes
|
||||
|
||||
|
@ -243,13 +240,13 @@ design. If we know that our design won't run into this issue, we can skip the
|
|||
interactive terminal. :kbd:`ctrl+c` (i.e. SIGINT) will also end the terminal
|
||||
session but will return an error code rather than exiting gracefully.
|
||||
|
||||
We can also run `proc` now to finish off the full :ref:`synth_begin`.
|
||||
Because the design schematic is quite large, we will be showing just the data
|
||||
path for the ``rdata`` output. If you would like to see the entire design for
|
||||
yourself, you can do so with :doc:`/cmd/show`. Note that the `show`
|
||||
command only works with a single module, so you may need to call it with
|
||||
:yoscrypt:`show fifo`. :ref:`show_intro` section in
|
||||
:doc:`/getting_started/scripting_intro` has more on how to use `show`.
|
||||
We can also run `proc` now to finish off the full :ref:`synth_begin`. Because
|
||||
the design schematic is quite large, we will be showing just the data path for
|
||||
the ``rdata`` output. If you would like to see the entire design for yourself,
|
||||
you can do so with :doc:`/cmd/show`. Note that the `show` command only works
|
||||
with a single module, so you may need to call it with :yoscrypt:`show fifo`.
|
||||
:ref:`show_intro` section in :doc:`/getting_started/scripting_intro` has more on
|
||||
how to use `show`.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_proc.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -321,11 +318,10 @@ merging happened during the call to `clean` which we can see in the
|
|||
output.
|
||||
|
||||
Depending on the target architecture, this stage of synthesis might also see
|
||||
commands such as `tribuf` with the ``-logic`` option and
|
||||
`deminout`. These remove tristate and inout constructs respectively,
|
||||
replacing them with logic suitable for mapping to an FPGA. Since we do not have
|
||||
any such constructs in our example running these commands does not change our
|
||||
design.
|
||||
commands such as `tribuf` with the ``-logic`` option and `deminout`. These
|
||||
remove tristate and inout constructs respectively, replacing them with logic
|
||||
suitable for mapping to an FPGA. Since we do not have any such constructs in
|
||||
our example running these commands does not change our design.
|
||||
|
||||
The coarse-grain representation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -342,9 +338,9 @@ optimizations and other transformations done previously.
|
|||
|
||||
.. note::
|
||||
|
||||
While the iCE40 flow had a :ref:`synth_flatten` and put `proc` in
|
||||
the :ref:`synth_begin`, some synthesis scripts will instead include these in
|
||||
this section.
|
||||
While the iCE40 flow had a :ref:`synth_flatten` and put `proc` in the
|
||||
:ref:`synth_begin`, some synthesis scripts will instead include these in this
|
||||
section.
|
||||
|
||||
Part 1
|
||||
^^^^^^
|
||||
|
@ -359,24 +355,23 @@ In the iCE40 flow, we start with the following commands:
|
|||
:caption: ``coarse`` section (part 1)
|
||||
:name: synth_coarse1
|
||||
|
||||
We've already come across `opt_expr`, and `opt_clean` is the
|
||||
same as `clean` but with more verbose output. The `check`
|
||||
pass identifies a few obvious problems which will cause errors later. Calling
|
||||
it here lets us fail faster rather than wasting time on something we know is
|
||||
impossible.
|
||||
We've already come across `opt_expr`, and `opt_clean` is the same as `clean` but
|
||||
with more verbose output. The `check` pass identifies a few obvious problems
|
||||
which will cause errors later. Calling it here lets us fail faster rather than
|
||||
wasting time on something we know is impossible.
|
||||
|
||||
Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple
|
||||
optimizations on the design. This command also ensures that only a specific
|
||||
subset of FF types are included, in preparation for the next command:
|
||||
:doc:`/cmd/fsm`. Both `opt` and `fsm` are macro commands
|
||||
which are explored in more detail in :doc:`/using_yosys/synthesis/opt` and
|
||||
:doc:`/cmd/fsm`. Both `opt` and `fsm` are macro commands which are explored in
|
||||
more detail in :doc:`/using_yosys/synthesis/opt` and
|
||||
:doc:`/using_yosys/synthesis/fsm` respectively.
|
||||
|
||||
Up until now, the data path for ``rdata`` has remained the same since
|
||||
:ref:`rdata_flat`. However the next call to `opt` does cause a change.
|
||||
Specifically, the call to `opt_dff` without the ``-nodffe -nosdff``
|
||||
options is able to fold one of the `$mux` cells into the `$adff` to form an
|
||||
`$adffe` cell; highlighted below:
|
||||
Specifically, the call to `opt_dff` without the ``-nodffe -nosdff`` options is
|
||||
able to fold one of the `$mux` cells into the `$adff` to form an `$adffe` cell;
|
||||
highlighted below:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.out
|
||||
:language: doscon
|
||||
|
@ -433,8 +428,8 @@ The next two (new) commands are :doc:`/cmd/peepopt` and :doc:`/cmd/share`.
|
|||
Neither of these affect our design, and they're explored in more detail in
|
||||
:doc:`/using_yosys/synthesis/opt`, so let's skip over them. :yoscrypt:`techmap
|
||||
-map +/cmp2lut.v -D LUT_WIDTH=4` optimizes certain comparison operators by
|
||||
converting them to LUTs instead. The usage of `techmap` is explored
|
||||
more in :doc:`/using_yosys/synthesis/techmap_synth`.
|
||||
converting them to LUTs instead. The usage of `techmap` is explored more in
|
||||
:doc:`/using_yosys/synthesis/techmap_synth`.
|
||||
|
||||
Our next command to run is
|
||||
:doc:`/cmd/memory_dff`.
|
||||
|
@ -451,9 +446,9 @@ Our next command to run is
|
|||
|
||||
``rdata`` output after `memory_dff`
|
||||
|
||||
As the title suggests, `memory_dff` has merged the output `$dff` into
|
||||
the `$memrd` cell and converted it to a `$memrd_v2` (highlighted). This has
|
||||
also connected the ``CLK`` port to the ``clk`` input as it is now a synchronous
|
||||
As the title suggests, `memory_dff` has merged the output `$dff` into the
|
||||
`$memrd` cell and converted it to a `$memrd_v2` (highlighted). This has also
|
||||
connected the ``CLK`` port to the ``clk`` input as it is now a synchronous
|
||||
memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and
|
||||
``SRST=1'0``) inputs.
|
||||
|
||||
|
@ -466,12 +461,11 @@ memory read with appropriate enable (``EN=1'1``) and reset (``ARST=1'0`` and
|
|||
Part 3
|
||||
^^^^^^
|
||||
|
||||
The third part of the `synth_ice40` flow is a series of commands for
|
||||
mapping to DSPs. By default, the iCE40 flow will not map to the hardware DSP
|
||||
blocks and will only be performed if called with the ``-dsp`` flag:
|
||||
:yoscrypt:`synth_ice40 -dsp`. While our example has nothing that could be
|
||||
mapped to DSPs we can still take a quick look at the commands here and describe
|
||||
what they do.
|
||||
The third part of the `synth_ice40` flow is a series of commands for mapping to
|
||||
DSPs. By default, the iCE40 flow will not map to the hardware DSP blocks and
|
||||
will only be performed if called with the ``-dsp`` flag: :yoscrypt:`synth_ice40
|
||||
-dsp`. While our example has nothing that could be mapped to DSPs we can still
|
||||
take a quick look at the commands here and describe what they do.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -483,28 +477,26 @@ what they do.
|
|||
|
||||
:yoscrypt:`wreduce t:$mul` performs width reduction again, this time targetting
|
||||
only cells of type `$mul`. :yoscrypt:`techmap -map +/mul2dsp.v -map
|
||||
+/ice40/dsp_map.v ... -D DSP_NAME=$__MUL16X16` uses `techmap` to map
|
||||
`$mul` cells to ``$__MUL16X16`` which are, in turn, mapped to the iCE40
|
||||
``SB_MAC16``. Any multipliers which aren't compatible with conversion to
|
||||
``$__MUL16X16`` are relabelled to ``$__soft_mul`` before `chtype`
|
||||
changes them back to `$mul`.
|
||||
+/ice40/dsp_map.v ... -D DSP_NAME=$__MUL16X16` uses `techmap` to map `$mul`
|
||||
cells to ``$__MUL16X16`` which are, in turn, mapped to the iCE40 ``SB_MAC16``.
|
||||
Any multipliers which aren't compatible with conversion to ``$__MUL16X16`` are
|
||||
relabelled to ``$__soft_mul`` before `chtype` changes them back to `$mul`.
|
||||
|
||||
During the mul2dsp conversion, some of the intermediate signals are marked with
|
||||
the attribute ``mul2dsp``. By calling :yoscrypt:`select a:mul2dsp` we restrict
|
||||
the following commands to only operate on the cells and wires used for these
|
||||
signals. `setattr` removes the now unnecessary ``mul2dsp`` attribute.
|
||||
`opt_expr` we've already come across for const folding and simple
|
||||
expression rewriting, the ``-fine`` option just enables more fine-grain
|
||||
optimizations. Then we perform width reduction a final time and clear the
|
||||
selection.
|
||||
`opt_expr` we've already come across for const folding and simple expression
|
||||
rewriting, the ``-fine`` option just enables more fine-grain optimizations.
|
||||
Then we perform width reduction a final time and clear the selection.
|
||||
|
||||
.. todo:: ``ice40_dsp`` is pmgen
|
||||
|
||||
Finally we have `ice40_dsp`: similar to the `memory_dff`
|
||||
command we saw in the previous section, this merges any surrounding registers
|
||||
into the ``SB_MAC16`` cell. This includes not just the input/output registers,
|
||||
but also pipeline registers and even a post-adder where applicable: turning a
|
||||
multiply + add into a single multiply-accumulate.
|
||||
Finally we have `ice40_dsp`: similar to the `memory_dff` command we saw in the
|
||||
previous section, this merges any surrounding registers into the ``SB_MAC16``
|
||||
cell. This includes not just the input/output registers, but also pipeline
|
||||
registers and even a post-adder where applicable: turning a multiply + add into
|
||||
a single multiply-accumulate.
|
||||
|
||||
.. seealso:: Advanced usage docs for
|
||||
:doc:`/using_yosys/synthesis/techmap_synth`
|
||||
|
@ -522,11 +514,10 @@ That brings us to the fourth and final part for the iCE40 synthesis flow:
|
|||
:caption: ``coarse`` section (part 4)
|
||||
:name: synth_coarse4
|
||||
|
||||
Where before each type of arithmetic operation had its own cell, e.g. `$add`,
|
||||
we now want to extract these into `$alu` and `$macc` cells which can help
|
||||
identify opportunities for reusing logic. We do this by running
|
||||
`alumacc`, which we can see produce the following changes in our
|
||||
example design:
|
||||
Where before each type of arithmetic operation had its own cell, e.g. `$add`, we
|
||||
now want to extract these into `$alu` and `$macc` cells which can help identify
|
||||
opportunities for reusing logic. We do this by running `alumacc`, which we can
|
||||
see produce the following changes in our example design:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.out
|
||||
:language: doscon
|
||||
|
@ -540,17 +531,17 @@ example design:
|
|||
|
||||
``rdata`` output after `alumacc`
|
||||
|
||||
Once these cells have been inserted, the call to `opt` can combine
|
||||
cells which are now identical but may have been missed due to e.g. the
|
||||
difference between `$add` and `$sub`.
|
||||
Once these cells have been inserted, the call to `opt` can combine cells which
|
||||
are now identical but may have been missed due to e.g. the difference between
|
||||
`$add` and `$sub`.
|
||||
|
||||
The other new command in this part is :doc:`/cmd/memory`. `memory` is
|
||||
another macro command which we examine in more detail in
|
||||
The other new command in this part is :doc:`/cmd/memory`. `memory` is another
|
||||
macro command which we examine in more detail in
|
||||
:doc:`/using_yosys/synthesis/memory`. For this document, let us focus just on
|
||||
the step most relevant to our example: `memory_collect`. Up until this
|
||||
point, our memory reads and our memory writes have been totally disjoint cells;
|
||||
operating on the same memory only in the abstract. `memory_collect`
|
||||
combines all of the reads and writes for a memory block into a single cell.
|
||||
the step most relevant to our example: `memory_collect`. Up until this point,
|
||||
our memory reads and our memory writes have been totally disjoint cells;
|
||||
operating on the same memory only in the abstract. `memory_collect` combines all
|
||||
of the reads and writes for a memory block into a single cell.
|
||||
|
||||
.. figure:: /_images/code_examples/fifo/rdata_coarse.*
|
||||
:class: width-helper invert-helper
|
||||
|
@ -609,19 +600,19 @@ Mapping to hard memory blocks uses a combination of `memory_libmap` and
|
|||
|
||||
``rdata`` output after :ref:`map_ram`
|
||||
|
||||
The :ref:`map_ram` converts the generic `$mem_v2` into the iCE40
|
||||
``SB_RAM40_4K`` (highlighted). We can also see the memory address has been
|
||||
remapped, and the data bits have been reordered (or swizzled). There is also
|
||||
now a `$mux` cell controlling the value of ``rdata``. In :ref:`fifo-v` we
|
||||
wrote our memory as read-before-write, however the ``SB_RAM40_4K`` has undefined
|
||||
behaviour when reading from and writing to the same address in the same cycle.
|
||||
As a result, extra logic is added so that the generated circuit matches the
|
||||
behaviour of the verilog. :ref:`no_rw_check` describes how we could change our
|
||||
verilog to match our hardware instead.
|
||||
The :ref:`map_ram` converts the generic `$mem_v2` into the iCE40 ``SB_RAM40_4K``
|
||||
(highlighted). We can also see the memory address has been remapped, and the
|
||||
data bits have been reordered (or swizzled). There is also now a `$mux` cell
|
||||
controlling the value of ``rdata``. In :ref:`fifo-v` we wrote our memory as
|
||||
read-before-write, however the ``SB_RAM40_4K`` has undefined behaviour when
|
||||
reading from and writing to the same address in the same cycle. As a result,
|
||||
extra logic is added so that the generated circuit matches the behaviour of the
|
||||
verilog. :ref:`no_rw_check` describes how we could change our verilog to match
|
||||
our hardware instead.
|
||||
|
||||
If we run `memory_libmap` under the `debug` command we can see
|
||||
candidates which were identified for mapping, along with the costs of each and
|
||||
what logic requires emulation.
|
||||
If we run `memory_libmap` under the `debug` command we can see candidates which
|
||||
were identified for mapping, along with the costs of each and what logic
|
||||
requires emulation.
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.libmap
|
||||
:language: doscon
|
||||
|
@ -667,11 +658,10 @@ into flip flops (the ``logic fallback``) with `memory_map`.
|
|||
Arithmetic
|
||||
^^^^^^^^^^
|
||||
|
||||
Uses `techmap` to map basic arithmetic logic to hardware. This sees
|
||||
somewhat of an explosion in cells as multi-bit :cell:ref:`$mux` and `$adffe` are
|
||||
replaced with single-bit `$_MUX_` and `$_DFFE_PP0P_` cells, while the
|
||||
:cell:ref:`$alu` is replaced with primitive `$_OR_` and `$_NOT_` gates and a
|
||||
`$lut` cell.
|
||||
Uses `techmap` to map basic arithmetic logic to hardware. This sees somewhat of
|
||||
an explosion in cells as multi-bit `$mux` and `$adffe` are replaced with
|
||||
single-bit `$_MUX_` and `$_DFFE_PP0P_` cells, while the `$alu` is replaced with
|
||||
primitive `$_OR_` and `$_NOT_` gates and a `$lut` cell.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -693,12 +683,12 @@ replaced with single-bit `$_MUX_` and `$_DFFE_PP0P_` cells, while the
|
|||
Flip-flops
|
||||
^^^^^^^^^^
|
||||
|
||||
Convert FFs to the types supported in hardware with `dfflegalize`, and
|
||||
then use `techmap` to map them. In our example, this converts the
|
||||
`$_DFFE_PP0P_` cells to ``SB_DFFER``.
|
||||
Convert FFs to the types supported in hardware with `dfflegalize`, and then use
|
||||
`techmap` to map them. In our example, this converts the `$_DFFE_PP0P_` cells
|
||||
to ``SB_DFFER``.
|
||||
|
||||
We also run `simplemap` here to convert any remaining cells which could
|
||||
not be mapped to hardware into gate-level primitives. This includes optimizing
|
||||
We also run `simplemap` here to convert any remaining cells which could not be
|
||||
mapped to hardware into gate-level primitives. This includes optimizing
|
||||
`$_MUX_` cells where one of the inputs is a constant ``1'0``, replacing it
|
||||
instead with an `$_AND_` cell.
|
||||
|
||||
|
@ -722,11 +712,10 @@ instead with an `$_AND_` cell.
|
|||
LUTs
|
||||
^^^^
|
||||
|
||||
`abc` and `techmap` are used to map LUTs; converting primitive
|
||||
cell types to use `$lut` and ``SB_CARRY`` cells. Note that the iCE40 flow
|
||||
uses `abc9` rather than `abc`. For more on what these do, and
|
||||
what the difference between these two commands are, refer to
|
||||
:doc:`/using_yosys/synthesis/abc`.
|
||||
`abc` and `techmap` are used to map LUTs; converting primitive cell types to use
|
||||
`$lut` and ``SB_CARRY`` cells. Note that the iCE40 flow uses `abc9` rather than
|
||||
`abc`. For more on what these do, and what the difference between these two
|
||||
commands are, refer to :doc:`/using_yosys/synthesis/abc`.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -742,8 +731,8 @@ what the difference between these two commands are, refer to
|
|||
|
||||
``rdata`` output after :ref:`map_luts`
|
||||
|
||||
Finally we use `techmap` to map the generic `$lut` cells to iCE40
|
||||
``SB_LUT4`` cells.
|
||||
Finally we use `techmap` to map the generic `$lut` cells to iCE40 ``SB_LUT4``
|
||||
cells.
|
||||
|
||||
.. literalinclude:: /cmd/synth_ice40.rst
|
||||
:language: yoscrypt
|
||||
|
@ -801,28 +790,27 @@ The new commands here are:
|
|||
- :doc:`/cmd/stat`, and
|
||||
- :doc:`/cmd/blackbox`.
|
||||
|
||||
The output from `stat` is useful for checking resource utilization;
|
||||
providing a list of cells used in the design and the number of each, as well as
|
||||
the number of other resources used such as wires and processes. For this
|
||||
design, the final call to `stat` should look something like the
|
||||
following:
|
||||
The output from `stat` is useful for checking resource utilization; providing a
|
||||
list of cells used in the design and the number of each, as well as the number
|
||||
of other resources used such as wires and processes. For this design, the final
|
||||
call to `stat` should look something like the following:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.stat
|
||||
:language: doscon
|
||||
:start-at: yosys> stat -top fifo
|
||||
|
||||
Note that the :yoscrypt:`-top fifo` here is optional. `stat` will
|
||||
automatically use the module with the ``top`` attribute set, which ``fifo`` was
|
||||
when we called `hierarchy`. If no module is marked ``top``, then stats
|
||||
will be shown for each module selected.
|
||||
Note that the :yoscrypt:`-top fifo` here is optional. `stat` will automatically
|
||||
use the module with the ``top`` attribute set, which ``fifo`` was when we called
|
||||
`hierarchy`. If no module is marked ``top``, then stats will be shown for each
|
||||
module selected.
|
||||
|
||||
The `stat` output is also useful as a kind of sanity-check: Since we
|
||||
have already run `proc`, we wouldn't expect there to be any processes.
|
||||
We also expect ``data`` to use hard memory; if instead of an ``SB_RAM40_4K`` saw
|
||||
a high number of flip-flops being used we might suspect something was wrong.
|
||||
The `stat` output is also useful as a kind of sanity-check: Since we have
|
||||
already run `proc`, we wouldn't expect there to be any processes. We also expect
|
||||
``data`` to use hard memory; if instead of an ``SB_RAM40_4K`` saw a high number
|
||||
of flip-flops being used we might suspect something was wrong.
|
||||
|
||||
If we instead called `stat` immediately after :yoscrypt:`read_verilog
|
||||
fifo.v` we would see something very different:
|
||||
If we instead called `stat` immediately after :yoscrypt:`read_verilog fifo.v` we
|
||||
would see something very different:
|
||||
|
||||
.. literalinclude:: /code_examples/fifo/fifo.stat
|
||||
:language: doscon
|
||||
|
@ -845,10 +833,10 @@ The iCE40 synthesis flow has the following output modes available:
|
|||
|
||||
As an example, if we called :yoscrypt:`synth_ice40 -top fifo -json fifo.json`,
|
||||
our synthesized ``fifo`` design will be output as :file:`fifo.json`. We can
|
||||
then read the design back into Yosys with `read_json`, but make sure
|
||||
you use :yoscrypt:`design -reset` or open a new interactive terminal first. The
|
||||
JSON output we get can also be loaded into `nextpnr`_ to do place and route; but
|
||||
that is beyond the scope of this documentation.
|
||||
then read the design back into Yosys with `read_json`, but make sure you use
|
||||
:yoscrypt:`design -reset` or open a new interactive terminal first. The JSON
|
||||
output we get can also be loaded into `nextpnr`_ to do place and route; but that
|
||||
is beyond the scope of this documentation.
|
||||
|
||||
.. _nextpnr: https://github.com/YosysHQ/nextpnr
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue