TOSA: Support for TABLE operator (int8)

Added support to map TABLE operator to LUT.
Limitations:
-Only supported for int8
-TABLE input must be constant

This also adds the support for TFLite legalisation of
Tanh/Sigmoid (int8/uint8).

Signed-off-by: Patrik Gustavsson <patrik.gustavsson@arm.com>
Change-Id: I1a95f61fb02fdd42c4a690494418cc0765c8b275
diff --git a/ethosu/vela/tosa_supported_operators.py b/ethosu/vela/tosa_supported_operators.py
index a4f822e..98df27e 100644
--- a/ethosu/vela/tosa_supported_operators.py
+++ b/ethosu/vela/tosa_supported_operators.py
@@ -42,7 +42,7 @@
     binary_elem_wise_add_mul_sub = set((Op.Add, Op.Mul, Op.RescaleMul, Op.Sub,))
     type_conversion_ops = set((Op.Rescale,))
     relu_ops = set((Op.Clamp, Op.ReluN,))
-    activation_ops = relu_ops
+    activation_ops = relu_ops | set((Op.Table,))
     pad_ops = set((Op.Pad,))
 
     npu_post_ops = activation_ops
@@ -68,6 +68,8 @@
 
         self.specific_constraints[Op.Transpose].append(TosaSupportedOperators.constraint_ifm_producer)
         self.specific_constraints[Op.Pad].append(TosaSupportedOperators.constraint_padding_producer)
+        self.specific_constraints[Op.Table].append(TosaSupportedOperators.constraint_table_dtype)
+        self.specific_constraints[Op.Table].append(TosaSupportedOperators.constraint_table_producer)
 
         # Depthwise Conv specific checks:
         for op_type in TosaSupportedOperators.depthwise_convolution_ops:
@@ -200,3 +202,23 @@
             )
             return valid, extra
         return True, "Op has depth_multiplier=1"
+
+    # TODO Table operator support limited to int8 for now.
+    # For TFLite it is assumed to be constant.
+    @staticmethod
+    def constraint_table_dtype(op):
+        "Only supported is int8"
+        valid = True
+        tensors = [op.ifm, op.ofm, op.inputs[1]]
+        for tens in tensors:
+            if tens.dtype != DataType.int8:
+                valid = False
+        return valid, "Table operator with non int8 tensor"
+
+    # TODO limit table to be constant data for now.
+    # Can it be non-constant?
+    @staticmethod
+    def constraint_table_producer(op):
+        "Input must be constant data"
+        valid = op.inputs[1].ops and op.inputs[1].ops[0].type == Op.Const
+        return valid, "Table Op with non-constant table input"