diff --git a/doc/src/quickstart/blink_implementation.png b/doc/src/quickstart/blink_implementation.png index 8acb5085f68..4b939c03cfb 100644 Binary files a/doc/src/quickstart/blink_implementation.png and b/doc/src/quickstart/blink_implementation.png differ diff --git a/doc/src/quickstart/index.rst b/doc/src/quickstart/index.rst index 7ac82662597..0621ae0cd81 100644 --- a/doc/src/quickstart/index.rst +++ b/doc/src/quickstart/index.rst @@ -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 ============== @@ -48,14 +48,6 @@ On most unix-like systems you can run: > make -The default front-end for VTR is :ref:`Parmys`, but you can build with ODIN II instead using the command below. This is required to run :ref:`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. @@ -73,11 +65,106 @@ from the VTR root directory (hereafter referred to as :term:`$VTR_ROOT`) to buil For more details on building VTR on various operating systems/platforms see :doc:`Building VTR`. +Running the VTR Flow +---------------------------------- +Running each stage of the flow manually is time consuming (and potentially error prone). +For convenience, VTR provides a script (:ref:`run_vtr_flow`) which automates this process. -Running VPR -=========== +First, make sure you have activated the Python virtual environment created at the beginning of this tutorial: -Let's now try taking a simple pre-synthesized circuit (consisting of LUTs and Flip-Flops) and use the VPR tool to implement it on a specific FPGA architecture. +.. code-block:: bash + + > source $VTR_ROOT/.venv/bin/activate + +Define the working directory where the flow will be executed. For convenience, use an environment variable: + +.. code-block:: bash + + export VTR_FLOW_DIR=~/vtr_work/quickstart/blink_run_flow + +Alternatively, you can manually replace ``$VTR_FLOW_DIR`` with your preferred directory path in the commands below. + +Create the working directory and navigate into it: + +.. code-block:: bash + + > mkdir -p $VTR_FLOW_DIR + > cd $VTR_FLOW_DIR + +Now lets run the script (``$VTR_ROOT/vtr_flow/scripts/run_vtr_flow.py``) passing in: + +* The circuit verilog file (``$VTR_ROOT/doc/src/quickstart/blink.v``) +* The FPGA architecture file (``$VTR_ROOT/vtr_flow/arch/timing/EArch.xml``) + +and also specifying the options: + +* ``--route_chan_width 100`` a fixed FPGA routing architecture channel width. + + +The resulting command is: + +.. code-block:: bash + + > $VTR_ROOT/vtr_flow/scripts/run_vtr_flow.py \ + $VTR_ROOT/doc/src/quickstart/blink.v \ + $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \ + --route_chan_width 100 + +.. note:: Options unrecognized by run_vtr_flow (like ``--route_chan_width``) are passed on to VPR. + +which should produce output similar to:: + + EArch/blink OK (took 0.26 seconds, overall memory peak 63.71 MiB consumed by vpr run) + +There are also multiple log files (including for ABC, Parmys and VPR), which by convention the script names with the ``.out`` suffix: + +.. code-block:: bash + + > ls $VTR_FLOW_DIR/temp/*.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 Parmys log file (``parmys.out``), log files produced by ABC (e.g. ``abc0.out``), and the VPR log file (``vpr.out``). + +.. note:: + + ABC may be invoked multiple times if a circuit has multiple clock domains, producing multiple log files (``abc0.out``, ``abc1.out``, ...) + + +You will also see there are several BLIF files produced: + +.. code-block:: bash + + > ls $VTR_FLOW_DIR/temp/*.blif + + 0_blink.abc.blif 0_blink.raw.abc.blif blink.parmys.blif + 0_blink.parmys.blif blink.abc.blif blink.pre-vpr.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: + +.. code-block:: bash + + > ls $VTR_FLOW_DIR/temp/*.net $VTR_FLOW_DIR/temp/*.place $VTR_FLOW_DIR/temp/*.route + + blink.net blink.place blink.route + +which we can visualize with: + +.. code-block:: bash + + > $VTR_ROOT/vpr/vpr \ + $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \ + blink --circuit_file $VTR_FLOW_DIR/temp/blink.pre-vpr.blif \ + --route_chan_width 100 \ + --analysis --disp on + + +Running VPR Manually +=========== +Sometimes you may wish to run only the vpr (placement, routing and timing analysis) parts of the flow rather than the full VTR flow (which includes synthesis). To show how to do this, let's now try taking a simple pre-synthesized circuit (consisting of LUTs and Flip-Flops) and use the VPR tool to implement it on a specific FPGA architecture. Running VPR on a Pre-Synthesized Circuit ---------------------------------------- @@ -198,7 +285,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 will re-implement the circuit from scratch. @@ -206,8 +293,8 @@ As an exercise try the following: By default ``--disp on`` stops at key stages to allow you to view and explore the implementation. You will need to press the ``Proceed`` button in the GUI to allow VPR to continue to the next stage. -Running the VTR Flow -==================== +Manually Running the VTR Flow +----------------------------- In the previous section we have implemented a pre-synthesized circuit onto a pre-existing FPGA architecture using VPR, and visualized the result. We now turn to how we can implement *our own circuit* on a pre-existing FPGA architecture. @@ -228,63 +315,60 @@ We will use the following simple example circuit, which causes its output to tog This Verilog creates a sequential 5-bit register (``r_counter``) which increments every clock cycle. If the count is below ``16`` it drives the output (``o_led``) high, otherwise it drives it low. -Manually Running the VTR Flow ------------------------------ -Let's start by making a fresh directory for us to work in: + +With the circuit defined, we are now ready to move forward with implementing it on an FPGA. To begin the process, we’ll set up a fresh working directory where we can manage our files and run the necessary VTR flow steps. Let’s get started by creating that directory and organizing our workspace: + +- ``$WRK_DIR`` will serve as our working directory for this example. + +To set this variable, define it in your shell: .. code-block:: bash - > mkdir -p ~/vtr_work/quickstart/blink_manual - > cd ~/vtr_work/quickstart/blink_manual + export WRK_DIR=~/vtr_work/quickstart/blink_manual -Next we need to run the three main sets of tools: +Alternatively, manually replace ``$WRK_DIR`` in the example commands with your path. -* :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:`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 -* :ref:`VPR` which performs packing, placement and routing of the circuit to implement it on the targeted FPGA architecture. +Now, create and navigate to the working directory: -.. _synthesizing_with_odin_ii: -Synthesizing with ODIN II -~~~~~~~~~~~~~~~~~~~~~~~~~ +.. code-block:: bash -First we'll run ODIN II on our Verilog file to synthesize it into a circuit netlist, providing the options: + > mkdir -p $WRK_DIR + > cd $WRK_DIR - * ``-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. +Next, we need to run the three main sets of tools, depending on the method of synthesis you choose: -The resulting command is: +1. **Synthesis Options**: + + - **Parmys**: Parmys is the default synthesis tool in the VTR flow. -.. code-block:: bash + - **Odin II**: Odin II is the alternative synthesis tool supported by VTR. - > $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 +2. **Finally, regardless of the synthesis method**, run :ref:`ABC` to perform logic optimization and technology mapping, and then run :ref:`VPR` to handle packing, placement, and routing, which completes the implementation on the FPGA architecture. -which when run should end with something like:: +.. _synthesizing_with_parmys: +Synthesizing with Parmys +~~~~~~~~~~~~~~~~~~~~~~~~~ - Total time: 14.7ms - Odin ran with exit status: 0 - Odin II took 0.01 seconds (max_rss 5.1 MiB) +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`). -where ``Odin ran with exit status: 0`` indicates Odin successfully synthesized our verilog. +The command is as follows: -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: +.. code-block:: bash -.. 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) + > $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 -.. 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) +When executed, the output should indicate successful synthesis, similar to: -.. 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) +.. code-block:: bash + + EArch/blink OK (took 0.16 seconds, overall memory peak 20.00 MiB consumed by parmys run) + +This output confirms that the synthesis was successful and provides information on the duration and memory usage during the process. + +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`. @@ -297,9 +381,9 @@ Next, we'll optimize and technology map our circuit using ABC, providing the opt We'll use the following, simple ABC commands:: - read blink.odin.blif; #Read the circuit synthesized by ODIN + read blink.parmys.blif; #Read the circuit synthesized by parmys 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 + write_hie blink.parmys.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. @@ -308,17 +392,17 @@ 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' + -c "read $WRK_DIR/temp/blink.parmys.blif; if -K 6; write_hie $WRK_DIR/temp/blink.parmys.blif $WRK_DIR/temp/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". + ABC command line: "read blink.parmys.blif; if -K 6; write_hie blink.parmys.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``): +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.parmys.blif``): .. literalinclude:: blink.abc_no_clock.blif :linenos: @@ -327,19 +411,18 @@ If we now inspect the produced BLIF file (``blink.abc_no_clock.blif``) we see th 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``): +We will restore the clock information by running a script which will transfer that information from the original parmys 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 + $WRK_DIR/temp/blink.parmys.blif \ + $WRK_DIR/temp/blink.abc_no_clock.blif \ + $WRK_DIR/temp/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: @@ -353,7 +436,6 @@ If we inspect ``blink.pre-vpr.blif`` we now see that the clock (``blink^clk``) h .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). @@ -370,14 +452,14 @@ The resulting command is: > $VTR_ROOT/vpr/vpr \ $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \ - blink --circuit_file blink.pre-vpr.blif \ + blink --circuit_file $WRK_DIR/temp/blink.pre-vpr.blif \ --route_chan_width 100 and after VPR finishes we should see the resulting implementation files: .. code-block:: bash - > ls *.net *.place *.route + > ls $WRK_DIR/*.net $WRK_DIR/*.place $WRK_DIR/*.route blink.net blink.place blink.route @@ -387,7 +469,7 @@ We can then view the implementation as usual by appending ``--analysis --disp on > $VTR_ROOT/vpr/vpr \ $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \ - blink --circuit_file blink.pre-vpr.blif \ + blink --circuit_file $WRK_DIR/temp/blink.pre-vpr.blif \ --route_chan_width 100 \ --analysis --disp on @@ -395,95 +477,71 @@ We can then view the implementation as usual by appending ``--analysis --disp on ``blink.v`` circuit implementation on the ``EArch`` FPGA architecture as viewed in the VPR GUI -Automatically Running the VTR Flow +Manually Running VTR with ODIN II ---------------------------------- -Running each stage of the flow manually is time consuming (and potentially error prone). -For convenience, VTR provides a script (:ref:`run_vtr_flow`) which automates this process. +VTR includes a second synthesis tool, ODIN II. Below we explain how to run this alternative synthesis flow. -First, make sure you have activated the Python virtual environment created at the beginning of this tutorial: +To synthesize your Verilog design with ODIN II, you need to build VTR with the following command: .. code-block:: bash - > source $VTR_ROOT/.venv/bin/activate - -Next, make a new directory to work in named ``blink_run_flow``: - -.. code-block:: bash - - > mkdir -p ~/vtr_work/quickstart/blink_run_flow - > cd ~/vtr_work/quickstart/blink_run_flow - -Now lets run the script (``$VTR_ROOT/vtr_flow/scripts/run_vtr_flow.py``) passing in: - -* The circuit verilog file (``$VTR_ROOT/doc/src/quickstart/blink.v``) -* The FPGA architecture file (``$VTR_ROOT/vtr_flow/arch/timing/EArch.xml``) - -and also specifying the options: - -* ``-temp_dir .`` to run in the current directory (``.`` on unix-like systems) -* ``--route_chan_width 100`` a fixed FPGA routing architecture channel width. + > cd ~/$VTR_ROOT + > make CMAKE_PARAMS="-DWITH_ODIN=on" +This step enables ODIN II support in the VTR build process, which is essential for the subsequent synthesis operations. -The resulting command is: +Lets make a new directory for us to work in: .. code-block:: bash - > $VTR_ROOT/vtr_flow/scripts/run_vtr_flow.py \ - $VTR_ROOT/doc/src/quickstart/blink.v \ - $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \ - -temp_dir . \ - --route_chan_width 100 - -.. note:: Options unrecognized by run_vtr_flow (like ``--route_chan_width``) are passed on to VPR. + > mkdir -p ~/vtr_work/quickstart/blink_manual + > cd ~/vtr_work/quickstart/blink_manual -which should produce output similar to:: +Next, run ODIN II on your Verilog file to synthesize it into a circuit netlist. Use the command below, specifying the required options: - EArch/blink OK (took 0.26 seconds) + * ``-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. -There are also multiple log files (including for ABC, ODIN and VPR), which by convention the script names with the ``.out`` suffix: +The resulting command is: .. code-block:: bash - > ls *.out - - 0_blackboxing_latch.out odin.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``). - -.. note:: - - ABC may be invoked multiple times if a circuit has multiple clock domains, producing multiple log files (``abc0.out``, ``abc1.out``, ...) - - -You will also see there are several BLIF files produced: + > $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 -.. code-block:: bash +After running the command, you should see an output similar to the following:: - > ls *.blif + Total time: 14.7ms + Odin ran with exit status: 0 + Odin II took 0.01 seconds (max_rss 5.1 MiB) - 0_blink.abc.blif 0_blink.raw.abc.blif blink.odin.blif - 0_blink.odin.blif blink.abc.blif blink.pre-vpr.blif +where ``Odin ran with exit status: 0`` indicates Odin successfully synthesized our verilog. -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``). +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: -Like before, we can also see the implementation files generated by VPR: +.. 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) -.. code-block:: bash +.. 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) - > ls *.net *.place *.route +.. 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) - blink.net blink.place blink.route +.. seealso:: For more information on the BLIF file format see :ref:`blif_format`. -which we can visualize with: -.. code-block:: bash +After generating ``blink.odin.blif``, we can proceed to optimize the netlist and implement it on the FPGA. Follow the steps outlined in the section titled :ref:`Optimizing and Technology Mapping with ABC`, using the generated ``blink.odin.blif`` as input instead of ``blink.parmys.blif``. - > $VTR_ROOT/vpr/vpr \ - $VTR_ROOT/vtr_flow/arch/timing/EArch.xml \ - blink --circuit_file blink.pre-vpr.blif \ - --route_chan_width 100 \ - --analysis --disp on +Once the netlist is optimized with ABC, continue with the :ref:`Implementing the circuit with VPR` section to pack, place, and route the circuit onto the FPGA architecture. Next Steps ========== diff --git a/doc/src/quickstart/tseng_blk1.png b/doc/src/quickstart/tseng_blk1.png index 20870a5da13..63ab4714b61 100644 Binary files a/doc/src/quickstart/tseng_blk1.png and b/doc/src/quickstart/tseng_blk1.png differ diff --git a/doc/src/quickstart/tseng_nets.png b/doc/src/quickstart/tseng_nets.png index e1608190744..4be86d716d6 100644 Binary files a/doc/src/quickstart/tseng_nets.png and b/doc/src/quickstart/tseng_nets.png differ