aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwilisa01 <william.isaksson@arm.com>2023-04-13 17:05:09 +0000
committerFredrik Svedberg <fredrik.svedberg@arm.com>2023-05-04 08:45:46 +0000
commit0a7d5ee98dfc8c881372bc5a50be37aed209c30e (patch)
tree7b88b1cc4bae5fa835f16f0c0d51fe7d4e14a7af
parent50550d60121a3ca39b086d643163e7c74ccee837 (diff)
downloadethos-u-vela-0a7d5ee98dfc8c881372bc5a50be37aed209c30e.tar.gz
MLBEDSW-7504: Vela does not keep op version number
We now read operator code version, store it in operator and write it out to optimized file. Signed-off-by: wilisa01 <william.isaksson@arm.com> Change-Id: Idba672531d2e2a0203a85d3ffca9cf65ace85b47
-rw-r--r--ethosu/vela/operation.py4
-rw-r--r--ethosu/vela/test/test_tflite_reader.py24
-rw-r--r--ethosu/vela/tflite_reader.py5
-rw-r--r--ethosu/vela/tflite_writer.py12
4 files changed, 26 insertions, 19 deletions
diff --git a/ethosu/vela/operation.py b/ethosu/vela/operation.py
index 69596522..161b17fd 100644
--- a/ethosu/vela/operation.py
+++ b/ethosu/vela/operation.py
@@ -471,6 +471,7 @@ class Operation:
"type",
"_original_type",
"name",
+ "version",
"op_index",
"attrs",
"inputs",
@@ -504,6 +505,7 @@ class Operation:
self.type = op_type
self._original_type = op_type # the original type of the operation. once set this shouldn't be changed
self.name = name
+ self.version = 1 # Used to track original operator version.
self.attrs: Dict[str, Any] = {}
self.inputs: List[Optional[Tensor]] = []
self.outputs: List[Tensor] = []
@@ -549,7 +551,7 @@ class Operation:
# maintain the original type, in cases where the type was changed to something different
res._original_type = self._original_type
-
+ res.version = self.version
res.attrs = dict(self.attrs)
res.inputs = list(self.inputs)
res.outputs = list(self.outputs)
diff --git a/ethosu/vela/test/test_tflite_reader.py b/ethosu/vela/test/test_tflite_reader.py
index 871545e4..d1a8ee67 100644
--- a/ethosu/vela/test/test_tflite_reader.py
+++ b/ethosu/vela/test/test_tflite_reader.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: Copyright 2020-2021 Arm Limited and/or its affiliates <open-source-office@arm.com>
+# SPDX-FileCopyrightText: Copyright 2020-2021, 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
#
# SPDX-License-Identifier: Apache-2.0
#
@@ -46,25 +46,25 @@ class TestTFLiteSubgraph:
assert output == expected
parse_op_testdata = [
- # op_type, opt_serializer, indices, inputs, output, expected
- (Op.FullyConnected, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, [0, 1, 2], 3, 3), # FC
- (Op.FullyConnected, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, [0, 1, -1], 3, 3), # FC disabled Bias
- (Op.FullyConnected, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, [0, 1], 3, 3), # FC no Bias
- (Op.Conv2DBias, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, [2, 1, 3], 0, 3), # Conv2D
- (Op.Conv2DBackpropInput, None, TFLITE_CONV2D_BACKPROP_INDICES, [0, 1, 2, 3], 4, 4), # TransposeConv
- (Op.Conv2DBackpropInput, None, TFLITE_CONV2D_BACKPROP_INDICES, [0, 1, 2], 4, 4), # TransposeConv no Bias
+ # op_type, opt_serializer, indices, version, inputs, output, expected
+ (Op.FullyConnected, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, 1, [0, 1, 2], 3, 3), # FC
+ (Op.FullyConnected, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, 1, [0, 1, -1], 3, 3), # FC disabled Bias
+ (Op.FullyConnected, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, 5, [0, 1], 3, 3), # FC no Bias
+ (Op.Conv2DBias, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, 5, [2, 1, 3], 0, 3), # Conv2D
+ (Op.Conv2DBackpropInput, None, TFLITE_CONV2D_BACKPROP_INDICES, 5, [0, 1, 2, 3], 4, 4), # TransposeConv
+ (Op.Conv2DBackpropInput, None, TFLITE_CONV2D_BACKPROP_INDICES, 5, [0, 1, 2], 4, 4), # TransposeConv no Bias
pytest.param(
- Op.Conv2DBias, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, [0, -1, 1], 3, 3, marks=pytest.mark.xfail
+ Op.Conv2DBias, None, TFLITE_IFM_WEIGHTS_BIAS_INDICES, 5, [0, -1, 1], 3, 3, marks=pytest.mark.xfail
), # Conv2D no Weights
]
- @pytest.mark.parametrize("op_type, opt_serializer, indices, inputs, output, expected", parse_op_testdata)
- def test_parse_operator(self, op_type, opt_serializer, indices, inputs, output, expected):
+ @pytest.mark.parametrize("op_type, opt_serializer, indices, version, inputs, output, expected", parse_op_testdata)
+ def test_parse_operator(self, op_type, opt_serializer, indices, version, inputs, output, expected):
with patch.object(TFLiteSubgraph, "__init__", lambda self, graph, subraph: None):
# Mock a TFLiteSubGraph
sg = TFLiteSubgraph(None, None)
sg.graph = MagicMock()
- sg.graph.operator_codes = [(op_type, opt_serializer, "", indices)]
+ sg.graph.operator_codes = [(op_type, opt_serializer, "", indices, version)]
# Mock a couple of tensors
sg.tensors = [MagicMock() for _ in range(5)]
diff --git a/ethosu/vela/tflite_reader.py b/ethosu/vela/tflite_reader.py
index 061f3626..85acb6b8 100644
--- a/ethosu/vela/tflite_reader.py
+++ b/ethosu/vela/tflite_reader.py
@@ -117,7 +117,7 @@ class TFLiteSubgraph:
return tens
def parse_operator(self, op_index, op_data):
- op_type, opt_serializer, custom_code, indices = self.graph.operator_codes[op_data.OpcodeIndex()]
+ op_type, opt_serializer, custom_code, indices, version = self.graph.operator_codes[op_data.OpcodeIndex()]
inputs = [self.tensors[idx] if idx != -1 else None for idx in op_data.InputsAsNumpy()]
outputs = [self.tensors[idx] if idx != -1 else None for idx in op_data.OutputsAsNumpy()]
intermediates = []
@@ -130,6 +130,7 @@ class TFLiteSubgraph:
inputs = align_tensor_indices_to_nng(op_type, indices, inputs)
op = Operation(op_type, name)
op.op_index = op_index
+ op.version = version
op.inputs = inputs
op.outputs = outputs
op.intermediates = intermediates
@@ -338,7 +339,7 @@ class TFLiteGraph:
custom_code = None
if c == BuiltinOperator.CUSTOM:
custom_code = decode_str(code.CustomCode())
- return op_type, ser, custom_code, indices
+ return op_type, ser, custom_code, indices, code.Version()
def read_tflite(filename, batch_size, feed_dict, output_node_names, initialisation_nodes):
diff --git a/ethosu/vela/tflite_writer.py b/ethosu/vela/tflite_writer.py
index 2e7345ce..8c03f051 100644
--- a/ethosu/vela/tflite_writer.py
+++ b/ethosu/vela/tflite_writer.py
@@ -108,8 +108,8 @@ class TFLiteSerialiser:
if inp is not None and inp.src_tensor is not None:
op.inputs[idx] = inp.src_tensor
- # list of tuple(Op, string); the custom code is only used for 3rd party custom operators
- self.operator_codes = sorted(set((op.type, op.attrs.get("custom_code", "")) for op in all_ops))
+ # list of tuple(Op, string, op.version); the custom code is only used for 3rd party custom operators
+ self.operator_codes = sorted(set((op.type, op.attrs.get("custom_code", ""), op.version) for op in all_ops))
self.operator_code_map = {}
def align_nng_inputs_to_tflite(self, op):
@@ -176,7 +176,7 @@ class TFLiteSerialiser:
return buffer_map
- def serialise_operator_code(self, idx, op_type, custom_code):
+ def serialise_operator_code(self, idx, op_type, custom_code, version):
builder = self.builder
custom_code_offset = None
if op_type == Op.Custom:
@@ -207,6 +207,7 @@ class TFLiteSerialiser:
OperatorCode.OperatorCodeStart(builder)
OperatorCode.OperatorCodeAddDeprecatedBuiltinCode(builder, tf_code if tf_code < 127 else 127)
OperatorCode.OperatorCodeAddBuiltinCode(builder, tf_code)
+ OperatorCode.OperatorCodeAddVersion(builder, version)
if custom_code_offset is not None:
OperatorCode.OperatorCodeAddCustomCode(builder, custom_code_offset)
@@ -455,7 +456,10 @@ class TFLiteSerialiser:
def serialise_model(self):
builder = self.builder
operator_code_offset = self.write_offset_vector(
- [self.serialise_operator_code(idx, optype, code) for idx, (optype, code) in enumerate(self.operator_codes)]
+ [
+ self.serialise_operator_code(idx, optype, code, version)
+ for idx, (optype, code, version) in enumerate(self.operator_codes)
+ ]
)
description = builder.CreateString("Vela Optimised")