Component Energy and Area#
The energy and area of components in the architecture can either be specified directly or by calls to the HWComponents library.
Calculating Energy and Area#
Component energy and area calculations will populate the following fields for each component. If these fields are pre-specified, then they may be used as input to the energy and area calculations.
area: The area of a single instance of this component in m^2. If set, area calculations will use this value.leak_power: The leak power of a single instance of this component in W. If set, leak power calculations will use this value.actions[<action name>].energy: Dynamic energy of this action. Per-action energy is multiplied by the component’s energy_scale and the action’s energy_scale.total_area: The total area of all instances of this component in m^2. Do not set this value. It is calculated when the architecture’s area is calculated.total_leak_power: The total leak power of all instances of this component in W. Do not set this value. It is calculated when the architecture’s leak power is calculated. If instances are power gated, actual leak power may be less than this value.component_modeling_log: A log of the energy and area calculations for this Component.component_model: The model to use for this Component. If not set, the model will be found with hwcomponents.get_models(). If set, the component_class will be ignored.
Additionally, the following fields will affect the energy and area calculations:
energy_scale: The scale factor for dynamic energy of this component. For each action, multiplies this action’s energy. Multiplies the calculated energy of each action.leak_power_scale: The scale factor for the leak power of this component. This is used to scale the leak power of this component. For example, if the leak power is 1 W and the scale factor is 2, then the leak power is 2 W.area_scale: The scale factor for the area of this comxponent. This is used to scale the area of this component. For example, if the area is 1 m^2 and the scale factor is 2, then the area is 2 m^2.n_parallel_instances: The number of parallel instances of this component. Increasing parallel instances will proportionally increase area and leakage, while reducing latency (unless latency calculation is overridden).actions[<action name>].energy_scale: The scale factor for dynamic energy of this action. Multiplies this action’s energy by this value.
The energy and area of a all components in the architecture can be calculated by calling
calculate_component_area_energy_latency_leak().
Note that an Einsum name can be provided to populate symbols with the Einsum’s symbols
from the workload; otherwise, if the architecture depends on something in the workload,
an error will be raised.
# Load the spec and calculate the energy and area of the entire design
spec = af.Spec.from_yaml(examples_dir / "arches" / "eyeriss.yaml")
spec = spec.calculate_component_area_energy_latency_leak()
# Print out the total area and leakage power of the entire design
print(f'Total area of the design: {spec.arch.total_area:.2e} m^2')
print(f'Area breakdown per component:')
for component, area in spec.arch.per_component_total_area.items():
print(f'\t{component}: {area:.2e} m^2')
print(f'Total leakage power of the design: {spec.arch.total_leak_power:.2e} W')
for component, leak_power in spec.arch.per_component_total_leak_power.items():
print(f'\t{component}: {leak_power:.2e} W')
We can also calculate the energy and area of individual components by calling
calculate_area_energy_latency_leak() on
them.
# Create the component from the yaml file
import accelforge as af
global_buffer = af.arch.Memory.from_yaml(
examples_dir / "misc" / "component_annotated.yaml"
)
# Calculate the energy and area of the component
global_buffer = global_buffer.calculate_area_energy_latency_leak()
# Print out the area, leak power, and energy for each action
area = global_buffer.area
leak_power = global_buffer.leak_power
print(f"Area: {area:.2e} m^2")
print(f"Leak power: {leak_power:.2e} W")
for action in global_buffer.actions:
energy = action.energy
latency = action.latency
print(f'Action {action.name} energy {energy:.2e} J, latency {latency:.2e}s')
There are additional Config fields that affect
the energy and area calculations, which can be set in the
Spec object’s config field:
component_models: A list of hwcomponents models to use for the energy and area calculations. These can either be paths to Python files that contain the models, or `hwcomponents` :py:class:`~hwcomponents.ComponentModel` objects.expression_custom_functions: A list of functions to use while parsing expressions. These can either be functions or paths to Python files that contain the functions. If a path is provided, then all functions in the file will be added to the evaluator.use_installed_component_models: If True, then the `hwcomponents` library will find all installed models. If False, then only the models specified in `component_models` will be used.
Specifying Area, Energy, Latency, and Leak Power#
One way to specify the area, energy, latency, and leak power of each component is to
directly set the area, leak_power, actions[<action name>].energy, and
actions[<action name>].latency fields. The following example from the TPU v4i
example architecture shows uses this approach:
name: GlobalBuffer
size: 1024*1024*128*8 # 128MB
total_latency: max(read_latency, write_latency) # Separate ports
leak_power: 0
area: 112e-6 # 112 mm^2
actions:
- {name: read, energy: 1.88e-12, latency: 1 / (8 * 2048e9)}
- {name: write, energy: 2.36e-12, latency: 1 / (8 * 1024e9)}
tensors: {keep: ~MainMemory.tensors, may_keep: All}
If any value is omitted, it will raise an appropriate error when
calculate_component_area_energy_latency_leak()
is called, so you may call this function to check whether you’ve missed anything.
hwcomponents is invoked automatically if any of the fields are missing. If you don’t
want it to be called, then you can do one of the following:
If calling
calculate_component_area_energy_latency_leak(), then you can setspec.config.component_modelsandspec.config.use_installed_component_modelsto an empty list andFalse, respectively.If calling
calculate_area_energy_latency_leak(), then you can setmodelsto an empty list.
Using the hwcomponents Library#
hwcomponents is invoked automatically when area and energy are not specified. The
following shows the fields used by hwcomponents:
# The YAML tag at the beginning of the component tells the parser what type of component
# it is.
!Memory
name: GlobalBuffer
# This component_class invokes the hwcomponents_library.SmartBufferSRAM model. The
# component is a SRAM buffer with an address register that is updated on every
# access to queue up the next data.
component_class: SmartBufferSRAM
# Set the size to 16384 bits (64 bits wide, 256 deep)
size: 16384
# Sometimes, hwcomponents models require additional attributes that are not part of the
# accelforge spec. These can be passed to the component models through the
# extra_attributes_for_component_model field.
extra_attributes_for_component_model:
width: 64
n_banks: 32
tech_node: 65e-9
# Actions that the hwcomponents_library model must support. All action attributes that
# can are passed to the model's appropriate method (in this case, `read` or `write`).
# The `bits_per_action` argument is special because it determines how many bits are
# transferred by each read or write. Additionally, to pass extra attributes to the
# component model as arguments, actions also have a extra_attributes_for_component_model
# field.
# For many component models, energy and latency are measured per-bit, so bits_per_action
# may be omitted in these cases.
actions:
- {name: read, bits_per_action: 64}
- {name: write, bits_per_action: 64}
When hwcomponents has been used to calculate the energy and area of a component,
then the component_model field will be set to the hwcomponents model used to
calculate the energy and area.
In addition to looking at the component_modeling_log field, we can further inspect
the component_model field to see more information about the model.
for message in global_buffer.component_modeling_log:
print(message)
component_model = global_buffer.component_model
print(help(component_model)) # Get documentation for the model
# The model is a hwcomponents_library.SmartBufferSRAM object!
from hwcomponents_library import SmartBufferSRAM
# Type hint it for our IDE
component_model: SmartBufferSRAM = global_buffer.component_model
# Inspect the area of each of its subcomponents
print(f'Area: {component_model.area:.2e} m^2')
print(f'\tSRAM area: {component_model.sram.area:.2e} m^2')
print(f'\tAdder area: {component_model.adder.area:.2e} m^2')
print(f'\tAddress register area: {component_model.address_reg.area:.2e} m^2')
print(f'\tDelta reg area: {component_model.delta_reg.area:.2e} m^2')