New example_synth code

`example_synth.rst` updated down to coarse-grain representation.
This commit is contained in:
Krystine Sherwin 2023-12-14 16:21:52 +13:00
parent 6d1caf6134
commit 80c78aaad6
No known key found for this signature in database
5 changed files with 388 additions and 73 deletions

View File

@ -0,0 +1,15 @@
PROGRAM_PREFIX :=
YOSYS ?= ../../../../$(PROGRAM_PREFIX)yosys
DOTS = control_hier.dot control_proc.dot
DOTS += example_hier.dot
dots: $(DOTS) example.out
$(DOTS) example.out: example.v example.ys
$(YOSYS) example.ys -l example.out -Q
.PHONY: clean
clean:
rm -f *.dot

View File

@ -0,0 +1,147 @@
-- Executing script file `example.ys' --
echo on
yosys> read_verilog -defer example.v
1. Executing Verilog-2005 frontend: example.v
Parsing Verilog input from `example.v' to AST representation.
Storing AST representation for module `$abstract\example'.
Storing AST representation for module `$abstract\control'.
Storing AST representation for module `$abstract\data'.
Successfully finished Verilog frontend.
yosys> hierarchy -top control
2. Executing HIERARCHY pass (managing design hierarchy).
3. Executing AST frontend in derive mode using pre-parsed AST for module `\control'.
Generating RTLIL representation for module `\control'.
3.1. Analyzing design hierarchy..
Top module: \control
3.2. Analyzing design hierarchy..
Top module: \control
Removing unused module `$abstract\data'.
Removing unused module `$abstract\control'.
Removing unused module `$abstract\example'.
Removed 3 unused modules.
yosys> show -notitle -format dot -prefix control_hier
4. Generating Graphviz representation of design.
Writing dot description to `control_hier.dot'.
Dumping module control to page 1.
yosys> proc
5. Executing PROC pass (convert processes to netlists).
yosys> proc_clean
5.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.
yosys> proc_rmdead
5.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Marked 1 switch rules as full_case in process $proc$example.v:43$1 in module control.
Removed a total of 0 dead cases.
yosys> proc_prune
5.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
Removed 1 redundant assignment.
Promoted 0 assignments to connections.
yosys> proc_init
5.4. Executing PROC_INIT pass (extract init attributes).
yosys> proc_arst
5.5. Executing PROC_ARST pass (detect async resets in processes).
yosys> proc_rom
5.6. Executing PROC_ROM pass (convert switches to ROMs).
Converted 0 switches.
<suppressed ~2 debug messages>
yosys> proc_mux
5.7. Executing PROC_MUX pass (convert decision trees to multiplexers).
Creating decoders for process `\control.$proc$example.v:43$1'.
1/2: $0\addr[7:0]
2/2: $0\state[1:0]
yosys> proc_dlatch
5.8. Executing PROC_DLATCH pass (convert process syncs to latches).
yosys> proc_dff
5.9. Executing PROC_DFF pass (convert process syncs to FFs).
Creating register for signal `\control.\state' using process `\control.$proc$example.v:43$1'.
created $dff cell `$procdff$12' with positive edge clock.
Creating register for signal `\control.\addr' using process `\control.$proc$example.v:43$1'.
created $dff cell `$procdff$13' with positive edge clock.
yosys> proc_memwr
5.10. Executing PROC_MEMWR pass (convert process memory writes to cells).
yosys> proc_clean
5.11. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Found and cleaned up 2 empty switches in `\control.$proc$example.v:43$1'.
Removing empty process `control.$proc$example.v:43$1'.
Cleaned up 2 empty switches.
yosys> opt_expr -keepdc
5.12. Executing OPT_EXPR pass (perform const folding).
Optimizing module control.
yosys> show -notitle -format dot -prefix control_proc
6. Generating Graphviz representation of design.
Writing dot description to `control_proc.dot'.
Dumping module control to page 1.
yosys> design -reset
yosys> read_verilog example.v
7. Executing Verilog-2005 frontend: example.v
Parsing Verilog input from `example.v' to AST representation.
Generating RTLIL representation for module `\example'.
Generating RTLIL representation for module `\control'.
Generating RTLIL representation for module `\data'.
Successfully finished Verilog frontend.
yosys> hierarchy -check -top example
8. Executing HIERARCHY pass (managing design hierarchy).
8.1. Analyzing design hierarchy..
Top module: \example
Used module: \data
Used module: \control
8.2. Analyzing design hierarchy..
Top module: \example
Used module: \data
Used module: \control
Removed 0 unused modules.
yosys> show -notitle -format dot -prefix example_hier example
9. Generating Graphviz representation of design.
Writing dot description to `example_hier.dot'.
Dumping module example to page 1.
End of script. Logfile hash: b45465606c, CPU: user 0.01s system 0.00s, MEM: 11.86 MB peak
Yosys 0.35+39 (git sha1 0cd4a10c8, clang 10.0.0-4ubuntu1 -fPIC -Os)
Time spent: 37% 4x read_verilog (0 sec), 23% 3x show (0 sec), ...

View File

@ -0,0 +1,76 @@
module example (
input clk,
input rst,
input inc,
input [7:0] a,
input [7:0] b,
output [15:0] c
);
wire [1:0] state;
wire [7:0] addr;
control ctrl (
.clk(clk),
.rst(rst),
.inc(inc),
.addr_o(addr),
.state_o(state)
);
data dat (
.clk(clk),
.addr_i(addr),
.state_i(state),
.a(a),
.b(b),
.c(c)
);
endmodule
module control (
input clk,
input rst,
input inc,
output [7:0] addr_o,
output [1:0] state_o
);
reg [1:0] state;
reg [7:0] addr;
always @(posedge clk) begin
if (rst) begin
state <= 2'b00;
addr <= 0;
end else begin
if (inc) state <= state + 1'b1;
addr <= addr + 1'b1;
end
end
endmodule //control
module data (
input clk,
input [7:0] addr_i,
input [1:0] state_i,
input [7:0] a,
input [7:0] b,
output reg [15:0] c
);
reg [15:0] mem[255:0];
always @(posedge clk) begin
case (state_i)
2'b00: mem[addr_i] <= a*b;
2'b01: mem[addr_i] <= a+b;
2'b10: mem[addr_i] <= a-b;
2'b11: mem[addr_i] <= addr_i;
endcase
c <= mem[addr_i];
end
endmodule //data

View File

@ -0,0 +1,17 @@
# turn command echoes on to use the log output as a console session
echo on
# ========================================================
read_verilog -defer example.v
hierarchy -top control
show -notitle -format dot -prefix control_hier
# ========================================================
proc
show -notitle -format dot -prefix control_proc
# ========================================================
design -reset
read_verilog example.v
hierarchy -check -top example
show -notitle -format dot -prefix example_hier example

View File

@ -13,33 +13,30 @@ used.
.. seealso:: Advanced usage docs for
:doc:`/using_yosys/synthesis/synth`
A simple counter
~~~~~~~~~~~~~~~~
Demo design
~~~~~~~~~~~
.. role:: yoscrypt(code)
:language: yoscrypt
.. TODO:: replace counter.v with a (slightly) more complex design
which includes hard blocks and maybe an FSM
First, let's quickly look at the design we'll be synthesizing:
.. literalinclude:: /code_examples/intro/counter.v
:language: Verilog
:caption: ``docs/source/code_examples/intro/counter.v``
:linenos:
.. todo:: reconsider including the whole (~77 line) design like this
This is a simple counter with reset and enable. If the reset signal, ``rst``,
is high then the counter will reset to 0. Otherwise, if the enable signal,
``en``, is high then the ``count`` register will increment by 1 each rising edge
of the clock, ``clk``.
.. literalinclude:: /code_examples/example_synth/example.v
:language: Verilog
:linenos:
:caption: ``example.v``
:name: example-v
.. todo:: example.v description
Loading the design
~~~~~~~~~~~~~~~~~~
Let's load the design into Yosys. From the command line, we can call ``yosys
counter.v``. This will open an interactive Yosys shell session and immediately
parse the code from ``counter.v`` and convert it into an Abstract Syntax Tree
example.v``. This will open an interactive Yosys shell session and immediately
parse the code from ``example.v`` and convert it into an Abstract Syntax Tree
(AST). If you are interested in how this happens, there is more information in
the document, :doc:`/yosys_internals/flow/verilog_frontend`. For now, suffice
it to say that we do this to simplify further processing of the design. You
@ -47,13 +44,15 @@ should see something like the following:
.. code:: console
$ yosys counter.v
$ yosys example.v
-- Parsing `counter.v' using frontend ` -vlog2k' --
-- Parsing `example.v' using frontend ` -vlog2k' --
1. Executing Verilog-2005 frontend: counter.v
Parsing Verilog input from `counter.v' to AST representation.
Storing AST representation for module `$abstract\counter'.
1. Executing Verilog-2005 frontend: example.v
Parsing Verilog input from `example.v' to AST representation.
Storing AST representation for module `$abstract\example'.
Storing AST representation for module `$abstract\control'.
Storing AST representation for module `$abstract\data'.
Successfully finished Verilog frontend.
.. seealso:: Advanced usage docs for
@ -63,9 +62,12 @@ Elaboration
~~~~~~~~~~~
Now that we are in the interactive shell, we can call Yosys commands directly.
Our overall goal is to call :yoscrypt:`synth_ice40 -top counter`, but for now we
Our overall goal is to call :yoscrypt:`synth_ice40 -top example`, but for now we
can run each of the commands individually for a better sense of how each part
contributes to the flow. At the bottom of the :cmd:ref:`help` output for
contributes to the flow. We will also start with just a single module;
``control``.
At the bottom of the :cmd:ref:`help` output for
:cmd:ref:`synth_ice40` is the complete list of commands called by this script.
Let's start with the section labeled ``begin``:
@ -75,6 +77,7 @@ Let's start with the section labeled ``begin``:
:end-before: flatten:
:dedent:
:caption: ``begin`` section
:name: synth_begin
:yoscrypt:`read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v` loads the
iCE40 cell models which allows us to include platform specific IP blocks in our
@ -83,15 +86,20 @@ design. PLLs are a common example of this, where we might need to reference
later. Since our simple design doesn't use any of these IP blocks, we can safely
skip this command.
Let's instead start with run :yoscrypt:`hierarchy -check -top counter`. This
command declares that the top level module is ``counter``, and that we want to
expand it and any other modules it may use. Any other modules which were loaded
are then discarded, preventing the subsequent commands from trying to work on
them. By passing the ``-check`` option there we are also telling the
:cmd:ref:`hierarchy` command that if the design includes any non-blackbox
modules without an implementation it should return an error.
The control module
^^^^^^^^^^^^^^^^^^
.. TODO:: more on why :cmd:ref:`hierarchy` is important
Since we're just getting started, let's instead begin with :yoscrypt:`hierarchy
-top control`. This command declares that the top level module is ``control``,
and everything else can be discarded.
.. literalinclude:: /code_examples/example_synth/example.v
:language: Verilog
:start-at: module control
:end-at: endmodule //control
:lineno-match:
:caption: ``control`` module source
:name: control-v
.. note::
@ -100,51 +108,95 @@ modules without an implementation it should return an error.
.. use doscon for a console-like display that supports the `yosys> [command]` format.
.. code:: doscon
.. literalinclude:: /code_examples/example_synth/example.out
:language: doscon
:start-at: yosys> hierarchy -top control
:end-before: yosys> show
:caption: :yoscrypt:`hierarchy -top control` output
yosys> hierarchy -check -top counter
Our ``control`` circuit now looks like this:
2. Executing HIERARCHY pass (managing design hierarchy).
3. Executing AST frontend in derive mode using pre-parsed AST for module `\counter'.
Generating RTLIL representation for module `\counter'.
3.1. Analyzing design hierarchy..
Top module: \counter
3.2. Analyzing design hierarchy..
Top module: \counter
Removing unused module `$abstract\counter'.
Removed 1 unused modules.
Our circuit now looks like this:
.. figure:: /_images/code_examples/intro/counter_00.*
.. figure:: /_images/code_examples/example_synth/control_hier.*
:class: width-helper
:name: control_hier
``counter`` module after :cmd:ref:`hierarchy`
``control`` module after :cmd:ref:`hierarchy`
Notice that block that says "PROC" in :ref:`counter-hierarchy`? Simple
operations like ``count + 2'd1`` can be extracted from our ``always @`` block in
:ref:`counter-v`. This gives us the ``$add`` cell we see. But control logic
(like the ``if .. else``) and memory elements (like the ``count <='2d0``) are
Notice that block that says "PROC" in :ref:`control_hier`? Simple operations
like ``addr + 1'b1`` can be extracted from our ``always @`` block in
:ref:`control-v`. This gives us the two ``$add`` cells we see. But control
logic (like the ``if .. else``) and memory elements (like the ``addr <= 0``) are
not so straightforward. To handle these, let us now introduce the next command:
:doc:`/cmd/proc`.
:cmd:ref:`proc` is a macro command like :cmd:ref:`synth_ice40`. Rather than
processing our design itself, it instead calls a series of other commands. In
modifying the design directly, it instead calls a series of other commands. In
the case of :cmd:ref:`proc`, these sub-commands work to convert the behavioral
logic of processes into multiplexers and registers. We go into more detail on
:cmd:ref:`proc` later in :doc:`/using_yosys/synthesis/proc`, but for now let's
see what happens when we run it.
logic of processes into multiplexers and registers. Let's see what happens when
we run it.
.. figure:: /_images/code_examples/intro/counter_proc.*
.. figure:: /_images/code_examples/example_synth/control_proc.*
:class: width-helper
``counter`` module after :cmd:ref:`proc`
``control`` module after :cmd:ref:`proc`
The ``if`` statements are now modeled with ``$mux`` cells, and the memory
consists of a ``$dff`` cell.
The ``if`` statements are now modeled with ``$mux`` cells, while the registers
use ``$dff`` cells. 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`.
The full example
^^^^^^^^^^^^^^^^
Let's now go back and check on our full design by using :yoscrypt:`hierarchy
-check -top example`. By passing the ``-check`` option there we are also
telling the :cmd:ref:`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 ``control``. We
could restart our shell session, but instead let's use two new commands:
- :doc:`/cmd/design`, and
- :doc:`/cmd/read_verilog`.
.. literalinclude:: /code_examples/example_synth/example.out
:language: doscon
:start-at: design -reset
:end-before: yosys> show
:caption: reloading ``example.v`` and running :yoscrypt:`hierarchy -check -top example`
Notice how this time we didn't see any of those `$abstract` modules? That's
because when we ran ``yosys example.v``, the first command Yosys called was
:yoscrypt:`read_verilog -defer example.v`. The ``-defer`` option there tells
:cmd:ref:`read_verilog` only read the abstract syntax tree and defer actual
compilation to a later :cmd:ref:`hierarchy` command. This is useful in cases
where the default parameters of modules yield invalid or not synthesizable code,
which is why Yosys does this 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``.
.. note::
The number before a command's output increments with each command run. Don't
worry if your numbers don't match ours! The output you are seeing comes from
the same script that was used to generate the images in this document,
included in the source as ``example.ys``. There are extra commands being run
which you don't see, but feel free to try them yourself, or play around with
different commands. You can always start over with a clean slate by calling
``exit`` or hitting ``ctrl+c`` (i.e. SIGINT) and re-launching the Yosys
interactive terminal.
.. figure:: /_images/code_examples/example_synth/example_hier.*
:class: width-helper
:name: example_hier
``example`` module after :cmd:ref:`hierarchy`
We can also run :cmd:ref:`proc` now, although we won't actually see any change
in this top view.
.. TODO:: more on why :cmd:ref:`hierarchy` is important
.. seealso:: Advanced usage docs for
:doc:`/using_yosys/synthesis/proc`
@ -153,26 +205,27 @@ Flattening
~~~~~~~~~~
At this stage of a synthesis flow there are a few other commands we could run.
First off is :cmd:ref:`flatten`. If we had any modules within our ``counter``,
this would replace them with their implementation. Flattening the design like
this can allow for optimizations between modules which would otherwise be
missed.
Depending on the target architecture, we might also run 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.
In :cmd:ref:`synth_ice40` we get these:
.. literalinclude:: /cmd/synth_ice40.rst
:language: yoscrypt
:start-after: flatten:
:end-before: coarse:
:dedent:
:name: flatten
:name: synth_flatten
:caption: ``flatten`` section
The iCE40 flow puts these commands into thier own :ref:`flatten`,
while some synthesis scripts will instead include them in the next section.
First off is :cmd:ref:`synth_flatten`. Flattening the design like this can
allow for optimizations between modules which would otherwise be missed. We
will skip this command for now because it makes the design schematic quite
large. If you would like to see for yourself, you can do so with
:doc:`/cmd/show`. Note that the :cmd:ref:`show` command only works with a
single module, so you may need to call it with :yoscrypt:`show example`.
Depending on the target architecture, we 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.
The coarse-grain representation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -195,6 +248,13 @@ In the iCE40 flow we get all the following commands:
:end-before: map_ram:
:dedent:
:caption: ``coarse`` section
:name: synth_coarse
.. note::
While the iCE40 flow had a :ref:`synth_flatten` and put :cmd:ref:`proc` in
the :ref:`synth_begin`, some synthesis scripts will instead include these in
the :ref:`synth_coarse` section.
.. TODO:: talk more about DSPs (and their associated commands)