aboutsummaryrefslogtreecommitdiff
path: root/ethosu/vela/operation_util.py
diff options
context:
space:
mode:
authorFredrik Svedberg <fredrik.svedberg@arm.com>2023-04-11 22:35:04 +0200
committerFredrik Svedberg <fredrik.svedberg@arm.com>2023-04-17 14:16:44 +0200
commit0ac0804e76e098695ee2b8a9e24e2f0a1efc324f (patch)
tree9ccb766221987a415244079ed6c596a47d693b20 /ethosu/vela/operation_util.py
parentc1ad80b3a581dd39b39a112d6c2026f6560207a4 (diff)
downloadethos-u-vela-0ac0804e76e098695ee2b8a9e24e2f0a1efc324f.tar.gz
MLBEDSW-7196 Add LSTM support
Added int8 and int16 UNIDIRECTIONAL_SEQUENCE_LSTM support. The implementation does not include support for: * CIFG * Peephole * Projection * Normalisation This change also: * Removed unused Op.BlockLSTM operation type. * Removed the only one consumer limitation on putting the SplitSliceRead on the tensor consumer(s), if all consumers fullfills the requirements * Added Op.VariableTensorWrite as a Operation.memory_function to make sure writes to variable tensors: * Always use linear mode * Are not moved to fast scratch * Are not fused with other elementwise operation tensor ranges Change-Id: Ief831738924ac3d1f2ba6d41f10bd6dc969911f3 Signed-off-by: Fredrik Svedberg <fredrik.svedberg@arm.com>
Diffstat (limited to 'ethosu/vela/operation_util.py')
-rw-r--r--ethosu/vela/operation_util.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/ethosu/vela/operation_util.py b/ethosu/vela/operation_util.py
index 74836eb2..ef4949fa 100644
--- a/ethosu/vela/operation_util.py
+++ b/ethosu/vela/operation_util.py
@@ -27,8 +27,10 @@ from .operation import ActivationFunction
from .operation import Op
from .operation import Operation
from .operation import Padding
+from .reader_util import clone_and_reshape_tensor
from .shape4d import Shape4D
from .tensor import create_const_tensor
+from .tensor import create_equivalence_id
from .tensor import QuantizationParameters
from .tensor import Tensor
@@ -117,6 +119,55 @@ def create_cast_op(
return op
+def create_fused_activation(op_type: Op, name: str, ifm: Tensor, quantization: QuantizationParameters) -> Operation:
+ assert op_type.is_activation_op()
+ op = create_avgpool_nop(name)
+ op.activation = ActivationFunction(op_type)
+ ofm = Tensor(ifm.shape, ifm.dtype, f"{op.name}_tens0")
+ ofm.quantization = quantization
+ op.add_input_tensor(ifm)
+ op.set_output_tensor(ofm)
+ op.set_ifm_ofm_shapes()
+ return op
+
+
+def create_fullyconnected(
+ name: str,
+ ifm: Tensor,
+ weights: Tensor,
+ bias: Optional[Tensor],
+ quantization: QuantizationParameters,
+ vela_weight_order: bool = True,
+) -> Operation:
+ # Reshape weights if needed
+ if not vela_weight_order:
+ weights = clone_and_reshape_tensor(weights, (1, 0), False)
+
+ n_ofm = weights.shape[-1]
+
+ # Setup bias if needed
+ if not bias:
+ bias_values = [0] * n_ofm
+ dtype = DataType.int64 if ifm.dtype == DataType.int16 else DataType.int32
+ bias = create_const_tensor(f"{name}_bias", [n_ofm], dtype, bias_values)
+ # Set equivalence_id based on values to avoid placing duplicate data in flash
+ bias.equivalence_id = create_equivalence_id(tuple(bias_values))
+ bias.value_id = bias.equivalence_id
+
+ # Setup ofm
+ ofm = Tensor([ifm.shape[0], n_ofm], ifm.dtype, f"{name}_tens0")
+ ofm.quantization = quantization
+
+ # Create op and add tensors
+ op = Operation(Op.FullyConnected, name)
+ op.add_input_tensor(ifm)
+ op.add_input_tensor(weights)
+ op.add_input_tensor(bias)
+ op.set_output_tensor(ofm)
+ op.set_ifm_ofm_shapes()
+ return op
+
+
def create_depthwise_maxpool(
name: str,
ifm: Tensor,