Accelerator Energy, Area, and Latency
=====================================

.. _accelerator-energy-latency:

To calculate energy and latency, we first need to look at the number of actions incurred
by each :py:class:`~fastfusion.frontend.arch.Component` in the architecture.

Calculating Number of Actions from A Mapping
--------------------------------------------

.. _calculating-num-actions:

Except for :py:class:`~fastfusion.frontend.arch.Compute`\ components (whose number of
compute actions, barring recomputation, depends only on workload), the number of actions
incurred by most :py:class:`~fastfusion.frontend.arch.Component`\ s depends on the
component type, the workload, and the mapping.

For :py:class:`~fastfusion.frontend.arch.Memory` and
:py:class:`~fastfusion.frontend.arch.ProcessingStage` components, the number of actions
depends on the number of accesses to the component. They may be accessed in two ways:

- ``read``: The component is read from a lower-level component, or output values are read
  up to a higher-level component.
- ``write``: The component is written to a lower-level component, or input values are
  written from a higher-level component.

The number of actions incurred by accesses for each tensor are equal to the number of
values accessed times the datawidth of the tensor (determined by that component's
:py:class:`~fastfusion.frontend.arch.TensorHolderAttributes`), divided by the
:py:class:`~fastfusion.frontend.arch.ActionArguments` ``bits_per_action`` attribute. For
example, if 1024 values are accessed with a datawidth of 16 bits and ``bits_per_action``
is 32, then 1024 * 16 / 32 = 512 actions are incurred.

Read+Modify+Writes (RMWs) to a component are counted as a read and a write. The first
read of output data is skipped because the value has not been written yet.

By default, the ``datawidth`` and ``bits_per_action`` attributes are set to 1.
Generally, it works to leave these as 1. For example:

- If ``bits_per_action`` is 1, then each action accesses one bit, so we can define
  actions in terms of bits accessed
- If ``datawidth`` is 1 and ``bits_per_action`` is 1, then each action accesses one
  value, so we can define actions in terms of values accessed. Additionally, ``size``
  will then be in terms of number of values that can be held, rather than number of
  bits.

The latter case is the default, and you may often see ``datawidth`` and
``bits_per_action`` un-set, ``size`` set to the number of values in the tensor, and
actions defined in terms of values accessed rather than bits.


Calculating Latency from a Pmapping
-----------------------------------

The :py:obj:`~fastfusion.frontend.arch.ComponentAttributes.latency` of a component, defined
in the class's `attributes.latency` field, is a Python expression that is evaluated
using the component's actions.

The :py:obj:`~fastfusion.frontend.arch.ComponentAttributes.latency` field is
:docstring-lower:`fastfusion.frontend.arch.ComponentAttributes.latency`


Calculating Area and Leak Power
-------------------------------

After :ref:`component-modeling` is completed, we can get area with the
:py:meth:`~fastfusion.frontend.arch.Arch.per_component_total_area` and
:py:meth:`~fastfusion.frontend.arch.Arch.total_area` methods. Similarly, we can get
leak power with the
:py:meth:`~fastfusion.frontend.arch.Arch.per_component_total_leak_power` and
:py:meth:`~fastfusion.frontend.arch.Arch.total_leak_power` methods.