Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QuickStart] Yosys/Parmys Update #2776

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified doc/src/quickstart/blink_implementation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
273 changes: 154 additions & 119 deletions doc/src/quickstart/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
VTR Quick Start
###############

This is a quick introduction to VTR which covers how to run VTR and some of its associated tools (:ref:`VPR`, :ref:`odin_ii`, :ref:`ABC`).
This is a quick introduction to VTR which covers how to run VTR and some of its associated tools (:ref:`VPR`, :ref:`Parmys`, :ref:`ABC`).

Setting Up VTR
==============
Expand Down Expand Up @@ -48,14 +48,6 @@ On most unix-like systems you can run:

> make

The default front-end for VTR is :ref:`Parmys<parmys>`, but you can build with ODIN II instead using the command below. This is required to run :ref:`Synthesizing with ODIN II<synthesizing_with_odin_ii>`.

.. code-block:: bash

> make CMAKE_PARAMS="-DWITH_ODIN=on"

from the VTR root directory (hereafter referred to as :term:`$VTR_ROOT`) to build VTR.

.. note::

In the VTR documentation lines starting with ``>`` (like ``> make`` above), indicate a command (i.e. ``make``) to run from your terminal.
Expand Down Expand Up @@ -198,7 +190,7 @@ As an exercise try the following:

.. figure:: tseng_blk1.png

Input (blue)/output (red) nets of block ``n_n3199`` (highlighted green).
Input (blue)/output (red) nets of block ``n_n3226`` (highlighted green).

.. note::
If you do not provide :option:`--analysis <vpr --analysis>`, VPR will re-implement the circuit from scratch.
Expand Down Expand Up @@ -239,124 +231,38 @@ Let's start by making a fresh directory for us to work in:

Next we need to run the three main sets of tools:

* :ref:`odin_ii` performs 'synthesis' which converts our behavioural Verilog (``.v`` file) into a circuit netlist (``.blif`` file) consisting of logic equations and FPGA architecture primitives (Flip-Flops, adders etc.),
* :ref:`Parmys` performs 'synthesis' which converts our behavioural Verilog (``.v`` file) into a circuit netlist (``.blif`` file) consisting of logic equations and FPGA architecture primitives (Flip-Flops, adders etc.),
* :ref:`ABC` performs 'logic optimization' which simplifies the circuit logic, and 'technology mapping' which converts logic equations into the Look-Up-Tables (LUTs) available on an FPGA, and
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved
* :ref:`VPR` which performs packing, placement and routing of the circuit to implement it on the targeted FPGA architecture.

.. _synthesizing_with_odin_ii:
Synthesizing with ODIN II
.. _synthesizing_with_parmys:
Synthesizing with Parmys
~~~~~~~~~~~~~~~~~~~~~~~~~

First we'll run ODIN II on our Verilog file to synthesize it into a circuit netlist, providing the options:
To synthesize our Verilog file into a circuit netlist, we will utilize the `run_vtr_flow.py` script, which streamlines the process. This command synthesizes the provided Verilog file (`blink.v`) while targeting the specified FPGA architecture (`EArch.xml`).

* ``-a $VTR_ROOT/vtr_flow/arch/timing/EArch.xml`` which specifies what FPGA architecture we are targeting,
* ``-V $VTR_ROOT/doc/src/quickstart/blink.v`` which specifies the verilog file we want to synthesize, and
* ``-o blink.odin.blif`` which specifies the name of the generated ``.blif`` circuit netlist.

The resulting command is:
The command is as follows:

.. code-block:: bash

> $VTR_ROOT/odin_ii/odin_ii \
-a $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \
-V $VTR_ROOT/doc/src/quickstart/blink.v \
-o blink.odin.blif

which when run should end with something like::
> $VTR_ROOT/vtr_flow/scripts/run_vtr_flow.py \
$VTR_ROOT/doc/src/quickstart/blink.v \
$VTR_ROOT/vtr_flow/arch/timing/EArch.xml \
-start parmys -end parmys

Total time: 14.7ms
Odin ran with exit status: 0
Odin II took 0.01 seconds (max_rss 5.1 MiB)
When executed, the output should indicate successful synthesis, similar to:

where ``Odin ran with exit status: 0`` indicates Odin successfully synthesized our verilog.
EArch/blink OK (took 0.16 seconds, overall memory peak 20.00 MiB consumed by parmys run)

We can now take a look at the circuit which ODIN produced (``blink.odin.blif``).
The file is long and likely harder to follow than our code in ``blink.v``; however it implements the same functionality.
Some interesting highlights are shown below:
This output confirms that the synthesis was successful and provides information on the duration and memory usage during the process.

.. literalinclude:: blink.odin.blif
:lines: 14,40
:caption: Instantiations of rising-edge triggered Latches (i.e. Flip-Flops) in ``blink.odin.blif`` (implements part of ``r_counter`` in blink.v)

.. literalinclude:: blink.odin.blif
:lines: 17-19,21-22
:caption: Adder primitive instantiations in ``blink.odin.blif``, used to perform addition (implements part of the ``+`` operator in blink.v)

.. literalinclude:: blink.odin.blif
:lines: 45-50
:caption: Logic equation (.names truth-table) in ``blink.odin.blif``, implementing logical OR (implements part of the ``<`` operator in blink.v)
We can now take a look at the circuit which Parmys produced (``blink.parmys.blif``).

.. seealso:: For more information on the BLIF file format see :ref:`blif_format`.

Optimizing and Technology Mapping with ABC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Next, we'll optimize and technology map our circuit using ABC, providing the option:

* ``-c <script>``, where ``<script>`` is a set of commands telling ABC how to synthesize our circuit.

We'll use the following, simple ABC commands::

read blink.odin.blif; #Read the circuit synthesized by ODIN
if -K 6; #Technology map to 6 input LUTs (6-LUTs)
write_hie blink.odin.blif blink.abc_no_clock.blif #Write new circuit to blink.abc_no_clock.blif

.. note:: Usually you should use a more complicated script (such as that used by :ref:`run_vtr_flow`) to ensure ABC optitmizes your circuit well.

The corresponding command to run is:

.. code-block:: bash

> $VTR_ROOT/abc/abc \
-c 'read blink.odin.blif; if -K 6; write_hie blink.odin.blif blink.abc_no_clock.blif'

When run, ABC's output should look similar to::

ABC command line: "read blink.odin.blif; if -K 6; write_hie blink.odin.blif blink.abc_no_clock.blif".

Hierarchy reader converted 6 instances of blackboxes.
The network was strashed and balanced before FPGA mapping.
Hierarchy writer reintroduced 6 instances of blackboxes.

If we now inspect the produced BLIF file (``blink.abc_no_clock.blif``) we see that ABC was able to significantly simplify and optimize the circuit's logic (compared to ``blink.odin.blif``):

.. literalinclude:: blink.abc_no_clock.blif
:linenos:
:emphasize-lines: 6-10,13-18,21-38
:caption: blink.abc_no_clock.blif

ABC has kept the ``.latch`` and ``.subckt adder`` primitives, but has significantly simplified the other logic (``.names``).


However, there is an issue with the above BLIF produced by ABC: the latches (rising edge Flip-Flops) do not have any clocks or edge sensitivity specified, which is information required by VPR.

Re-inserting clocks
^^^^^^^^^^^^^^^^^^^
We will restore the clock information by running a script which will transfer that information from the original ODIN BLIF file (writing it to the new file ``blink.pre-vpr.blif``):

.. code-block:: bash

> $VTR_ROOT/vtr_flow/scripts/restore_multiclock_latch.pl \
blink.odin.blif \
blink.abc_no_clock.blif \
blink.pre-vpr.blif

If we inspect ``blink.pre-vpr.blif`` we now see that the clock (``blink^clk``) has been restored to the Flip-Flops:

.. code-block:: bash

> grep 'latch' blink.pre-vpr.blif

.latch n19 blink^r_counter~0_FF re blink^clk 3
.latch n24 blink^r_counter~4_FF re blink^clk 3
.latch n29 blink^r_counter~3_FF re blink^clk 3
.latch n34 blink^r_counter~2_FF re blink^clk 3
.latch n39 blink^r_counter~1_FF re blink^clk 3


Implementing the circuit with VPR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now that we have the optimized and technology mapped netlist (``blink.pre-vpr.blif``), we can invoke VPR to implement it onto the ``EArch`` FPGA architecture (in the same way we did with the ``tseng`` design earlier).
Now that we have the optimized and technology mapped netlist (``blink.parmys.blif``), we can invoke VPR to implement it onto the ``EArch`` FPGA architecture (in the same way we did with the ``tseng`` design earlier).
However, since our BLIF file doesn't match the design name we explicitly specify:

* ``blink`` as the circuit name, and
Expand All @@ -370,7 +276,7 @@ The resulting command is:

> $VTR_ROOT/vpr/vpr \
$VTR_ROOT/vtr_flow/arch/timing/EArch.xml \
blink --circuit_file blink.pre-vpr.blif \
~/vtr_work/quickstart/blink_manual/temp/blink.parmys.blif \
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved
--route_chan_width 100

and after VPR finishes we should see the resulting implementation files:
Expand All @@ -379,15 +285,15 @@ and after VPR finishes we should see the resulting implementation files:

> ls *.net *.place *.route

blink.net blink.place blink.route
blink.parmys.net blink.parmys.place blink.parmys.route

We can then view the implementation as usual by appending ``--analysis --disp on`` to the command:

.. code-block:: bash

> $VTR_ROOT/vpr/vpr \
$VTR_ROOT/vtr_flow/arch/timing/EArch.xml \
blink --circuit_file blink.pre-vpr.blif \
~/vtr_work/quickstart/blink_manual/temp/blink.parmys.blif \
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved
--route_chan_width 100 \
--analysis --disp on

Expand Down Expand Up @@ -440,16 +346,16 @@ which should produce output similar to::

EArch/blink OK (took 0.26 seconds)

There are also multiple log files (including for ABC, ODIN and VPR), which by convention the script names with the ``.out`` suffix:
There are also multiple log files (including for ABC, Parmys and VPR), which by convention the script names with the ``.out`` suffix:
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: bash

> ls *.out

0_blackboxing_latch.out odin.out report_clocks.abc.out vanilla_restore_clocks.out
0_blackboxing_latch.out parmys.out report_clocks.abc.out vanilla_restore_clocks.out
abc0.out report_clk.out restore_latch0.out vpr.out

With the main log files of interest including the ODIN log file (``odin.out``), log files produced by ABC (e.g. ``abc0.out``), and the VPR log file (``vpr.out``).
With the main log files of interest including the Parmys log file (``parmys.out``), log files produced by ABC (e.g. ``abc0.out``), and the VPR log file (``vpr.out``).

.. note::

Expand All @@ -462,10 +368,10 @@ You will also see there are several BLIF files produced:

> ls *.blif

0_blink.abc.blif 0_blink.raw.abc.blif blink.odin.blif
0_blink.odin.blif blink.abc.blif blink.pre-vpr.blif
0_blink.abc.blif 0_blink.raw.abc.blif blink.parmys.blif
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved
0_blink.parmys.blif blink.abc.blif blink.pre-vpr.blif

With the main files of interest being ``blink.odin.blif`` (netlist produced by ODIN), ``blink.abc.blif`` (final netlist produced by ABC after clock restoration), ``blink.pre-vpr.blif`` netlist used by VPR (usually identical to ``blink.abc.blif``).
With the main files of interest being ``blink.parmys.blif`` (netlist produced by Parmys), ``blink.abc.blif`` (final netlist produced by ABC after clock restoration), ``blink.pre-vpr.blif`` netlist used by VPR (usually identical to ``blink.abc.blif``).

Like before, we can also see the implementation files generated by VPR:

Expand All @@ -485,6 +391,135 @@ which we can visualize with:
--route_chan_width 100 \
--analysis --disp on

Manually Running VTR with ODIN II
----------------------------------
VTR includes a second synthesis tool, ODIN II. Below we explain how to run this alternative synthesis flow.
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved

Let's start by making a new directory for us to work in:
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: bash

> mkdir -p ~/vtr_work/quickstart/blink_manual
> cd ~/vtr_work/quickstart/blink_manual

To synthesize your Verilog design with ODIN II, you need to build VTR with the following command:

.. code-block:: bash

> make CMAKE_PARAMS="-DWITH_ODIN=on"
ZohairZaidi marked this conversation as resolved.
Show resolved Hide resolved

This step enables ODIN II support in the VTR build process, which is essential for the subsequent synthesis operations.


Next, run ODIN II on your Verilog file to synthesize it into a circuit netlist. Use the command below, specifying the required options:

* ``-a $VTR_ROOT/vtr_flow/arch/timing/EArch.xml`` which specifies what FPGA architecture we are targeting,
* ``-V $VTR_ROOT/doc/src/quickstart/blink.v`` which specifies the verilog file we want to synthesize, and
* ``-o blink.odin.blif`` which specifies the name of the generated ``.blif`` circuit netlist.

The resulting command is:

.. code-block:: bash

> $VTR_ROOT/odin_ii/odin_ii \
-a $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \
-V $VTR_ROOT/doc/src/quickstart/blink.v \
-o blink.odin.blif

After running the command, you should see an output similar to the following::

Total time: 14.7ms
Odin ran with exit status: 0
Odin II took 0.01 seconds (max_rss 5.1 MiB)

where ``Odin ran with exit status: 0`` indicates Odin successfully synthesized our verilog.

We can now take a look at the circuit which ODIN produced (``blink.odin.blif``).
The file is long and likely harder to follow than our code in ``blink.v``; however it implements the same functionality.
Some interesting highlights are shown below:

.. literalinclude:: blink.odin.blif
:lines: 14,40
:caption: Instantiations of rising-edge triggered Latches (i.e. Flip-Flops) in ``blink.odin.blif`` (implements part of ``r_counter`` in blink.v)

.. literalinclude:: blink.odin.blif
:lines: 17-19,21-22
:caption: Adder primitive instantiations in ``blink.odin.blif``, used to perform addition (implements part of the ``+`` operator in blink.v)

.. literalinclude:: blink.odin.blif
:lines: 45-50
:caption: Logic equation (.names truth-table) in ``blink.odin.blif``, implementing logical OR (implements part of the ``<`` operator in blink.v)

.. seealso:: For more information on the BLIF file format see :ref:`blif_format`.

Optimizing and Technology Mapping with ABC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Next, we'll optimize and technology map our circuit using ABC, providing the option:

* ``-c <script>``, where ``<script>`` is a set of commands telling ABC how to synthesize our circuit.

We'll use the following, simple ABC commands::

read blink.odin.blif; #Read the circuit synthesized by ODIN
if -K 6; #Technology map to 6 input LUTs (6-LUTs)
write_hie blink.odin.blif blink.abc_no_clock.blif #Write new circuit to blink.abc_no_clock.blif

.. note:: Usually you should use a more complicated script (such as that used by :ref:`run_vtr_flow`) to ensure ABC optitmizes your circuit well.

The corresponding command to run is:

.. code-block:: bash

> $VTR_ROOT/abc/abc \
-c 'read blink.odin.blif; if -K 6; write_hie blink.odin.blif blink.abc_no_clock.blif'

When run, ABC's output should look similar to::

ABC command line: "read blink.odin.blif; if -K 6; write_hie blink.odin.blif blink.abc_no_clock.blif".

Hierarchy reader converted 6 instances of blackboxes.
The network was strashed and balanced before FPGA mapping.
Hierarchy writer reintroduced 6 instances of blackboxes.

If we now inspect the produced BLIF file (``blink.abc_no_clock.blif``) we see that ABC was able to significantly simplify and optimize the circuit's logic (compared to ``blink.odin.blif``):

.. literalinclude:: blink.abc_no_clock.blif
:linenos:
:emphasize-lines: 6-10,13-18,21-38
:caption: blink.abc_no_clock.blif

ABC has kept the ``.latch`` and ``.subckt adder`` primitives, but has significantly simplified the other logic (``.names``).


However, there is an issue with the above BLIF produced by ABC: the latches (rising edge Flip-Flops) do not have any clocks or edge sensitivity specified, which is information required by VPR.

Re-inserting clocks
^^^^^^^^^^^^^^^^^^^
We will restore the clock information by running a script which will transfer that information from the original ODIN BLIF file (writing it to the new file ``blink.pre-vpr.blif``):

.. code-block:: bash

> $VTR_ROOT/vtr_flow/scripts/restore_multiclock_latch.pl \
blink.odin.blif \
blink.abc_no_clock.blif \
blink.pre-vpr.blif

If we inspect ``blink.pre-vpr.blif`` we now see that the clock (``blink^clk``) has been restored to the Flip-Flops:

.. code-block:: bash

> grep 'latch' blink.pre-vpr.blif

.latch n19 blink^r_counter~0_FF re blink^clk 3
.latch n24 blink^r_counter~4_FF re blink^clk 3
.latch n29 blink^r_counter~3_FF re blink^clk 3
.latch n34 blink^r_counter~2_FF re blink^clk 3
.latch n39 blink^r_counter~1_FF re blink^clk 3


After optimizing the netlist, we can proceed to follow the steps outlined in the section titled :ref:'Implementing the circuit with VPR' using the genrated `blink.pre-vpr.blif` instead of `blink.parmys.blif`.

Next Steps
==========
Now that you've finished the VTR quickstart, you're ready to start experimenting and using VTR.
Expand Down
Binary file modified doc/src/quickstart/tseng_blk1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/src/quickstart/tseng_nets.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.