MLBEDSW-7709: MLCE: Crash when rewriting split op

- A crash occurred due to NoneType subscriptable error when
rewriting a Slice op. The reason was that the Size tensor did
not contain any data.

- Added constraint pushing the Slice operator to the CPU if
begin or size tensor are empty.

- Added test to supported operators
- Updated SUPPORTED_OPS.md

Change-Id: Ide204cae24e5871f0e6ae1fdc98ac68d0ce4d3ae
Signed-off-by: Johan Alfven <johan.alfven@arm.com>
diff --git a/SUPPORTED_OPS.md b/SUPPORTED_OPS.md
index fdceb43..5258946 100644
--- a/SUPPORTED_OPS.md
+++ b/SUPPORTED_OPS.md
@@ -19,7 +19,7 @@
 # Supported Ops
 
 This file was automatically generated by Vela using the `--supported-ops-report` parameter.  
-Vela version: `3.8.1.dev3+gc66541d`
+Vela version: `3.8.1.dev7+g0f09dd2`
 
 This file complies with
 [**Gitiles Markdown syntax**](https://github.com/google/gitiles/blob/master/Documentation/markdown.md)
@@ -66,7 +66,7 @@
 | RESIZE_NEAREST_NEIGHBOR | [Generic](#tflite-generic-constraints), [Specific](#tflite-resize_nearest_neighbor-constraints) |
 | RSQRT | [Generic](#tflite-generic-constraints), [Specific](#tflite-rsqrt-constraints) |
 | SHAPE | [Generic](#tflite-generic-constraints) |
-| SLICE | [Generic](#tflite-generic-constraints) |
+| SLICE | [Generic](#tflite-generic-constraints), [Specific](#tflite-slice-constraints) |
 | SOFTMAX | [Generic](#tflite-generic-constraints), [Specific](#tflite-softmax-constraints) |
 | SPLIT | [Generic](#tflite-generic-constraints), [Specific](#tflite-split-constraints) |
 | SPLIT_V | [Generic](#tflite-generic-constraints), [Specific](#tflite-split_v-constraints) |
@@ -328,6 +328,12 @@
 - IFM and OFM data types must match
 - IFM must be int8
 
+### TFLite SLICE Constraints
+
+This is a list of constraints that the SLICE operator must satisfy in order to be scheduled on the NPU.
+
+- Begin and Size Input tensors must be constant
+
 ### TFLite SOFTMAX Constraints
 
 This is a list of constraints that the SOFTMAX operator must satisfy in order to be scheduled on the NPU.
diff --git a/ethosu/vela/test/test_tflite_supported_operators.py b/ethosu/vela/test/test_tflite_supported_operators.py
index cbad171..6f3553d 100644
--- a/ethosu/vela/test/test_tflite_supported_operators.py
+++ b/ethosu/vela/test/test_tflite_supported_operators.py
@@ -675,3 +675,20 @@
     # Test not supported op (int16)
     op = testutil.create_elemwise_op(Op.Rsqrt, "op", [1, 8, 8, 8], [1, 8, 8, 8], [1, 8, 8, 8], datatype=DataType.int16)
     assert not support.is_operator_supported(op)
+
+
+def test_constraint_slice_inputs_const():
+    # Begin and Size tensor cannot be non-const tensors
+    # Test not supported op
+    ifm = Tensor([3, 1, 256], DataType.int8, "in")
+    begin = Tensor([3], DataType.int32, "begin")
+    size = Tensor([3], DataType.int32, "size")
+    ofm = Tensor([1, 1, 256], DataType.int8, "size")
+    op = testutil.create_op(Op.Slice, [ifm, begin, size], ofm)
+    assert not support.is_operator_supported(op)
+    # Test supported op
+    begin = create_const_tensor("begin", [3], DataType.int32, [0, 0, 0])
+    size = create_const_tensor("size", [3], DataType.int32, [2, 1, 256])
+    op.set_input_tensor(begin, 1)
+    op.set_input_tensor(begin, 2)
+    assert support.is_operator_supported(op)
diff --git a/ethosu/vela/tflite_supported_operators.py b/ethosu/vela/tflite_supported_operators.py
index a24eebc..f965d2b 100644
--- a/ethosu/vela/tflite_supported_operators.py
+++ b/ethosu/vela/tflite_supported_operators.py
@@ -331,6 +331,9 @@
         # Rsqrt specific checks
         self.specific_constraints[Op.Rsqrt].append(TFLiteSupportedOperators.constraint_rsqrt_input_int8)
 
+        # Slice specific checks:
+        self.specific_constraints[Op.Slice].append(TFLiteSupportedOperators.constraint_slice_inputs_const)
+
     def is_operator_supported(self, op):
         ext_type = optype_to_builtintype(op.type)
         if op.type not in TFLiteSupportedOperators.supported_operators:
@@ -942,3 +945,18 @@
         ifm_dtype = op.ifm.dtype
         valid = ifm_dtype == DataType.int8
         return valid, f"Op has ifm_dtype={ifm_dtype}"
+
+    @staticmethod
+    def constraint_slice_inputs_const(op):
+        "Begin and Size Input tensors must be constant"
+        valid = True
+        extra = []
+        _, begin, sizes = op.inputs
+        if begin.values is None:
+            valid = False
+            extra.append(f"Begin tensor '{begin.name}'")
+        if sizes.values is None:
+            valid = False
+            extra.append(f"Size tensor '{sizes.name}'")
+        extra = ", ".join(extra)
+        return valid, f"Op has non-constant tensors: {extra}"