IVGCVSW-3013 Add unit tests for QSymm16 LSTM

* Add unit tests for QSymm16 LSTM
* Update supportedTypes in WorkloadData & RefLayerSupport with
  DataType::QuantisedSymm16

Change-Id: I1a2627b11b707d68d7d7002f63b985f9571ee177
Signed-off-by: Conor Kennedy <conor.kennedy@arm.com>
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index 61e0d40..2cf9937 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -862,7 +862,9 @@
     ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "LstmQueueDescriptor", 2, "output");
 
     std::vector<DataType> supportedTypes = {
+        DataType::Float16,
         DataType::Float32,
+        DataType::QuantisedSymm16
     };
 
     ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp
index 525ac17..e505b56 100644
--- a/src/backends/backendsCommon/test/LayerTests.cpp
+++ b/src/backends/backendsCommon/test/LayerTests.cpp
@@ -1019,13 +1019,13 @@
     boost::multi_array<float, 2> expectedOutput = MakeTensor<float, 2>(outputDesc, std::vector<float>(
             {-0.36444446f, -0.00352185f, 0.12886585f, -0.05163646f,
              -0.42734814f, -0.00478661f,  0.13455015f, -0.03560682f}));
-    return LstmLayerWithCifgWithPeepholeNoProjectionTestImpl(
+    return LstmLayerWithCifgWithPeepholeNoProjectionTestImpl<armnn::DataType::Float32>(
         workloadFactory, memoryManager, input, expectedOutput);
 }
 
 LayerTestResult<float, 2> LstmLayerFloat32NoCifgWithPeepholeWithProjectionTest(
-        armnn::IWorkloadFactory& workloadFactory,
-        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
 {
     armnn::TensorInfo inputDesc({ 2, 5 }, armnn::DataType::Float32);
     boost::multi_array<float, 2> input = MakeTensor<float, 2>(inputDesc, std::vector<float>(
@@ -1041,7 +1041,8 @@
              -0.0186926f,   0.0193662f,   -0.0115437f,  0.00422612f,  -0.0345232f,
              0.00223253f,   -0.00957321f, 0.0210624f,   0.013331f,    0.0150954f,
              0.02168f}));
-    return LstmLayerNoCifgWithPeepholeWithProjectionTestImpl(workloadFactory, memoryManager, input, expectedOutput);
+    return LstmLayerNoCifgWithPeepholeWithProjectionTestImpl<armnn::DataType::Float32>(
+        workloadFactory, memoryManager, input, expectedOutput);
 }
 
 LayerTestResult<float, 2> LstmLayerFloat32NoCifgNoPeepholeNoProjectionTest(
@@ -1058,10 +1059,110 @@
             {{-0.02973187f, 0.1229473f,   0.20885126f, -0.15358765f,
               -0.0185422f,   0.11281417f,  0.24466537f, -0.1826292f}}));
 
-    return LstmNoCifgNoPeepholeNoProjectionTestImpl(
+    return LstmNoCifgNoPeepholeNoProjectionTestImpl<armnn::DataType::Float32>(
         workloadFactory, memoryManager, input, expectedOutput);
 }
 
+LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgNoPeepholeNoProjectionTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    const float qScale = 1.0f;
+    const int32_t qOffset = 0;
+
+    const armnn::DataType datatype = armnn::DataType::QuantisedSymm16;
+    const armnn::DataType constantDatatype = armnn::DataType::QuantisedAsymm8;
+
+    armnn::TensorInfo inputDesc({2, 2}, datatype);
+    boost::multi_array<int16_t , 2> input = MakeTensor<int16_t , 2>(inputDesc, QuantizedVector<int16_t>(qScale, qOffset,
+            std::vector<float>{2., 3., 3., 4.}));
+
+    armnn::TensorInfo outputDesc({2, 4}, datatype);
+    boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
+            qOffset, std::vector<float>({{-0.02973187f, 0.1229473f,   0.20885126f, -0.15358765f,
+                                          -0.0185422f,  0.11281417f,  0.24466537f, -0.1826292f}})));
+
+    return LstmNoCifgNoPeepholeNoProjectionTestImpl<datatype>(
+        workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, constantDatatype);
+
+}
+
+LayerTestResult<int16_t, 2> LstmLayerInt16WithCifgWithPeepholeNoProjectionTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    const float qScale = 1.0f;
+    const int32_t qOffset = 0;
+
+    const armnn::DataType datatype = armnn::DataType::QuantisedSymm16;
+    const armnn::DataType constantDatatype = armnn::DataType::QuantisedAsymm8;
+
+    armnn::TensorInfo inputDesc({ 2, 2 }, datatype);
+    boost::multi_array<int16_t, 2> input = MakeTensor<int16_t, 2>(inputDesc, QuantizedVector<int16_t>(qScale, qOffset,
+            std::vector<float>({ 2., 3., 3., 4. })));
+
+    armnn::TensorInfo outputDesc({ 2, 4 }, datatype);
+    boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
+            qOffset, std::vector<float>(
+            {-0.36444446f, -0.00352185f, 0.12886585f, -0.05163646f,
+             -0.42734814f, -0.00478661f, 0.13455015f, -0.03560682f})));
+
+    return LstmLayerWithCifgWithPeepholeNoProjectionTestImpl<datatype>(
+        workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, constantDatatype);
+}
+
+LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgWithPeepholeWithProjectionTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    const float qScale = 2.0f;
+    const int32_t qOffset = 0;
+
+    const armnn::DataType datatype = armnn::DataType::QuantisedSymm16;
+    const armnn::DataType constantDatatype = armnn::DataType::QuantisedAsymm8;
+
+    armnn::TensorInfo inputDesc({ 2, 5 }, datatype);
+    boost::multi_array<int16_t, 2> input = MakeTensor<int16_t, 2>(inputDesc, QuantizedVector<int16_t>(qScale,
+            qOffset, std::vector<float>(
+            {0.787926f, 0.151646f, 0.071352f, 0.118426f, 0.458058f,
+             0.295743f, 0.544053f, 0.690064f, 0.858138f, 0.497181f})));
+
+    armnn::TensorInfo outputDesc({ 2, 16 }, datatype);
+    boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
+            qOffset, std::vector<float>(
+            {-0.00396806f,  0.029352f,   -0.00279226f, 0.0159977f,  -0.00835576f,
+             -0.0211779f,   0.0283512f,  -0.0114597f,  0.00907307f, -0.0244004f,
+             -0.0152191f,  -0.0259063f,   0.00914318f, 0.00415118f,  0.017147f,
+              0.0134203f,  -0.013869f,    0.0287268f, -0.00334693f,  0.00733398f, -0.0287926f,
+             -0.0186926f,   0.0193662f,  -0.0115437f,  0.00422612f, -0.0345232f,
+              0.00223253f, -0.00957321f,  0.0210624f,  0.013331f,    0.0150954f,   0.02168f})));
+
+    return LstmLayerNoCifgWithPeepholeWithProjectionTestImpl<datatype>(
+        workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, constantDatatype);
+}
+
+LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgNoPeepholeNoProjectionInt16ConstantTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    const float qScale = 1.0f;
+    const int32_t qOffset = 0;
+
+    const armnn::DataType datatype = armnn::DataType::QuantisedSymm16; // datatype & constants set to QSymm16
+
+    armnn::TensorInfo inputDesc({2, 2}, datatype);
+    boost::multi_array<int16_t , 2> input = MakeTensor<int16_t , 2>(inputDesc, QuantizedVector<int16_t>(qScale,
+            qOffset, std::vector<float>{2., 3., 3., 4.}));
+
+    armnn::TensorInfo outputDesc({2, 4}, datatype);
+    boost::multi_array<int16_t, 2> expectedOutput = MakeTensor<int16_t, 2>(outputDesc, QuantizedVector<int16_t>(qScale,
+            qOffset, std::vector<float>({{-0.02973187f, 0.1229473f,   0.20885126f, -0.15358765f,
+                                          -0.0185422f,  0.11281417f,  0.24466537f, -0.1826292f}})));
+
+    return LstmNoCifgNoPeepholeNoProjectionTestImpl<datatype>(
+        workloadFactory, memoryManager, input, expectedOutput, qScale, qOffset, datatype);
+}
+
 LayerTestResult<float,3> MergerTest(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index 762e581..0e8025e 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -1140,6 +1140,22 @@
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
 
+LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgNoPeepholeNoProjectionTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+LayerTestResult<int16_t, 2> LstmLayerInt16WithCifgWithPeepholeNoProjectionTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgWithPeepholeWithProjectionTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+LayerTestResult<int16_t, 2> LstmLayerInt16NoCifgNoPeepholeNoProjectionInt16ConstantTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
 LayerTestResult<float, 4> SimpleConvertFp16ToFp32Test(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
diff --git a/src/backends/backendsCommon/test/LstmTestImpl.hpp b/src/backends/backendsCommon/test/LstmTestImpl.hpp
index e300a52..dae9c8a 100644
--- a/src/backends/backendsCommon/test/LstmTestImpl.hpp
+++ b/src/backends/backendsCommon/test/LstmTestImpl.hpp
@@ -16,11 +16,16 @@
 #include <backendsCommon/CpuTensorHandle.hpp>
 #include <backendsCommon/WorkloadFactory.hpp>
 
-LayerTestResult<float, 2> LstmNoCifgNoPeepholeNoProjectionTestImpl(
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2>
+LstmNoCifgNoPeepholeNoProjectionTestImpl(
         armnn::IWorkloadFactory& workloadFactory,
         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
-        const boost::multi_array<float, 2>& input,
-        const boost::multi_array<float, 2>& outputExpected)
+        const boost::multi_array<T, 2>& input,
+        const boost::multi_array<T, 2>& outputExpected,
+        float qScale = 0.0f,
+        int32_t qOffset = 0,
+        armnn::DataType constantDataType = armnn::DataType::Float32)
 {
     unsigned int batchSize = boost::numeric_cast<unsigned int>(input.shape()[0]);
     unsigned int inputSize = boost::numeric_cast<unsigned int>(input.shape()[1]);
@@ -28,19 +33,16 @@
     // cellSize and outputSize have the same size when there is no projection.
     unsigned numUnits = outputSize;
 
+    armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, ArmnnType,  qScale, qOffset );
+    armnn::TensorInfo cellStateInTensorInfo({batchSize , numUnits}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize}, ArmnnType, qScale, qOffset);
 
-    armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo cellStateInTensorInfo({batchSize , numUnits}, armnn::DataType::Float32);
-    armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize}, armnn::DataType::Float32);
+    armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 4}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
 
-
-    armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 4}, armnn::DataType::Float32);
-    armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits}, armnn::DataType::Float32);
-    armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
-
-
-    LayerTestResult<float, 2> ret(outputTensorInfo);
+    LayerTestResult<T, 2> ret(outputTensorInfo);
 
     std::vector<float> inputVector;
     inputVector.assign(input.data(), input.data() + (batchSize * inputSize));
@@ -91,9 +93,9 @@
     AddOutputToWorkload(data, info, cellStateOutTensorInfo, cellStateOutHandle.get());
     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
 
-    armnn::TensorInfo tensorInfo4({numUnits}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfo8({numUnits, 2}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfo16({numUnits, 4}, armnn::DataType::Float32);
+    armnn::TensorInfo tensorInfo4({numUnits}, constantDataType , qScale, qOffset);
+    armnn::TensorInfo tensorInfo8({numUnits, 2}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfo16({numUnits, 4}, constantDataType, qScale, qOffset);
 
     auto inputToInputWeights = MakeTensor<float, 2>(tensorInfo8, {-0.45018822f, -0.02338299f, -0.0870589f,
                                                                   -0.34550029f, 0.04266912f, -0.15680569f,
@@ -191,14 +193,12 @@
     data.m_CellBias = &cellBiasTensor;
     data.m_OutputGateBias = &outputGateBiasTensor;
 
-
     // Flags to set test configuration
     data.m_Parameters.m_ActivationFunc = 4;
     data.m_Parameters.m_CifgEnabled = false;
     data.m_Parameters.m_PeepholeEnabled = false;
     data.m_Parameters.m_ProjectionEnabled = false;
 
-
     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateLstm(data, info);
     inputHandle->Allocate();
     outputStateInHandle->Allocate();
@@ -220,29 +220,32 @@
     return ret;
 }
 
-
-LayerTestResult<float, 2>
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2>
 LstmLayerNoCifgWithPeepholeWithProjectionTestImpl(armnn::IWorkloadFactory& workloadFactory,
                                                   const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
-                                                  const boost::multi_array<float, 2>& input,
-                                                  const boost::multi_array<float, 2>& outputExpected)
+                                                  const boost::multi_array<T, 2>& input,
+                                                  const boost::multi_array<T, 2>& outputExpected,
+                                                  float qScale = 0.0f,
+                                                  int32_t qOffset = 0,
+                                                  armnn::DataType constantDataType = armnn::DataType::Float32)
 {
     unsigned int batchSize = 2;
     unsigned int outputSize = 16;
     unsigned int inputSize = 5;
     unsigned numUnits = 20;
 
-    armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo cellStateInTensorInfo({batchSize , numUnits}, armnn::DataType::Float32);
-    armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize}, armnn::DataType::Float32);
+    armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo cellStateInTensorInfo({batchSize , numUnits}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize}, ArmnnType, qScale, qOffset);
 
     // Scratch buffer size without CIFG [batchSize, numUnits * 4]
-    armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 4}, armnn::DataType::Float32);
-    armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits}, armnn::DataType::Float32);
-    armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
+    armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 4}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
 
-    LayerTestResult<float, 2> ret(outputTensorInfo);
+    LayerTestResult<T, 2> ret(outputTensorInfo);
 
     std::vector<float> inputVector;
     inputVector.assign(input.data(), input.data() + (batchSize * inputSize));
@@ -292,11 +295,11 @@
     AddOutputToWorkload(data, info, cellStateOutTensorInfo, cellStateOutHandle.get());
     AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
 
-    armnn::TensorInfo tensorInfo16({outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfo20({numUnits}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, armnn::DataType::Float32);
+    armnn::TensorInfo tensorInfo16({outputSize}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfo20({numUnits}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfo20x5({numUnits, inputSize}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfo20x16({numUnits, outputSize}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfo16x20({outputSize, numUnits}, constantDataType, qScale, qOffset);
 
     auto inputToInputWeights =
             MakeTensor<float, 2>(tensorInfo20x5, {0.021393683f,0.06124551f,  0.046905167f,-0.014657677f,-0.03149463f,
@@ -931,12 +934,15 @@
 
 }
 
-
-LayerTestResult<float, 2> LstmLayerWithCifgWithPeepholeNoProjectionTestImpl(
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 2> LstmLayerWithCifgWithPeepholeNoProjectionTestImpl(
         armnn::IWorkloadFactory& workloadFactory,
         const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
-        const boost::multi_array<float, 2>& input,
-        const boost::multi_array<float, 2>& outputExpected)
+        const boost::multi_array<T, 2>& input,
+        const boost::multi_array<T, 2>& outputExpected,
+        float qScale = 0.0f,
+        int32_t qOffset = 0,
+        armnn::DataType constantDataType = armnn::DataType::Float32)
 {
     bool cifgEnabled = true;
     bool peepholeEnabled = true;
@@ -950,15 +956,15 @@
     const unsigned int cellSize = outputSize;
 
     // Decide the shape of all input tensors
-    armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo outputStateInTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo cellStateInTensorInfo({batchSize, cellSize}, armnn::DataType::Float32);
+    armnn::TensorInfo inputTensorInfo({batchSize , inputSize}, ArmnnType, qScale, qOffset); // change to ArmnnType
+    armnn::TensorInfo outputStateInTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo cellStateInTensorInfo({batchSize, cellSize}, ArmnnType, qScale, qOffset);
 
     unsigned int scratchBufferSize = cifgEnabled ? cellSize * 3 : cellSize * 4;
-    armnn::TensorInfo scratchBufferTensorInfo({batchSize, scratchBufferSize}, armnn::DataType::Float32);
-    armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo cellStateOutTensorInfo({batchSize, cellSize}, armnn::DataType::Float32);
-    armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, armnn::DataType::Float32);
+    armnn::TensorInfo scratchBufferTensorInfo({batchSize, scratchBufferSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo cellStateOutTensorInfo({batchSize, cellSize}, ArmnnType, qScale, qOffset);
+    armnn::TensorInfo outputTensorInfo({batchSize, outputSize}, ArmnnType, qScale, qOffset);
 
     // List of inputs
     std::vector<float> inputData;
@@ -974,9 +980,9 @@
 
     // Prepare all the weights in the descriptor for LSTM
     armnn::LstmQueueDescriptor data;
-    armnn::TensorInfo tensorInfoInput({cellSize, inputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfoOutput({cellSize, outputSize}, armnn::DataType::Float32);
-    armnn::TensorInfo tensorInfoNumUnits({cellSize}, armnn::DataType::Float32);
+    armnn::TensorInfo tensorInfoInput({cellSize, inputSize}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfoOutput({cellSize, outputSize}, constantDataType, qScale, qOffset);
+    armnn::TensorInfo tensorInfoNumUnits({cellSize}, constantDataType, qScale, qOffset);
 
     auto inputToCellWeights = MakeTensor<float, 2>(tensorInfoInput,
                                                      {-0.49770179f, -0.27711356f, -0.09624726f, 0.05100781f,
@@ -1074,24 +1080,24 @@
     // List of outputs
     std::vector<float> scratchBufferVector(batchSize * scratchBufferSize, 0.f);
     auto scratchBufferTensor = MakeTensor<float,2>(scratchBufferTensorInfo, scratchBufferVector);
-    LayerTestResult<float, 2> ret0(scratchBufferTensorInfo);
+    LayerTestResult<T, 2> ret0(scratchBufferTensorInfo);
 
     // Output state for a certain time step
     std::vector<float> outputStateOutVector(batchSize * outputSize, 0.f);
     auto outputStateOutTensor = MakeTensor<float,2>(outputStateOutTensorInfo, outputStateOutVector);
-    LayerTestResult<float, 2> ret1(outputStateOutTensorInfo);
+    LayerTestResult<T, 2> ret1(outputStateOutTensorInfo);
 
     // Cell state for a certain time step
     std::vector<float> cellStateOutVector(batchSize * cellSize, 0.f);
     auto cellStateOutTensor = MakeTensor<float,2>(cellStateOutTensorInfo, cellStateOutVector);
-    LayerTestResult<float, 2> ret2(cellStateOutTensorInfo);
+    LayerTestResult<T, 2> ret2(cellStateOutTensorInfo);
 
     // Output for a certain time step
     std::vector<float> outputVector(batchSize * outputSize, 0.f);
     auto outputTensor = MakeTensor<float, 2>(outputTensorInfo, outputVector);
     std::vector<float> outputData;
     outputData.assign(outputExpected.data(), outputExpected.data() + batchSize*outputSize);
-    LayerTestResult<float, 2> ret3(outputTensorInfo);
+    LayerTestResult<T, 2> ret3(outputTensorInfo);
     ret3.outputExpected = MakeTensor<float, 2>(outputTensorInfo, outputData);
 
     // Prepare the inputs and outputs for the workload
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index 67c13c3..8eded84 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -616,7 +616,8 @@
     bool supported = true;
 
     std::array<DataType,2> supportedTypes = {
-        DataType::Float32
+        DataType::Float32,
+        DataType::QuantisedSymm16
     };
 
     supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported,
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp
index 04b215a..b260002 100644
--- a/src/backends/reference/test/RefLayerTests.cpp
+++ b/src/backends/reference/test/RefLayerTests.cpp
@@ -458,6 +458,15 @@
 ARMNN_AUTO_TEST_CASE(LstmLayerFloat32NoCifgWithPeepholeWithProjection,
                      LstmLayerFloat32NoCifgWithPeepholeWithProjectionTest)
 
+ARMNN_AUTO_TEST_CASE(LstmLayerInt16NoCifgNoPeepholeNoProjection,
+                     LstmLayerInt16NoCifgNoPeepholeNoProjectionTest)
+ARMNN_AUTO_TEST_CASE(LstmLayerInt16WithCifgWithPeepholeNoProjection,
+                     LstmLayerInt16WithCifgWithPeepholeNoProjectionTest)
+ARMNN_AUTO_TEST_CASE(LstmLayerInt16NoCifgWithPeepholeWithProjection,
+                     LstmLayerInt16NoCifgWithPeepholeWithProjectionTest)
+ARMNN_AUTO_TEST_CASE(LstmLayerInt16NoCifgNoPeepholeNoProjectionInt16Constant,
+                     LstmLayerInt16NoCifgNoPeepholeNoProjectionInt16ConstantTest)
+
 // Convert from Float16 to Float32
 ARMNN_AUTO_TEST_CASE(SimpleConvertFp16ToFp32, SimpleConvertFp16ToFp32Test)
 // Convert from Float32 to Float16