mirror of https://github.com/YosysHQ/yosys.git
docs: work on example_synth
Split hardware mapping from `fifo.ys` into `fifo_map.ys`. Reduces size of `fifo.out` log and allows separate yosys calls in the makefile. Some tidy up and minor changes in `fifo.ys` for better discussion. Filled out note on `clean` (changed from `opt_clean`) and introduced `;;`. Highlighted `$memrd` and added a paragraph about it. More detail on the flatten and merging of `fifo_reader` block. Brief discussion on the changes from `$memrd` to `$memrd_v2`.
This commit is contained in:
parent
50d8c1b258
commit
9f1c445fbf
|
@ -3,17 +3,21 @@ PROGRAM_PREFIX :=
|
||||||
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
|
||||||
|
|
||||||
DOT_NAMES = addr_gen_hier addr_gen_proc addr_gen_clean
|
DOT_NAMES = addr_gen_hier addr_gen_proc addr_gen_clean
|
||||||
DOT_NAMES += rdata_proc rdata_flat rdata_adffe rdata_memrdv2 rdata_alumacc
|
DOT_NAMES += rdata_proc rdata_flat rdata_adffe rdata_memrdv2 rdata_alumacc rdata_coarse
|
||||||
DOT_NAMES += rdata_coarse rdata_map_ram rdata_map_ffram rdata_map_gates
|
MAPDOT_NAMES = rdata_map_ram rdata_map_ffram rdata_map_gates
|
||||||
DOT_NAMES += rdata_map_ffs rdata_map_luts rdata_map_cells
|
MAPDOT_NAMES += rdata_map_ffs rdata_map_luts rdata_map_cells
|
||||||
|
|
||||||
DOTS := $(addsuffix .dot,$(DOT_NAMES))
|
DOTS := $(addsuffix .dot,$(DOT_NAMES))
|
||||||
|
MAPDOTS := $(addsuffix .dot,$(MAPDOT_NAMES))
|
||||||
|
|
||||||
dots: $(DOTS) fifo.out
|
dots: $(DOTS) $(MAPDOTS) fifo.out
|
||||||
|
|
||||||
$(DOTS) fifo.out: fifo.v fifo.ys
|
$(DOTS) fifo.out: fifo.v fifo.ys
|
||||||
$(YOSYS) fifo.ys -l fifo.out -Q -T
|
$(YOSYS) fifo.ys -l fifo.out -Q -T
|
||||||
|
|
||||||
|
$(MAPDOTS): fifo.v fifo_map.ys
|
||||||
|
$(YOSYS) fifo_map.ys
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f *.dot
|
rm -f *.dot
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,7 @@ select -set new_cells t:$mux t:*dff
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix addr_gen_proc
|
show -color maroon3 @new_cells -notitle -format dot -prefix addr_gen_proc
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
opt_clean
|
clean
|
||||||
show -notitle -format dot -prefix addr_gen_clean
|
show -notitle -format dot -prefix addr_gen_clean
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
|
@ -26,12 +26,15 @@ design -reset
|
||||||
read_verilog fifo.v
|
read_verilog fifo.v
|
||||||
hierarchy -check -top fifo
|
hierarchy -check -top fifo
|
||||||
proc
|
proc
|
||||||
show -color maroon3 c:fifo_reader -notitle -format dot -prefix rdata_proc o:rdata %ci*
|
select -set new_cells t:$memrd
|
||||||
|
show -color maroon3 c:fifo_reader -color cornflowerblue @new_cells -notitle -format dot -prefix rdata_proc o:rdata %ci*
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
|
|
||||||
flatten;;
|
flatten;;
|
||||||
show -notitle -format dot -prefix rdata_flat o:rdata %ci*
|
select -set rdata_path o:rdata %ci*
|
||||||
|
select -set new_cells @rdata_path o:rdata %ci3 %d i:* %d
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_flat @rdata_path
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
|
|
||||||
|
@ -53,54 +56,7 @@ show -color maroon3 @new_cells -notitle -format dot -prefix rdata_alumacc o:rdat
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
|
|
||||||
design -reset
|
memory -nomap
|
||||||
read_verilog fifo.v
|
|
||||||
synth_ice40 -top fifo -run begin:map_ram
|
|
||||||
select -set new_cells t:$mem_v2
|
select -set new_cells t:$mem_v2
|
||||||
select -set rdata_path @new_cells %ci*:-$mem_v2[WR_DATA,WR_ADDR,WR_EN] @new_cells %co* %%
|
select -set rdata_path @new_cells %ci*:-$mem_v2[WR_DATA,WR_ADDR,WR_EN] @new_cells %co* %%
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_coarse @rdata_path
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_coarse @rdata_path
|
||||||
|
|
||||||
# turn command echoes off to avoid randomly generated abc file names
|
|
||||||
echo off
|
|
||||||
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
synth_ice40 -top fifo -run map_ram:map_ffram
|
|
||||||
select -set new_cells t:SB_RAM40_4K
|
|
||||||
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_ram @rdata_path
|
|
||||||
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
synth_ice40 -top fifo -run map_ffram:map_gates
|
|
||||||
select -set new_cells t:SB_RAM40_4K
|
|
||||||
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_ffram @rdata_path
|
|
||||||
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
synth_ice40 -top fifo -run map_gates:map_ffs
|
|
||||||
select -set new_cells t:SB_RAM40_4K
|
|
||||||
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_gates @rdata_path
|
|
||||||
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
synth_ice40 -top fifo -run map_ffs:map_luts
|
|
||||||
select -set new_cells t:SB_RAM40_4K
|
|
||||||
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_ffs @rdata_path
|
|
||||||
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
synth_ice40 -top fifo -run map_luts:map_cells
|
|
||||||
select -set new_cells t:SB_RAM40_4K
|
|
||||||
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_luts @rdata_path
|
|
||||||
|
|
||||||
# ========================================================
|
|
||||||
|
|
||||||
synth_ice40 -top fifo -run map_cells:
|
|
||||||
select -set new_cells t:SB_RAM40_4K
|
|
||||||
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
|
||||||
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_cells @rdata_path
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
read_verilog fifo.v
|
||||||
|
synth_ice40 -top fifo -run begin:map_ram
|
||||||
|
# this point should be the same as rdata_coarse
|
||||||
|
|
||||||
|
# ========================================================
|
||||||
|
|
||||||
|
synth_ice40 -top fifo -run map_ram:map_ffram
|
||||||
|
select -set new_cells t:SB_RAM40_4K
|
||||||
|
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_ram @rdata_path
|
||||||
|
|
||||||
|
# ========================================================
|
||||||
|
|
||||||
|
synth_ice40 -top fifo -run map_ffram:map_gates
|
||||||
|
select -set new_cells t:SB_RAM40_4K
|
||||||
|
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_ffram @rdata_path
|
||||||
|
|
||||||
|
# ========================================================
|
||||||
|
|
||||||
|
synth_ice40 -top fifo -run map_gates:map_ffs
|
||||||
|
select -set new_cells t:SB_RAM40_4K
|
||||||
|
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_gates @rdata_path
|
||||||
|
|
||||||
|
# ========================================================
|
||||||
|
|
||||||
|
synth_ice40 -top fifo -run map_ffs:map_luts
|
||||||
|
select -set new_cells t:SB_RAM40_4K
|
||||||
|
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_ffs @rdata_path
|
||||||
|
|
||||||
|
# ========================================================
|
||||||
|
|
||||||
|
synth_ice40 -top fifo -run map_luts:map_cells
|
||||||
|
select -set new_cells t:SB_RAM40_4K
|
||||||
|
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_luts @rdata_path
|
||||||
|
|
||||||
|
# ========================================================
|
||||||
|
|
||||||
|
synth_ice40 -top fifo -run map_cells:
|
||||||
|
select -set new_cells t:SB_RAM40_4K
|
||||||
|
select -set rdata_path @new_cells %ci*:-SB_RAM40_4K[WDATA,WADDR,WE] @new_cells %co* %%
|
||||||
|
show -color maroon3 @new_cells -notitle -format dot -prefix rdata_map_cells @rdata_path
|
|
@ -149,25 +149,29 @@ each of these in more detail in :doc:`/using_yosys/synthesis/proc`.
|
||||||
:doc:`/cmd/opt_expr`
|
:doc:`/cmd/opt_expr`
|
||||||
|
|
||||||
- by default called at the end of :cmd:ref:`proc`
|
- by default called at the end of :cmd:ref:`proc`
|
||||||
|
- can be disabled with ``-noopt``
|
||||||
|
- done here for... reasons?
|
||||||
|
|
||||||
Notice how in the top left of :ref:`addr_gen_proc` we have a floating wire,
|
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
|
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
|
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
|
before we can generate the physical hardware. We can do this now by calling
|
||||||
:cmd:ref:`opt_clean`:
|
:cmd:ref:`clean`:
|
||||||
|
|
||||||
.. figure:: /_images/code_examples/fifo/addr_gen_clean.*
|
.. figure:: /_images/code_examples/fifo/addr_gen_clean.*
|
||||||
:class: width-helper
|
:class: width-helper
|
||||||
:name: addr_gen_clean
|
:name: addr_gen_clean
|
||||||
|
|
||||||
``addr_gen`` module after :cmd:ref:`opt_clean`
|
``addr_gen`` module after :cmd:ref:`clean`
|
||||||
|
|
||||||
.. TODO:: more on opt_clean
|
.. note::
|
||||||
:doc:`/cmd/opt_clean`
|
|
||||||
|
|
||||||
- :cmd:ref:`clean` for short, ``;;`` for even shorter
|
:doc:`/cmd/clean` can also be called with two semicolons after any command,
|
||||||
- final command of :cmd:ref:`opt`
|
for example we could have called :yoscrypt:`proc;;` instead of
|
||||||
- can run at any time
|
:yoscrypt:`proc` and then :yoscrypt:`clean`. It is generally beneficial to
|
||||||
|
run :cmd:ref:`clean` after each command as a quick way of removing
|
||||||
|
disconnected parts of the circuit which have been left over. You may notice
|
||||||
|
some scripts will end each line with ``;;``.
|
||||||
|
|
||||||
.. todo:: consider a brief glossary for terms like adff
|
.. todo:: consider a brief glossary for terms like adff
|
||||||
|
|
||||||
|
@ -231,11 +235,15 @@ command only works with a single module, so you may need to call it with
|
||||||
|
|
||||||
The highlighted ``fifo_reader`` block contains an instance of the
|
The highlighted ``fifo_reader`` block contains an instance of the
|
||||||
:ref:`addr_gen_proc` that we looked at earlier. Notice how the type is shown as
|
:ref:`addr_gen_proc` that we looked at earlier. Notice how the type is shown as
|
||||||
``$paramod\\addr_gen\\MAX_DATA=s32'...``. This is a "parametric module"; an
|
``$paramod\\addr_gen\\MAX_DATA=s32'...``. This is a "parametric module": an
|
||||||
instance of the ``addr_gen`` module with the ``MAX_DATA`` set to the given
|
instance of the ``addr_gen`` module with the ``MAX_DATA`` parameter set to the
|
||||||
value.
|
given value.
|
||||||
|
|
||||||
.. TODO:: comment on ``$memrd``
|
The other highlighted block is a ``$memrd`` cell. At this stage of synthesis we
|
||||||
|
don't yet know what type of memory is going to be implemented, but we *do* know
|
||||||
|
that ``rdata <= data[raddr];`` could be implemented as a read from memory. Note
|
||||||
|
that the ``$memrd`` cell here is asynchronous, with both the clock and enable
|
||||||
|
signal undefined; shown with the ``1'x`` inputs.
|
||||||
|
|
||||||
.. seealso:: Advanced usage docs for
|
.. seealso:: Advanced usage docs for
|
||||||
:doc:`/using_yosys/synthesis/proc`
|
:doc:`/using_yosys/synthesis/proc`
|
||||||
|
@ -261,7 +269,7 @@ optimizations between modules which would otherwise be missed. Let's run
|
||||||
.. literalinclude:: /code_examples/fifo/fifo.out
|
.. literalinclude:: /code_examples/fifo/fifo.out
|
||||||
:language: doscon
|
:language: doscon
|
||||||
:start-at: yosys> flatten
|
:start-at: yosys> flatten
|
||||||
:end-before: yosys> show
|
:end-before: yosys> select
|
||||||
:name: flat_clean
|
:name: flat_clean
|
||||||
:caption: output of :yoscrypt:`flatten;;`
|
:caption: output of :yoscrypt:`flatten;;`
|
||||||
|
|
||||||
|
@ -271,16 +279,24 @@ optimizations between modules which would otherwise be missed. Let's run
|
||||||
|
|
||||||
``rdata`` output after :yoscrypt:`flatten;;`
|
``rdata`` output after :yoscrypt:`flatten;;`
|
||||||
|
|
||||||
We can now see both :ref:`rdata_proc` and :ref:`addr_gen_proc` together. Note
|
.. role:: yoterm(code)
|
||||||
that in the :ref:`flat_clean` we see above has two separate calls: one to
|
:language: doscon
|
||||||
:cmd:ref:`flatten` and one to :cmd:ref:`clean`. In an interactive terminal the
|
|
||||||
output of both commands will be combined into the single `yosys> flatten;;`
|
|
||||||
output.
|
|
||||||
|
|
||||||
Depending on the target architecture, we might also see commands such as
|
The pieces have moved around a bit, but we can see :ref:`addr_gen_proc` from
|
||||||
:cmd:ref:`tribuf` with the ``-logic`` option and :cmd:ref:`deminout`. These
|
earlier has replaced the ``fifo_reader`` block in :ref:`rdata_proc`. We can
|
||||||
remove tristate and inout constructs respectively, replacing them with logic
|
also see that the ``addr`` output has been renamed to ``fifo_reader.addr`` and
|
||||||
suitable for mapping to an FPGA.
|
merged with the ``raddr`` wire feeding into the ``$memrd`` cell. This wire
|
||||||
|
merging happened during the call to :cmd:ref:`clean` which we can see in the
|
||||||
|
:ref:`flat_clean`. Note that in an interactive terminal the outputs of
|
||||||
|
:cmd:ref:`flatten` and :cmd:ref:`clean` will be combined into a single
|
||||||
|
:yoterm:`yosys> flatten;;` output.
|
||||||
|
|
||||||
|
Depending on the target architecture, this stage of synthesis might also see
|
||||||
|
commands such as :cmd:ref:`tribuf` with the ``-logic`` option and
|
||||||
|
:cmd:ref:`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
|
The coarse-grain representation
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -314,18 +330,18 @@ In the iCE40 flow, we start with the following commands:
|
||||||
:caption: ``coarse`` section (part 1)
|
:caption: ``coarse`` section (part 1)
|
||||||
:name: synth_coarse1
|
:name: synth_coarse1
|
||||||
|
|
||||||
The first few commands are relatively straightforward, and we've already come
|
We've already come across :cmd:ref:`opt_expr`, and :cmd:ref:`opt_clean` is the
|
||||||
across :cmd:ref:`opt_clean` and :cmd:ref:`opt_expr`. The :cmd:ref:`check` pass
|
same as :cmd:ref:`clean` but with more verbose output. The :cmd:ref:`check`
|
||||||
identifies a few obvious problems which will cause errors later. Calling it
|
pass identifies a few obvious problems which will cause errors later. Calling
|
||||||
here lets us fail faster rather than wasting time on something we know is
|
it here lets us fail faster rather than wasting time on something we know is
|
||||||
impossible.
|
impossible.
|
||||||
|
|
||||||
Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple
|
Next up is :yoscrypt:`opt -nodffe -nosdff` performing a set of simple
|
||||||
optimizations on the design. This command also ensures that only a specific
|
optimizations on the design. This command also ensures that only a specific
|
||||||
subset of FF types are included, in preparation for the next command:
|
subset of FF types are included, in preparation for the next command:
|
||||||
:doc:`/cmd/fsm`. Both :cmd:ref:`opt` and :cmd:ref:`fsm` are macro commands
|
:doc:`/cmd/fsm`. Both :cmd:ref:`opt` and :cmd:ref:`fsm` are macro commands
|
||||||
which are explored in more detail in :doc:`/using_yosys/synthesis/fsm` and
|
which are explored in more detail in :doc:`/using_yosys/synthesis/opt` and
|
||||||
:doc:`/using_yosys/synthesis/opt` respectively.
|
:doc:`/using_yosys/synthesis/fsm` respectively.
|
||||||
|
|
||||||
Up until now, the data path for ``rdata`` has remained the same since
|
Up until now, the data path for ``rdata`` has remained the same since
|
||||||
:ref:`rdata_flat`. However the next call to :cmd:ref:`opt` does cause a change.
|
:ref:`rdata_flat`. However the next call to :cmd:ref:`opt` does cause a change.
|
||||||
|
@ -384,7 +400,10 @@ Our next command to run is
|
||||||
``rdata`` output after :cmd:ref:`memory_dff`
|
``rdata`` output after :cmd:ref:`memory_dff`
|
||||||
|
|
||||||
As the title suggests, :cmd:ref:`memory_dff` has merged the output ``$dff`` into
|
As the title suggests, :cmd:ref:`memory_dff` has merged the output ``$dff`` into
|
||||||
the ``$memrd`` cell and converted it to a ``$memrd_v2`` (highlighted).
|
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.
|
||||||
|
|
||||||
.. seealso:: Advanced usage docs for
|
.. seealso:: Advanced usage docs for
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue