From 81b765df02d7c7cae5f1084eec998824b68c00ab Mon Sep 17 00:00:00 2001 From: Johan Gunnarsson Date: Fri, 4 Aug 2023 17:16:29 +0200 Subject: MLBEDSW-7626: Add constraint for PAD op paddings PAD input tensor shape plus paddings must equal output tensor shape. Change-Id: Icc5dea9bf6a8f6e1c8402f4d9af4d9796e8ef1aa Signed-off-by: Johan Gunnarsson --- SUPPORTED_OPS.md | 4 +++- ethosu/vela/test/test_tflite_model_semantic.py | 12 ++++++++++++ ethosu/vela/tflite_model_semantic.py | 11 +++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/SUPPORTED_OPS.md b/SUPPORTED_OPS.md index 8a992b5f..17a17ecf 100644 --- a/SUPPORTED_OPS.md +++ b/SUPPORTED_OPS.md @@ -19,7 +19,7 @@ limitations under the License. # Supported Ops This file was automatically generated by Vela using the `--supported-ops-report` parameter. -Vela version: `3.8.1.dev17+g1d5e859.d20230711` +Vela version: `3.8.1.dev24+g3c2461d` This file complies with [**Gitiles Markdown syntax**](https://github.com/google/gitiles/blob/master/Documentation/markdown.md) @@ -292,6 +292,7 @@ This is a list of constraints that the PAD operator must satisfy in order to be - Number of input tensors must be exactly 2 - The padding tensor must be constant +- Shape of output tensor must equal to size of input tensor plus padding - The padding tensor must have the shape [3,2] or [4,2] - The pad tensor can only pad width and height - Pad tensor must be of type: int32, int64 @@ -427,3 +428,4 @@ This is a list of constraints that the UNIDIRECTIONAL_SEQUENCE_LSTM operator mus - Must not use Projection - Must not use Normalisation - All input and recurrent weights must be available +- All recurrent weights must be 2D diff --git a/ethosu/vela/test/test_tflite_model_semantic.py b/ethosu/vela/test/test_tflite_model_semantic.py index e7fd3073..7ca1bbda 100644 --- a/ethosu/vela/test/test_tflite_model_semantic.py +++ b/ethosu/vela/test/test_tflite_model_semantic.py @@ -356,6 +356,18 @@ def test_constraint_pad_input_count(): assert not semantic_checker.is_operator_semantic_valid(op) +def test_constraint_pad_output_shape(): + # Incorrect output tensor shape + op = create_pad_op( + in_shape=[1, 1, 1, 1], + out_shape=[1, 3, 3, 1], + padding=[[0, 0], [1, 1], [1, 1], [0, 0]], + ) + assert semantic_checker.is_operator_semantic_valid(op) + op.outputs[0].shape = [1, 1, 1, 1] + assert not semantic_checker.is_operator_semantic_valid(op) + + def create_strided_slice(): # Creates a valid strided slice operator with some valid inputs/outputs op = create_strided_slice_op([1, 10, 10, 10], [1, 5, 5, 10], [127, 2, 2, 0], [0, 7, -3, 0]) diff --git a/ethosu/vela/tflite_model_semantic.py b/ethosu/vela/tflite_model_semantic.py index 62648914..ea7ef4a3 100644 --- a/ethosu/vela/tflite_model_semantic.py +++ b/ethosu/vela/tflite_model_semantic.py @@ -184,6 +184,7 @@ class TFLiteSemantic: # Pad specific checks: self.specific_constraints[Op.Pad].append(TFLiteSemantic.constraint_pad_input_count) self.specific_constraints[Op.Pad].append(TFLiteSemantic.constraint_pad_constant) + self.specific_constraints[Op.Pad].append(TFLiteSemantic.constraint_pad_output_shape) # HardSwish specific checks: self.specific_constraints[Op.HardSwish].append(TFLiteSemantic.constraint_input_8bit) @@ -585,6 +586,16 @@ class TFLiteSemantic: valid = pad_tensor is not None return valid, f"Op has non-constant padding tensor: {op.inputs[1].values}" + @staticmethod + def constraint_pad_output_shape(op): + "Shape of output tensor must equal to size of input tensor plus padding" + input_shape = op.inputs[0].shape + expected_output_shape = op.outputs[0].shape + pad_tensor = op.inputs[1].values + actual_output_shape = input_shape + pad_tensor.T[0] + pad_tensor.T[1] + valid = np.array_equal(actual_output_shape, expected_output_shape) + return valid, f"Op has wrong output tensor shape: {expected_output_shape}, has shape: {actual_output_shape}" + @staticmethod def constraint_stridedslice_inputs_const(op): "Begin, End and Stride Input tensors must be constant" -- cgit v1.2.1