.. _advanced-usage:

Advanced Usage
==============

Hammer Development and Upgrades
-------------------------------
If you need to develop Hammer within Chipyard or use a version of Hammer beyond the latest PyPI release, clone the `Hammer repository <https://github.com/ucb-bar/hammer>`__ somewhere else on your disk. Then:

.. code-block:: shell

    pip install -e <path/to/hammer>

To bump specific plugins to their latest commits and install them, you can use the upgrade script from the Chipyard root directory, with arguments for match patterns for the plugin names:

.. code-block:: shell

    ./scripts/upgrade-vlsi.sh <pattern(s)>

If you would like to upgrade your Hammer installation to the latest PyPI release and bump all of your plugins at once, run the above script without arguments. WARNING: this may pull in plugin changes that are newer than the latest Hammer release and cause incompatibility issues.

Alternative RTL Flows
---------------------
The Make-based build system provided supports using Hammer without using RTL generated by Chipyard. To push a custom Verilog module through, one only needs to append the following environment variables to the ``make buildfile`` command (or edit them directly in the Makefile).

.. code-block:: shell

    CUSTOM_VLOG=<your Verilog files>
    VLSI_TOP=<your top module>

``CUSTOM_VLOG`` breaks the dependency on the rest of the Chipyard infrastructure and does not start any Chisel/FIRRTL elaboration. ``VLSI_TOP`` selects the top module from your custom Verilog files.

Under the Hood
--------------
To uncover what is happening under the hood, here are the commands that are executed:

For ``make syn``:

.. code-block:: shell

    ./example-vlsi -e /path/to/env.yml -p /path/to/example.yml -p /path/to/inputs.yml --obj_dir /path/to/build syn

``example-vlsi`` is the entry script as explained before, ``-e`` provides the environment yml, ``-p`` points to configuration yml/jsons, ``--obj_dir`` speficies the destination directory,  and ``syn`` is the action.

For ``make par``:

.. code-block:: shell

    ./example-vlsi -e /path/to/env.yml -p /path/to/syn-output-full.json -o /path/to/par-input.json --obj_dir /path/to/build syn-to-par
    ./example-vlsi -e /path/to/env.yml -p /path/to/par-input.json --obj_dir /path/to/build par

A ``syn-to-par`` action translates the synthesis output configuration into an input configuration given by ``-o``. Then, this is passed to the ``par`` action.

For more information about all the options that can be passed to the Hammer command-line driver, please see the Hammer documentation.

Manual Step Execution & Dependency Tracking
-------------------------------------------
It is invariably necessary to debug certain steps of the flow, e.g. if the power strap settings need to be updated. The underlying Hammer commands support options such as ``--stop_after_step``, ``--start_before_step``, and ``--only_step``. These allow you to control which steps of a particular action are executed.

Make's dependency tracking can sometimes result in re-starting the entire flow when the user only wants to re-run a certain action. Hammer's build system has "redo" targets such as ``redo-syn`` and ``redo-par`` to run certain actions without typing out the entire Hammer command.

Say you need to update some power straps settings in ``new_power_straps.yml`` and want to try out the new settings:

.. code-block:: shell

   make redo-par HAMMER_REDO_ARGS='-p new_power_straps.yml --only_step power_straps'

The command that is executed will be:

.. code-block:: shell

    ./example-vlsi -e /path/to/env.yml -p /path/to/par-input.json -p new_power_straps.yml --only_step power_straps --obj_dir /path/to/build par

Hierarchical RTL/Gate-level Simulation, Power Estimation
--------------------------------------------------------
With the Synopsys plugin, hierarchical RTL and gate-level simulation is supported using VCS at the chip-level. Also, rtl-level/post-syn power estimation with Joules and post-par power estimation with Voltus in the Cadence plugin is also supported. Special Make targets are provided in the ``vlsi/`` directory in ``sims.mk`` and ``power.mk``. Here is a brief description:

* ``sim-rtl``: RTL-level simulation

  * ``sim-rtl-debug``: Also write a FSDB waveform

* ``sim-syn``: Post-synthesis gate-level simulation

  * ``sim-syn-debug``: Also write a FSDB waveform
  * ``sim-syn-timing-debug``: Timing-annotated with FSDB waveform

* ``sim-par``: Post-par gate-level simulation

  * ``sim-par-debug``: Also write a FSDB waveform
  * ``sim-par-timing-debug``: Timing-annotated with FSDB waveform

* ``power-rtl``: RTL-level power estimation

  * Note: this will run ``sim-rtl-debug`` first

* ``power-syn``: Post-synthesis power estimation

  * Note: this will run ``sim-syn-debug`` first

* ``power-par``: Post-par power estimation

  * Note: this will run ``sim-par-debug`` first

* ``redo-`` can be appended to all above targets to break dependency tracking, like described above.

* ``-$(VLSI_TOP)`` suffixes denote simulations/power analysis on a submodule in a hierarchical flow (remember to override this variable). Note that you must provide the testbenches for these modules since the default testbench only simulates a Chipyard-based ``ChipTop`` DUT instance.

The simulation configuration (e.g. binaries) can be edited for your design. See the ``Makefile`` and refer to Hammer's documentation for how to set up simulation parameters for your design.

UPF Generation Flow
-------------------------------
This VLSI flow experimentally supports generating Chisel-based `UPF <https://vlsitutorials.com/upf-low-power-vlsi/>`__ files using `Chisel Aspects <https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/latest/chisel3/aop/Aspect.html>`__.

To generate UPF for any design, first modify the ``UPFInputs`` object in ``generators/chipyard/src/main/scala/upf/UPFInputs.scala`` to fit your design power specifications.

This involves filling in the ``upfInfo`` list with ``PowerDomainInput`` objects representing all the power domains you want in your design, along with specifying hierarchy and domain attributes.

The given example in ``UPFInputs`` corresponds to a dual-core Rocket config with 3 power domains (1 parent domain with all uncore modules and 2 children corresponding to the Rocket tiles).

To run the flow:

.. code-block:: shell

    cd chipyard/vlsi
    make verilog ASPECTS=chipyard.upf.ChipTopUPFAspect

The output UPF files will be dumped in ``vlsi/generated-src/upf``.
