Expression Evaluation#
Objects can include expressions that are evaluated when the
Spec is evaluated. Evaluation occurs when the
Spec() is going to be used to model the energy, area,
or latency of an accelerator, such as when the
calculate_component_area_energy_latency_leak()
method is called.
To-be-evaluated expressions can include Python code, and supported
operations include many standard library functions (e.g., range, min) and
functions from the math standard library (e.g., log2, ceil).
The scope available for evaluation includes the following in order of increasing precedence:
Variables defined in a top-level
Variablesobject.Variables defined in outer-level YAML objects. Dictionary keys can be referenced by names, and list entries by index. The dot syntax can be used to access dictionaries; for example,
x.y.zis equivalent toouter_scope["x"]["y"]["z"].Variables defined in the current YAML object. Dictionary keys may reference each other as long as references are not cyclic.
The following is an example of valid evaluated data:
variables:
a: 123
b: a + 5
c: min(b, 3)
d: sum(y for y in range(1, 10))
# In some later scope
... outer_scope:
x: 123
y: a + x # Reference top-level variables
inner_scope:
a: 3 # Override outer scope
b: outer_scope.x
# Statements can be out-of-order if not cyclic referencing
firt_item: second_item
second_item: 3
Additionally, values can be set directly in Python code. For example:
from accelforge.frontend.arch import ComponentAttributes
attributes = ComponentAttributes(
value1=123,
value2="value1 + 5"
# ... other attributes
)
Included Functions#
The following are available functions. In addition to the below, Python keywords that
are available witout import (e.g., min) are also available
ceil:math.ceil()comb:math.comb()copysign:math.copysign()fabs:math.fabs()factorial:math.factorial()floor:math.floor()fmod:math.fmod()frexp:math.frexp()fsum:math.fsum()gcd:math.gcd()isclose:math.isclose()isfinite:math.isfinite()isinf:math.isinf()isnan:math.isnan()isqrt:math.isqrt()ldexp:math.ldexp()modf:math.modf()perm:math.perm()prod:math.prod()remainder:math.remainder()trunc:math.trunc()exp:math.exp()expm1:math.expm1()log:math.log()log1p:math.log1p()log2:math.log2()log10:math.log10()pow:math.pow()sqrt:math.sqrt()acos:math.acos()asin:math.asin()atan:math.atan()atan2:math.atan2()cos:math.cos()dist:math.dist()hypot:math.hypot()sin:math.sin()tan:math.tan()degrees:math.degrees()radians:math.radians()acosh:math.acosh()asinh:math.asinh()atanh:math.atanh()cosh:math.cosh()sinh:math.sinh()tanh:math.tanh()erf:math.erf()erfc:math.erfc()gamma:math.gamma()lgamma:math.lgamma()pi:math.pi()e:math.e()tau:math.tau()inf:math.inf()nan:math.nan()abs:abs()round:round()pow:pow()sum:sum()range:range()len:len()min:min()max:max()float:float()int:int()str:str()bool:bool()list:list()tuple:tuple()enumerate:enumerate()getcwd:os.getcwd()map:map()
Additional funcitons can be added to the scope by definining the
expression_custom_functions attribute and
listing either functionss or paths to Python files that contain functions.
Set Expressions#
In the architecture, set expressions may reference the tensors and rank variables of the specific Einsum being executed. Set expressions are evaluated for each Einsum + Flattened-Architecture (Flattening) combination.
As an example of a set expression, we can describe all tensors that are not intermediates using the following:
~Intermediates
Set expressions can use the full Python syntax, including the following:
&: Intersection|: Union~: Complement-: Difference
You may also use Pythonic language with set expressions in some locations. For example, we may want to use input tensors if and only if there are three or fewer total tensors:
Inputs if len(All) > 3 else All
Set expressions are evaluated for every Einsum + Flattened-Architecture (Flattening) combination. The following set expressions are supported:
All: All tensors used in the current Einsum.Inputs: Tensors input to the current Einsum.Intermediates: Tensors produced by one Einsum and consumed by another.Nothing: The empty set.Outputs: Tensors output from the current Einsum.Persistent: Tensors that must remain in backing storage for the full duration of the workload’s execution.Shared: Tensors that are shared between multiple Einsums.Tensors: Alias forAll.
Additionally, the following special variables are available:
Above: The set of all tensors that are stored in all memory objects above the current memory object in the hierarchy. Includes the same caveats as the previousMemoryObject.<Any Tensor Name>: Resolves to the tensor with the given name. If the tensor is not used in the current Einsum, then it resolves to the empty set.
MemoryObject.Tensors: The set of all tensors that are stored in the memory object. Architectures are evaluated from the top down, so this will only be availableMemoryObjecthas been evaluated. Lower-level memory objects may reference upper-level memory objects, but not vice versa. Additionally, this may not be used for energy and area calculations.
All tensor expressions can be converted into relevant rank variables by accessing
.rank_variables, which will return the set of all rank variables that index into the
tensor. If multiple tensors are referenced, then the union of all indexing rank
variables is returned. For example, MemoryObject.tensors.rank_variables will return
the set of all rank variables that index into any of the tensors stored in
MemoryObject.
Every tensor expression also has a bits_per_value attribute that returns the number
of bits per value for the tensor. This can only be called on size-one sets of tensors,
or else an error will be raised.
Additional keys can be defined following the renaming section of the Workload and Renames Specification.