Scripting in Yosys
------------------

On the previous page we went through a synthesis script, running each command in
the interactive Yosys shell.  On this page, we will be introducing the script
file format and how you can make your own synthesis scripts.

Yosys script files typically use the :file:`.ys` extension and contain a set of
commands for Yosys to run sequentially.  These commands are the same ones we
were using on the previous page like `read_verilog` and `hierarchy`.

Script parsing
~~~~~~~~~~~~~~

As with the interactive shell, each command consists of the command name, and an
optional whitespace separated list of arguments. Commands are terminated with
the newline character, and anything after a hash sign ``#`` is a comment (i.e.
it is ignored).

It is also possible to terminate commands with a semicolon ``;``.  This is
particularly useful in conjunction with the ``-p <command>`` command line
option, where ``<command>`` can be a string with multiple commands separated by
semicolon. In-line comments can also be made with the colon ``:``, where the end
of the comment is a semicolon ``;`` or a new line.

.. code-block::
   :caption: Using the ``-p`` option

   $ yosys -p 'read_verilog fifo.v; :this is a comment; prep'

.. warning::

   The space after the semicolon is required for correct parsing. ``log a;log
   b;`` for example will display ``a;log b`` instead of ``a`` and ``b`` as might
   be expected.

Another special character that can be used in Yosys scripts is the bang ``!``.
Anything after the bang will be executed as a shell command.  This can only be
terminated with a new line.  Any semicolons, hashes, or other special characters
will be passed to the shell.  If an error code is returned from the shell it
will be raised by Yosys.  `exec` provides a much more flexible way of executing
commands, allowing the output to be logged and more control over when to
generate errors.

.. warning::

   Take care when using the ``yosys -p`` option.  Some shells such as bash will
   perform substitution options inside of a double quoted string, such as ``!``
   for history substitution and ``$`` for variable substitution; single quotes
   should be used instead to pass the string to Yosys without substitution.

The synthesis starter script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. role:: yoscrypt(code)
   :language: yoscrypt

All of the images and console output used in
:doc:`/getting_started/example_synth` were generated by Yosys, using Yosys
script files found in :file:`docs/source/code_examples/fifo`. If you haven't
already, let's take a look at some of those script files now.

.. literalinclude:: /code_examples/fifo/fifo.ys
   :language: yoscrypt
   :lineno-match:
   :start-at: echo on
   :end-before: design -reset
   :caption: A section of :file:`fifo.ys`, generating the images used for :ref:`addr_gen_example`
   :name: fifo-ys

The first command there, :yoscrypt:`echo on`, uses `echo` to enable command
echoes on.  This is how we generated the code listing for
:ref:`hierarchy_output`.  Turning command echoes on prints the ``yosys>
hierarchy -top addr_gen`` line, making the output look the same as if it were an
interactive terminal.  :yoscrypt:`hierarchy -top addr_gen` is of course the
command we were demonstrating, including the output text and an image of the
design schematic after running it.

We briefly touched on `select` when it came up in `synth_ice40`, but let's look
at it more now.

.. _select_intro:

Selections intro
^^^^^^^^^^^^^^^^

The `select` command is used to modify and view the list of selected objects:

.. literalinclude:: /code_examples/fifo/fifo.out
   :language: doscon
   :start-at: yosys> select
   :end-before: yosys> show

When we call :yoscrypt:`select -module addr_gen` we are changing the currently
active selection from the whole design, to just the ``addr_gen`` module.  Notice
how this changes the ``yosys`` at the start of each command to ``yosys
[addr_gen]``?  This indicates that any commands we run at this point will *only*
operate on the ``addr_gen`` module.  When we then call :yoscrypt:`select -list`
we get a list of all objects in the ``addr_gen`` module, including the module
itself, as well as all of the wires, inputs, outputs, processes, and cells.

Next we perform another selection, :yoscrypt:`select t:*`.  The ``t:`` part
signifies we are matching on the *cell type*, and the ``*`` means to match
anything.  For this (very simple) selection, we are trying to find all of the
cells, regardless of their type.  The active selection is now shown as
``[addr_gen]*``, indicating some sub-selection of the ``addr_gen`` module.  This
gives us the `$add` and `$eq` cells, which we want to highlight for the
:ref:`addr_gen_hier` image.

.. _select_new_cells:

We can assign a name to a selection with :yoscrypt:`select -set`.  In our case
we are using the name ``new_cells``, and telling it to use the current
selection, indicated by the ``%`` symbol.  We can then use this named selection
by referring to it as ``@new_cells``, which we will see later.  Then we clear
the selection so that the following commands can operate on the full design.
While we split that out for this document, we could have done the same thing in
a single line by calling :yoscrypt:`select -set new_cells addr_gen/t:*`.  If we
know we only have the one module in our design, we can even skip the
``addr_gen/`` part.  Looking further down :ref:`the fifo.ys code <fifo-ys>` we
can see this with :yoscrypt:`select -set new_cells t:$mux t:*dff`.  We can also
see in that command that selections don't have to be limited to a single
statement.

Many commands also support an optional ``[selection]`` argument which can be
used to override the currently selected objects.  We could, for example, call
:yoscrypt:`clean addr_gen` to have `clean` operate on *just* the ``addr_gen``
module.

Detailed documentation of the select framework can be found under
:doc:`/using_yosys/more_scripting/selections` or in the command reference at
:cmd:title:`select`.

.. _show_intro:

Displaying schematics
^^^^^^^^^^^^^^^^^^^^^

While the `select` command is very useful, sometimes nothing beats being able to
see a design for yourself.  This is where `show` comes in.  Note that this
document is just an introduction to the `show` command, only covering the
basics.  For more information, including a guide on what the different symbols
represent, see :ref:`interactive_show` and the
:doc:`/using_yosys/more_scripting/interactive_investigation` page.

.. figure:: /_images/code_examples/fifo/addr_gen_show.*
   :class: width-helper invert-helper
   :name: addr_gen_show

   Calling :yoscrypt:`show addr_gen` after `hierarchy`

.. note::

   The `show` command requires a working installation of `GraphViz`_ and `xdot`_
   for displaying the actual circuit diagrams.

.. _GraphViz: http://www.graphviz.org/
.. _xdot: https://github.com/jrfonseca/xdot.py

This is the first :yoscrypt:`show` command we called in :file:`fifo.ys`,
:ref:`as we saw above <fifo-ys>`.  If we look at the log output for this image
we see the following:

.. literalinclude:: /code_examples/fifo/fifo.out
   :language: doscon
   :start-at: -prefix addr_gen_show
   :end-before: yosys> show

Calling `show` with :yoscrypt:`-format dot` tells it we want to output a
:file:`.dot` file rather than opening it for display.  The :yoscrypt:`-prefix
addr_gen_show` option indicates we want the file to be called
:file:`addr_gen_show.{*}`. Remember, we do this in :file:`fifo.ys` because we
need to store the image for displaying in the documentation you're reading.  But
if you just want to display the images locally you can skip these two options.
The ``-format`` option internally calls the ``dot`` command line program from
GraphViz to convert to formats other than :file:`.dot`.  Check `GraphViz output
docs`_ for more on available formats.

.. _GraphViz output docs: https://graphviz.org/docs/outputs/

.. note::

   If you are using a POSIX based version of Yosys (such as for Mac or Linux),
   xdot will be opened in the background and Yosys can continue to be used. If
   it it still open, future calls to :yoscrypt:`show` will use the same xdot
   instance.

The ``addr_gen`` at the end tells it we only want the ``addr_gen`` module, just
like when we called :yoscrypt:`select -module addr_gen` in :ref:`select_intro`.
That last parameter doesn't have to be a module name, it can be any valid
selection string.  Remember when we :ref:`assigned a name to a
selection<select_new_cells>` and called it ``new_cells``?  We saw in the
:yoscrypt:`select -list` output that it contained two cells, an `$add` and an
`$eq`.  We can call `show` on that selection just as easily:

.. figure:: /_images/code_examples/fifo/new_cells_show.*
   :class: width-helper invert-helper
   :name: new_cells_show

   Calling :yoscrypt:`show -notitle @new_cells`

We could have gotten the same output with :yoscrypt:`show -notitle t:$add t:$eq`
if we didn't have the named selection. By adding the :yoscrypt:`-notitle` flag
there we can also get rid of the ``addr_gen`` title that would have been
automatically added.  The last two images were both added for this introduction.
The next image is the first one we saw in :doc:`/getting_started/example_synth`:
showing the full ``addr_gen`` module while also highlighting ``@new_cells`` and
the two ``PROC`` blocks.  To achieve this highlight, we make use of the
:yoscrypt:`-color` option:

.. figure:: /_images/code_examples/fifo/addr_gen_hier.*
   :class: width-helper invert-helper

   Calling :yoscrypt:`show -color maroon3 @new_cells -color cornflowerblue p:* -notitle`

As described in the the `help` output for `show` (or by clicking on the `show`
link), colors are specified as :yoscrypt:`-color <color> <object>`.  Color names
for the ``<color>`` portion can be found on the `GraphViz color docs`_.  Unlike
the final `show` parameter which can have be any selection string, the
``<object>`` part must be a single selection expression or named selection.
That means while we can use ``@new_cells``, we couldn't use ``t:$eq t:$add``.
In general, if a command lists ``[selection]`` as its final parameter it can be
any selection string.  Any selections that are not the final parameter, such as
those used in options, must be a single expression instead.

.. _GraphViz color docs: https://graphviz.org/doc/info/colors

For all of the options available to `show`, check the command reference at
:cmd:title:`show`.

.. seealso:: :ref:`interactive_show` on the
   :doc:`/using_yosys/more_scripting/interactive_investigation` page.
