Add quantized implementation for HEATMAP_MAX_KEYPOINT.

Bug: 113562572
Test: NeuralNetworksTest_static
Change-Id: I47c76ae34ce9013fcf09fa11fc1fb6df41477ecd
diff --git a/common/operations/HeatmapMaxKeypoint.cpp b/common/operations/HeatmapMaxKeypoint.cpp
index 3ebc98f..0e3e976 100644
--- a/common/operations/HeatmapMaxKeypoint.cpp
+++ b/common/operations/HeatmapMaxKeypoint.cpp
@@ -175,17 +175,49 @@
                                          outputKeypointShape, fpAtol, fpRtol);
 }
 
+inline bool heatmapMaxKeypointQuant(const uint8_t* heatmap, const Shape& heatmapShape,
+                                    const uint16_t* boxes, const Shape& boxesShape, bool layout,
+                                    uint8_t* outputScoreData, const Shape& outputScoreShape,
+                                    uint16_t* outputKeypointData, const Shape& outputKeypointShape,
+                                    float fpAtol, float fpRtol) {
+    std::vector<float> heatmap_float32(getNumberOfElements(heatmapShape));
+    convertQuantToFloat32(heatmap, heatmapShape.scale, heatmapShape.offset, &heatmap_float32);
+    std::vector<float> boxes_float32(getNumberOfElements(boxesShape));
+    convertQuantToFloat32(boxes, boxesShape.scale, boxesShape.offset, &boxes_float32);
+    std::vector<float> outputScore_float32(getNumberOfElements(outputScoreShape));
+    std::vector<float> outputKeypoint_float32(getNumberOfElements(outputKeypointShape));
+    NN_RET_CHECK(heatmapMaxKeypointFloat32(
+            heatmap_float32.data(), heatmapShape, boxes_float32.data(), boxesShape, layout,
+            outputScore_float32.data(), outputScoreShape, outputKeypoint_float32.data(),
+            outputKeypointShape, fpAtol, fpRtol));
+    convertFloat32ToQuant(outputScore_float32, outputScoreShape.scale, outputScoreShape.offset,
+                          outputScoreData);
+    convertFloat32ToQuant(outputKeypoint_float32, outputKeypointShape.scale,
+                          outputKeypointShape.offset, outputKeypointData);
+    return true;
+}
+
 }  // namespace
 
 bool validate(const IOperationValidationContext* context) {
     NN_RET_CHECK_EQ(context->getNumInputs(), kNumInputs);
     NN_RET_CHECK_EQ(context->getNumOutputs(), kNumOutputs);
+    std::vector<OperandType> inExpectedTypes;
+    std::vector<OperandType> outExpectedTypes;
     auto inputType = context->getInputType(kHeatmapTensor);
-    NN_RET_CHECK(inputType == OperandType::TENSOR_FLOAT16 ||
-                 inputType == OperandType::TENSOR_FLOAT32)
-            << "Unsupported tensor type for operation " << kOperationName;
-    NN_RET_CHECK(validateInputTypes(context, {inputType, inputType, OperandType::BOOL}));
-    NN_RET_CHECK(validateOutputTypes(context, {inputType, inputType}));
+    if (inputType == OperandType::TENSOR_FLOAT32 || inputType == OperandType::TENSOR_FLOAT16) {
+        inExpectedTypes = {inputType, inputType, OperandType::BOOL};
+        outExpectedTypes = {inputType, inputType};
+    } else if (inputType == OperandType::TENSOR_QUANT8_ASYMM) {
+        inExpectedTypes = {OperandType::TENSOR_QUANT8_ASYMM, OperandType::TENSOR_QUANT16_ASYMM,
+                           OperandType::BOOL};
+        outExpectedTypes = {OperandType::TENSOR_QUANT8_ASYMM, OperandType::TENSOR_QUANT16_ASYMM};
+    } else {
+        LOG(ERROR) << "Unsupported input tensor type for operation " << kOperationName;
+        return false;
+    }
+    NN_RET_CHECK(validateInputTypes(context, inExpectedTypes));
+    NN_RET_CHECK(validateOutputTypes(context, outExpectedTypes));
     return validateHalVersion(context, HalVersion::V1_2);
 }
 
@@ -205,18 +237,21 @@
     NN_RET_CHECK_EQ(getSizeOfDimension(boxesShape, 0), numBoxes);
     NN_RET_CHECK_EQ(boxInfoLength, 4);
 
+    if (heatmapShape.type == OperandType::TENSOR_QUANT8_ASYMM) {
+        NN_RET_CHECK_EQ(boxesShape.scale, 0.125f);
+        NN_RET_CHECK_EQ(boxesShape.offset, 0);
+    }
+
     Shape outputScore = context->getOutputShape(kOutputScoreTensor);
     outputScore.type = heatmapShape.type;
     outputScore.dimensions = {numBoxes, numKeypoints};
-    outputScore.offset = heatmapShape.offset;
-    outputScore.scale = heatmapShape.scale;
     NN_RET_CHECK(context->setOutputShape(kOutputScoreTensor, outputScore));
 
     Shape outputKeypoint = context->getOutputShape(kOutputKeypointTensor);
     outputKeypoint.type = boxesShape.type;
     outputKeypoint.dimensions = {numBoxes, numKeypoints, 2};
-    outputKeypoint.offset = boxesShape.offset;
-    outputKeypoint.scale = boxesShape.scale;
+    outputKeypoint.offset = 0;
+    outputKeypoint.scale = 0.125f;
     NN_RET_CHECK(context->setOutputShape(kOutputKeypointTensor, outputKeypoint));
     return true;
 }
@@ -258,6 +293,17 @@
                                              context->getOutputShape(kOutputKeypointTensor), 1e-5f,
                                              1e-5f);
         }
+        case OperandType::TENSOR_QUANT8_ASYMM: {
+            return heatmapMaxKeypointQuant(
+                    context->getInputBuffer<uint8_t>(kHeatmapTensor),
+                    context->getInputShape(kHeatmapTensor),
+                    context->getInputBuffer<uint16_t>(kBoxesTensor),
+                    context->getInputShape(kBoxesTensor), layout,
+                    context->getOutputBuffer<uint8_t>(kOutputScoreTensor),
+                    context->getOutputShape(kOutputScoreTensor),
+                    context->getOutputBuffer<uint16_t>(kOutputKeypointTensor),
+                    context->getOutputShape(kOutputKeypointTensor), 1e-5f, 1e-5f);
+        }
         default:
             NN_RET_CHECK_FAIL() << "Unsupported tensor type for operation " << kOperationName;
     }
diff --git a/runtime/include/NeuralNetworks.h b/runtime/include/NeuralNetworks.h
index 6a240fa..2614c76 100644
--- a/runtime/include/NeuralNetworks.h
+++ b/runtime/include/NeuralNetworks.h
@@ -2672,7 +2672,9 @@
      * A valid bounding box should satisfy x1 <= x2 and y1 <= y2.
      *
      * Supported tensor {@link OperandCode}:
+     * * {@link ANEURALNETWORKS_TENSOR_FLOAT16}
      * * {@link ANEURALNETWORKS_TENSOR_FLOAT32}
+     * * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
      *
      * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
      * With the default data layout NHWC, the data is stored in the order of:
@@ -2685,7 +2687,10 @@
      *      specifying the heatmaps, the height and width of heatmaps should
      *      be the same, and must be greater than or equal to 2.
      * * 1: A 2-D Tensor of shape [num_boxes, 4], specifying the bounding boxes,
-     *      each with format [x1, y1, x2, y2].
+     *      each with format [x1, y1, x2, y2]. For input0 of type
+     *      {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}, this tensor should
+     *      be of {@link ANEURALNETWORKS_TENSOR_QUANT16_ASYMM}, with zeroPoint
+     *      of 0 and scale of 0.125.
      * * 2: An {@link ANEURALNETWORKS_BOOL} scalar, set to true to specify
      *      NCHW data layout for input0. Set to false for NHWC.
      *
diff --git a/runtime/test/TestValidateOperations.cpp b/runtime/test/TestValidateOperations.cpp
index 9bf25787..e7d73fa 100644
--- a/runtime/test/TestValidateOperations.cpp
+++ b/runtime/test/TestValidateOperations.cpp
@@ -1975,14 +1975,15 @@
                      ANEURALNETWORKS_FLOAT32);
 }
 
-void heatmapMaxKeypointOpTest(int32_t operandCode) {
+void heatmapMaxKeypointOpTest(int32_t heatmapOperandCode, int32_t roiOperandCode) {
     uint32_t heatmapDim[] = {6, 4, 4, 1}, boxDim[] = {6, 4}, outScoreDim[] = {6, 1},
              outKeypointDim[] = {6, 1, 2};
     OperationTestBase heatmapMaxKeypointTest(
             ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT,
-            {getOpType(operandCode, 4, heatmapDim), getOpType(operandCode, 2, boxDim),
+            {getOpType(heatmapOperandCode, 4, heatmapDim), getOpType(roiOperandCode, 2, boxDim),
              getOpType(ANEURALNETWORKS_BOOL)},
-            {getOpType(operandCode, 2, outScoreDim), getOpType(operandCode, 3, outKeypointDim)});
+            {getOpType(heatmapOperandCode, 2, outScoreDim),
+             getOpType(roiOperandCode, 3, outKeypointDim)});
 
     EXPECT_TRUE(heatmapMaxKeypointTest.testMutatingInputOperandCode());
     EXPECT_TRUE(heatmapMaxKeypointTest.testMutatingInputOperandCounts());
@@ -1991,11 +1992,16 @@
 }
 
 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_float16) {
-    heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT16);
+    heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT16, ANEURALNETWORKS_TENSOR_FLOAT16);
 }
 
 TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_float32) {
-    heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT32);
+    heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_FLOAT32, ANEURALNETWORKS_TENSOR_FLOAT32);
+}
+
+TEST(OperationValidationTest, HEATMAP_MAX_KEYPOINT_quant) {
+    heatmapMaxKeypointOpTest(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,
+                             ANEURALNETWORKS_TENSOR_QUANT16_ASYMM);
 }
 
 void groupedConvOpTest(int32_t operandCode) {
diff --git a/runtime/test/generated/all_generated_V1_2_vts_tests.cpp b/runtime/test/generated/all_generated_V1_2_vts_tests.cpp
index eecfda6..28af6fe 100644
--- a/runtime/test/generated/all_generated_V1_2_vts_tests.cpp
+++ b/runtime/test/generated/all_generated_V1_2_vts_tests.cpp
@@ -22670,6 +22670,21 @@
 }
 
 
+TEST_F(NeuralnetworksHidlTest, heatmap_max_keypoint_nhwc_quant8) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_nhwc_quant8,
+                           heatmap_max_keypoint::is_ignored_nhwc_quant8,
+                           heatmap_max_keypoint::get_examples_nhwc_quant8());
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_nhwc_quant8) {
+  const Model model = heatmap_max_keypoint::createTestModel_nhwc_quant8();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_nhwc_quant8());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
 TEST_F(NeuralnetworksHidlTest, heatmap_max_keypoint_nchw_2) {
   generated_tests::Execute(device,
                            heatmap_max_keypoint::createTestModel_nchw_2,
@@ -22715,6 +22730,21 @@
 }
 
 
+TEST_F(NeuralnetworksHidlTest, heatmap_max_keypoint_nchw_quant8) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_nchw_quant8,
+                           heatmap_max_keypoint::is_ignored_nchw_quant8,
+                           heatmap_max_keypoint::get_examples_nchw_quant8());
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_nchw_quant8) {
+  const Model model = heatmap_max_keypoint::createTestModel_nchw_quant8();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_nchw_quant8());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
 #ifdef NN_TEST_DYNAMIC_OUTPUT_SHAPE
 TEST_F(DynamicOutputShapeTest, heatmap_max_keypoint_dynamic_output_shape_nhwc_2) {
   generated_tests::Execute(device,
@@ -22767,6 +22797,23 @@
 
 #endif
 #ifdef NN_TEST_DYNAMIC_OUTPUT_SHAPE
+TEST_F(DynamicOutputShapeTest, heatmap_max_keypoint_dynamic_output_shape_nhwc_quant8) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_dynamic_output_shape_nhwc_quant8,
+                           heatmap_max_keypoint::is_ignored_dynamic_output_shape_nhwc_quant8,
+                           heatmap_max_keypoint::get_examples_dynamic_output_shape_nhwc_quant8(), true);
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_dynamic_output_shape_nhwc_quant8) {
+  const Model model = heatmap_max_keypoint::createTestModel_dynamic_output_shape_nhwc_quant8();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_dynamic_output_shape_nhwc_quant8());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
+#endif
+#ifdef NN_TEST_DYNAMIC_OUTPUT_SHAPE
 TEST_F(DynamicOutputShapeTest, heatmap_max_keypoint_dynamic_output_shape_nchw_2) {
   generated_tests::Execute(device,
                            heatmap_max_keypoint::createTestModel_dynamic_output_shape_nchw_2,
@@ -22817,6 +22864,87 @@
 
 
 #endif
+#ifdef NN_TEST_DYNAMIC_OUTPUT_SHAPE
+TEST_F(DynamicOutputShapeTest, heatmap_max_keypoint_dynamic_output_shape_nchw_quant8) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_dynamic_output_shape_nchw_quant8,
+                           heatmap_max_keypoint::is_ignored_dynamic_output_shape_nchw_quant8,
+                           heatmap_max_keypoint::get_examples_dynamic_output_shape_nchw_quant8(), true);
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_dynamic_output_shape_nchw_quant8) {
+  const Model model = heatmap_max_keypoint::createTestModel_dynamic_output_shape_nchw_quant8();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_dynamic_output_shape_nchw_quant8());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
+#endif
+TEST_F(NeuralnetworksHidlTest, heatmap_max_keypoint_nhwc_quant8_2) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_nhwc_quant8_2,
+                           heatmap_max_keypoint::is_ignored_nhwc_quant8_2,
+                           heatmap_max_keypoint::get_examples_nhwc_quant8_2());
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_nhwc_quant8_2) {
+  const Model model = heatmap_max_keypoint::createTestModel_nhwc_quant8_2();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_nhwc_quant8_2());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
+TEST_F(NeuralnetworksHidlTest, heatmap_max_keypoint_nchw_quant8_2) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_nchw_quant8_2,
+                           heatmap_max_keypoint::is_ignored_nchw_quant8_2,
+                           heatmap_max_keypoint::get_examples_nchw_quant8_2());
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_nchw_quant8_2) {
+  const Model model = heatmap_max_keypoint::createTestModel_nchw_quant8_2();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_nchw_quant8_2());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
+#ifdef NN_TEST_DYNAMIC_OUTPUT_SHAPE
+TEST_F(DynamicOutputShapeTest, heatmap_max_keypoint_dynamic_output_shape_nhwc_quant8_2) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_dynamic_output_shape_nhwc_quant8_2,
+                           heatmap_max_keypoint::is_ignored_dynamic_output_shape_nhwc_quant8_2,
+                           heatmap_max_keypoint::get_examples_dynamic_output_shape_nhwc_quant8_2(), true);
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_dynamic_output_shape_nhwc_quant8_2) {
+  const Model model = heatmap_max_keypoint::createTestModel_dynamic_output_shape_nhwc_quant8_2();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_dynamic_output_shape_nhwc_quant8_2());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
+#endif
+#ifdef NN_TEST_DYNAMIC_OUTPUT_SHAPE
+TEST_F(DynamicOutputShapeTest, heatmap_max_keypoint_dynamic_output_shape_nchw_quant8_2) {
+  generated_tests::Execute(device,
+                           heatmap_max_keypoint::createTestModel_dynamic_output_shape_nchw_quant8_2,
+                           heatmap_max_keypoint::is_ignored_dynamic_output_shape_nchw_quant8_2,
+                           heatmap_max_keypoint::get_examples_dynamic_output_shape_nchw_quant8_2(), true);
+}
+
+TEST_F(ValidationTest, heatmap_max_keypoint_dynamic_output_shape_nchw_quant8_2) {
+  const Model model = heatmap_max_keypoint::createTestModel_dynamic_output_shape_nchw_quant8_2();
+  const std::vector<Request> requests = createRequests(heatmap_max_keypoint::get_examples_dynamic_output_shape_nchw_quant8_2());
+  validateModel(model);
+  validateRequests(model, requests);
+}
+
+
+#endif
 // Generated from: instance_normalization.mod.py.
 namespace instance_normalization {
 // Generated instance_normalization test
diff --git a/runtime/test/generated/examples/heatmap_max_keypoint.example.cpp b/runtime/test/generated/examples/heatmap_max_keypoint.example.cpp
index e4a9c6e..416803a 100644
--- a/runtime/test/generated/examples/heatmap_max_keypoint.example.cpp
+++ b/runtime/test/generated/examples/heatmap_max_keypoint.example.cpp
@@ -795,6 +795,59 @@
 return examples_nhwc_float16_2;
 };
 
+std::vector<MixedTypedExample>& get_examples_nhwc_quant8() {
+static std::vector<MixedTypedExample> examples_nhwc_quant8 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4, 4, 4}}, {1, {2, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {147, 189, 177, 129, 226, 193, 192, 198, 204, 183, 211, 147, 174, 131, 195, 199, 145, 151, 217, 136, 224, 193, 180, 168, 164, 208, 183, 217, 186, 157, 155, 197, 194, 134, 179, 154, 224, 166, 169, 217, 216, 174, 224, 201, 182, 192, 212, 202, 179, 169, 141, 147, 180, 149, 178, 203, 217, 217, 148, 186, 198, 141, 157, 167, 219, 134, 221, 162, 208, 215, 187, 195, 185, 213, 152, 153, 204, 162, 165, 139, 128, 157, 158, 205, 162, 185, 176, 204, 221, 146, 192, 140, 195, 175, 184, 178, 176, 227, 174, 194, 226, 134, 138, 194, 194, 219, 195, 151, 168, 165, 145, 163, 176, 226, 175, 177, 184, 146, 203, 157, 132, 151, 170, 183, 166, 135, 199, 208}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4}}, {1, {2, 4, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {102, 89, 101, 95, 99, 107, 93, 80}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {58, 34, 65, 142, 68, 101, 67, 81, 99, 71, 37, 74, 37, 59, 211, 77}}},
+}
+},
+}, // End of an example
+};
+return examples_nhwc_quant8;
+};
+
 std::vector<MixedTypedExample>& get_examples_nchw_2() {
 static std::vector<MixedTypedExample> examples_nchw_2 = {
 // Begin of an example
@@ -954,6 +1007,59 @@
 return examples_nchw_float16_2;
 };
 
+std::vector<MixedTypedExample>& get_examples_nchw_quant8() {
+static std::vector<MixedTypedExample> examples_nchw_quant8 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4, 4, 4}}, {1, {2, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {147, 226, 204, 174, 145, 224, 164, 186, 194, 224, 216, 182, 179, 180, 217, 198, 189, 193, 183, 131, 151, 193, 208, 157, 134, 166, 174, 192, 169, 149, 217, 141, 177, 192, 211, 195, 217, 180, 183, 155, 179, 169, 224, 212, 141, 178, 148, 157, 129, 198, 147, 199, 136, 168, 217, 197, 154, 217, 201, 202, 147, 203, 186, 167, 219, 208, 185, 204, 128, 162, 221, 195, 176, 226, 194, 168, 176, 184, 132, 166, 134, 215, 213, 162, 157, 185, 146, 175, 227, 134, 219, 165, 226, 146, 151, 135, 221, 187, 152, 165, 158, 176, 192, 184, 174, 138, 195, 145, 175, 203, 170, 199, 162, 195, 153, 139, 205, 204, 140, 178, 194, 194, 151, 163, 177, 157, 183, 208}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4}}, {1, {2, 4, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {102, 89, 101, 95, 99, 107, 93, 80}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {58, 34, 65, 142, 68, 101, 67, 81, 99, 71, 37, 74, 37, 59, 211, 77}}},
+}
+},
+}, // End of an example
+};
+return examples_nchw_quant8;
+};
+
 std::vector<MixedTypedExample>& get_examples_dynamic_output_shape_nhwc_2() {
 static std::vector<MixedTypedExample> examples_dynamic_output_shape_nhwc_2 = {
 // Begin of an example
@@ -1113,6 +1219,59 @@
 return examples_dynamic_output_shape_nhwc_float16_2;
 };
 
+std::vector<MixedTypedExample>& get_examples_dynamic_output_shape_nhwc_quant8() {
+static std::vector<MixedTypedExample> examples_dynamic_output_shape_nhwc_quant8 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4, 4, 4}}, {1, {2, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {147, 189, 177, 129, 226, 193, 192, 198, 204, 183, 211, 147, 174, 131, 195, 199, 145, 151, 217, 136, 224, 193, 180, 168, 164, 208, 183, 217, 186, 157, 155, 197, 194, 134, 179, 154, 224, 166, 169, 217, 216, 174, 224, 201, 182, 192, 212, 202, 179, 169, 141, 147, 180, 149, 178, 203, 217, 217, 148, 186, 198, 141, 157, 167, 219, 134, 221, 162, 208, 215, 187, 195, 185, 213, 152, 153, 204, 162, 165, 139, 128, 157, 158, 205, 162, 185, 176, 204, 221, 146, 192, 140, 195, 175, 184, 178, 176, 227, 174, 194, 226, 134, 138, 194, 194, 219, 195, 151, 168, 165, 145, 163, 176, 226, 175, 177, 184, 146, 203, 157, 132, 151, 170, 183, 166, 135, 199, 208}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4}}, {1, {2, 4, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {102, 89, 101, 95, 99, 107, 93, 80}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {58, 34, 65, 142, 68, 101, 67, 81, 99, 71, 37, 74, 37, 59, 211, 77}}},
+}
+},
+}, // End of an example
+};
+return examples_dynamic_output_shape_nhwc_quant8;
+};
+
 std::vector<MixedTypedExample>& get_examples_dynamic_output_shape_nchw_2() {
 static std::vector<MixedTypedExample> examples_dynamic_output_shape_nchw_2 = {
 // Begin of an example
@@ -1272,3 +1431,268 @@
 return examples_dynamic_output_shape_nchw_float16_2;
 };
 
+std::vector<MixedTypedExample>& get_examples_dynamic_output_shape_nchw_quant8() {
+static std::vector<MixedTypedExample> examples_dynamic_output_shape_nchw_quant8 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4, 4, 4}}, {1, {2, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {147, 226, 204, 174, 145, 224, 164, 186, 194, 224, 216, 182, 179, 180, 217, 198, 189, 193, 183, 131, 151, 193, 208, 157, 134, 166, 174, 192, 169, 149, 217, 141, 177, 192, 211, 195, 217, 180, 183, 155, 179, 169, 224, 212, 141, 178, 148, 157, 129, 198, 147, 199, 136, 168, 217, 197, 154, 217, 201, 202, 147, 203, 186, 167, 219, 208, 185, 204, 128, 162, 221, 195, 176, 226, 194, 168, 176, 184, 132, 166, 134, 215, 213, 162, 157, 185, 146, 175, 227, 134, 219, 165, 226, 146, 151, 135, 221, 187, 152, 165, 158, 176, 192, 184, 174, 138, 195, 145, 175, 203, 170, 199, 162, 195, 153, 139, 205, 204, 140, 178, 194, 194, 151, 163, 177, 157, 183, 208}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {2, 4}}, {1, {2, 4, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {102, 89, 101, 95, 99, 107, 93, 80}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {58, 34, 65, 142, 68, 101, 67, 81, 99, 71, 37, 74, 37, 59, 211, 77}}},
+}
+},
+}, // End of an example
+};
+return examples_dynamic_output_shape_nchw_quant8;
+};
+
+std::vector<MixedTypedExample>& get_examples_nhwc_quant8_2() {
+static std::vector<MixedTypedExample> examples_nhwc_quant8_2 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 4, 4, 1}}, {1, {5, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 148, 122, 138, 108, 126, 136, 118, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 148, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 16, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80, 64, 24, 120, 104, 48, 40, 152, 96, 40, 16, 80, 160}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 1}}, {1, {5, 1, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {101, 110, 82, 110, 117}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {66, 68, 94, 77, 71, 76, 139, 47, 77, 16}}},
+}
+},
+}, // End of an example
+};
+return examples_nhwc_quant8_2;
+};
+
+std::vector<MixedTypedExample>& get_examples_nchw_quant8_2() {
+static std::vector<MixedTypedExample> examples_nchw_quant8_2 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 1, 4, 4}}, {1, {5, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 148, 122, 138, 108, 126, 136, 118, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 148, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 16, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80, 64, 24, 120, 104, 48, 40, 152, 96, 40, 16, 80, 160}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 1}}, {1, {5, 1, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {101, 110, 82, 110, 117}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {66, 68, 94, 77, 71, 76, 139, 47, 77, 16}}},
+}
+},
+}, // End of an example
+};
+return examples_nchw_quant8_2;
+};
+
+std::vector<MixedTypedExample>& get_examples_dynamic_output_shape_nhwc_quant8_2() {
+static std::vector<MixedTypedExample> examples_dynamic_output_shape_nhwc_quant8_2 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 4, 4, 1}}, {1, {5, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 148, 122, 138, 108, 126, 136, 118, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 148, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 16, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80, 64, 24, 120, 104, 48, 40, 152, 96, 40, 16, 80, 160}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 1}}, {1, {5, 1, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {101, 110, 82, 110, 117}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {66, 68, 94, 77, 71, 76, 139, 47, 77, 16}}},
+}
+},
+}, // End of an example
+};
+return examples_dynamic_output_shape_nhwc_quant8_2;
+};
+
+std::vector<MixedTypedExample>& get_examples_dynamic_output_shape_nchw_quant8_2() {
+static std::vector<MixedTypedExample> examples_dynamic_output_shape_nchw_quant8_2 = {
+// Begin of an example
+{
+.operands = {
+//Input(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 1, 4, 4}}, {1, {5, 4}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 148, 122, 138, 108, 126, 136, 118, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 126, 136, 148, 112, 124, 136, 130, 142, 124, 134, 114, 124, 132, 122, 138, 108, 16, 136, 118, 112, 124, 146, 130, 142, 124, 134, 114, 124, 132, 122, 138}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {40, 16, 80, 160, 8, 56, 240, 80, 64, 24, 120, 104, 48, 40, 152, 96, 40, 16, 80, 160}}},
+},
+//Output(s)
+{ // See tools/test_generator/include/TestHarness.h:MixedTyped
+  // int -> Dimensions map
+  .operandDimensions = {{0, {5, 1}}, {1, {5, 1, 2}}},
+  // int -> FLOAT32 map
+  .float32Operands = {},
+  // int -> INT32 map
+  .int32Operands = {},
+  // int -> QUANT8_ASYMM map
+  .quant8AsymmOperands = {{0, {101, 110, 82, 110, 117}}},
+  // int -> QUANT16_SYMM map
+  .quant16SymmOperands = {},
+  // int -> FLOAT16 map
+  .float16Operands = {},
+  // int -> BOOL8 map
+  .bool8Operands = {},
+  // int -> QUANT8_SYMM_PER_CHANNEL map
+  .quant8ChannelOperands = {},
+  // int -> QUANT16_ASYMM map
+  .quant16AsymmOperands = {{1, {66, 68, 94, 77, 71, 76, 139, 47, 77, 16}}},
+}
+},
+}, // End of an example
+};
+return examples_dynamic_output_shape_nchw_quant8_2;
+};
+
diff --git a/runtime/test/generated/models/heatmap_max_keypoint.model.cpp b/runtime/test/generated/models/heatmap_max_keypoint.model.cpp
index 4e13f52..9f212b5 100644
--- a/runtime/test/generated/models/heatmap_max_keypoint.model.cpp
+++ b/runtime/test/generated/models/heatmap_max_keypoint.model.cpp
@@ -60,16 +60,16 @@
 
 void CreateModel_nhwc_float16(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type10(Type::TENSOR_FLOAT16, {6, 1, 2});
-  OperandType type11(Type::TENSOR_FLOAT16, {6, 1});
-  OperandType type8(Type::TENSOR_FLOAT16, {6, 4});
-  OperandType type9(Type::TENSOR_FLOAT16, {6, 4, 4, 1});
+  OperandType type12(Type::TENSOR_FLOAT16, {6, 4});
+  OperandType type13(Type::TENSOR_FLOAT16, {6, 4, 4, 1});
+  OperandType type14(Type::TENSOR_FLOAT16, {6, 1, 2});
+  OperandType type15(Type::TENSOR_FLOAT16, {6, 1});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type9);
-  auto boxes = model->addOperand(&type8);
+  auto heatmap = model->addOperand(&type13);
+  auto boxes = model->addOperand(&type12);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type11);
-  auto keypoint = model->addOperand(&type10);
+  auto score = model->addOperand(&type15);
+  auto keypoint = model->addOperand(&type14);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -88,12 +88,12 @@
 
 void CreateModel_nchw(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type12(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
+  OperandType type16(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
   OperandType type2(Type::TENSOR_FLOAT32, {6, 4});
   OperandType type3(Type::TENSOR_FLOAT32, {6, 1});
   OperandType type4(Type::TENSOR_FLOAT32, {6, 1, 2});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type12);
+  auto heatmap = model->addOperand(&type16);
   auto boxes = model->addOperand(&type2);
   auto layout = model->addOperand(&type0);
   auto score = model->addOperand(&type3);
@@ -116,12 +116,12 @@
 
 void CreateModel_nchw_relaxed(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type12(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
+  OperandType type16(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
   OperandType type2(Type::TENSOR_FLOAT32, {6, 4});
   OperandType type3(Type::TENSOR_FLOAT32, {6, 1});
   OperandType type4(Type::TENSOR_FLOAT32, {6, 1, 2});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type12);
+  auto heatmap = model->addOperand(&type16);
   auto boxes = model->addOperand(&type2);
   auto layout = model->addOperand(&type0);
   auto score = model->addOperand(&type3);
@@ -146,16 +146,16 @@
 
 void CreateModel_nchw_float16(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type10(Type::TENSOR_FLOAT16, {6, 1, 2});
-  OperandType type11(Type::TENSOR_FLOAT16, {6, 1});
-  OperandType type13(Type::TENSOR_FLOAT16, {6, 1, 4, 4});
-  OperandType type8(Type::TENSOR_FLOAT16, {6, 4});
+  OperandType type12(Type::TENSOR_FLOAT16, {6, 4});
+  OperandType type14(Type::TENSOR_FLOAT16, {6, 1, 2});
+  OperandType type15(Type::TENSOR_FLOAT16, {6, 1});
+  OperandType type17(Type::TENSOR_FLOAT16, {6, 1, 4, 4});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type13);
-  auto boxes = model->addOperand(&type8);
+  auto heatmap = model->addOperand(&type17);
+  auto boxes = model->addOperand(&type12);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type11);
-  auto keypoint = model->addOperand(&type10);
+  auto score = model->addOperand(&type15);
+  auto keypoint = model->addOperand(&type14);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -175,15 +175,15 @@
 void CreateModel_dynamic_output_shape_nhwc(Model *model) {
   OperandType type0(Type::BOOL, {});
   OperandType type1(Type::TENSOR_FLOAT32, {6, 4, 4, 1});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type2(Type::TENSOR_FLOAT32, {6, 4});
   // Phase 1, operands
   auto heatmap = model->addOperand(&type1);
   auto boxes = model->addOperand(&type2);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type14);
-  auto keypoint = model->addOperand(&type15);
+  auto score = model->addOperand(&type18);
+  auto keypoint = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -203,15 +203,15 @@
 void CreateModel_dynamic_output_shape_nhwc_relaxed(Model *model) {
   OperandType type0(Type::BOOL, {});
   OperandType type1(Type::TENSOR_FLOAT32, {6, 4, 4, 1});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type2(Type::TENSOR_FLOAT32, {6, 4});
   // Phase 1, operands
   auto heatmap = model->addOperand(&type1);
   auto boxes = model->addOperand(&type2);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type14);
-  auto keypoint = model->addOperand(&type15);
+  auto score = model->addOperand(&type18);
+  auto keypoint = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -232,16 +232,16 @@
 
 void CreateModel_dynamic_output_shape_nhwc_float16(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type16(Type::TENSOR_FLOAT16, {0, 0});
-  OperandType type17(Type::TENSOR_FLOAT16, {0, 0, 0});
-  OperandType type8(Type::TENSOR_FLOAT16, {6, 4});
-  OperandType type9(Type::TENSOR_FLOAT16, {6, 4, 4, 1});
+  OperandType type12(Type::TENSOR_FLOAT16, {6, 4});
+  OperandType type13(Type::TENSOR_FLOAT16, {6, 4, 4, 1});
+  OperandType type20(Type::TENSOR_FLOAT16, {0, 0});
+  OperandType type21(Type::TENSOR_FLOAT16, {0, 0, 0});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type9);
-  auto boxes = model->addOperand(&type8);
+  auto heatmap = model->addOperand(&type13);
+  auto boxes = model->addOperand(&type12);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type16);
-  auto keypoint = model->addOperand(&type17);
+  auto score = model->addOperand(&type20);
+  auto keypoint = model->addOperand(&type21);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -260,16 +260,16 @@
 
 void CreateModel_dynamic_output_shape_nchw(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type12(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type16(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type2(Type::TENSOR_FLOAT32, {6, 4});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type12);
+  auto heatmap = model->addOperand(&type16);
   auto boxes = model->addOperand(&type2);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type14);
-  auto keypoint = model->addOperand(&type15);
+  auto score = model->addOperand(&type18);
+  auto keypoint = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -288,16 +288,16 @@
 
 void CreateModel_dynamic_output_shape_nchw_relaxed(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type12(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type16(Type::TENSOR_FLOAT32, {6, 1, 4, 4});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type2(Type::TENSOR_FLOAT32, {6, 4});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type12);
+  auto heatmap = model->addOperand(&type16);
   auto boxes = model->addOperand(&type2);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type14);
-  auto keypoint = model->addOperand(&type15);
+  auto score = model->addOperand(&type18);
+  auto keypoint = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -318,16 +318,16 @@
 
 void CreateModel_dynamic_output_shape_nchw_float16(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type13(Type::TENSOR_FLOAT16, {6, 1, 4, 4});
-  OperandType type16(Type::TENSOR_FLOAT16, {0, 0});
-  OperandType type17(Type::TENSOR_FLOAT16, {0, 0, 0});
-  OperandType type8(Type::TENSOR_FLOAT16, {6, 4});
+  OperandType type12(Type::TENSOR_FLOAT16, {6, 4});
+  OperandType type17(Type::TENSOR_FLOAT16, {6, 1, 4, 4});
+  OperandType type20(Type::TENSOR_FLOAT16, {0, 0});
+  OperandType type21(Type::TENSOR_FLOAT16, {0, 0, 0});
   // Phase 1, operands
-  auto heatmap = model->addOperand(&type13);
-  auto boxes = model->addOperand(&type8);
+  auto heatmap = model->addOperand(&type17);
+  auto boxes = model->addOperand(&type12);
   auto layout = model->addOperand(&type0);
-  auto score = model->addOperand(&type16);
-  auto keypoint = model->addOperand(&type17);
+  auto score = model->addOperand(&type20);
+  auto keypoint = model->addOperand(&type21);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -402,15 +402,15 @@
 
 void CreateModel_nhwc_float16_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type18(Type::TENSOR_FLOAT16, {2, 4});
-  OperandType type19(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
-  OperandType type20(Type::TENSOR_FLOAT16, {2, 4, 2});
+  OperandType type22(Type::TENSOR_FLOAT16, {2, 4});
+  OperandType type23(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
+  OperandType type24(Type::TENSOR_FLOAT16, {2, 4, 2});
   // Phase 1, operands
-  auto heatmap1 = model->addOperand(&type19);
-  auto boxes1 = model->addOperand(&type18);
+  auto heatmap1 = model->addOperand(&type23);
+  auto boxes1 = model->addOperand(&type22);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type18);
-  auto keypoint1 = model->addOperand(&type20);
+  auto score1 = model->addOperand(&type22);
+  auto keypoint1 = model->addOperand(&type24);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -427,6 +427,34 @@
   return ignore.find(i) != ignore.end();
 }
 
+void CreateModel_nhwc_quant8(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type25(Type::TENSOR_QUANT16_ASYMM, {2, 4}, 0.125f, 0);
+  OperandType type26(Type::TENSOR_QUANT8_ASYMM, {2, 4, 4, 4}, 0.01f, 128);
+  OperandType type27(Type::TENSOR_QUANT16_ASYMM, {2, 4, 2}, 0.125f, 0);
+  OperandType type28(Type::TENSOR_QUANT8_ASYMM, {2, 4}, 0.01f, 0);
+  // Phase 1, operands
+  auto heatmap1 = model->addOperand(&type26);
+  auto boxes1 = model->addOperand(&type25);
+  auto layout = model->addOperand(&type0);
+  auto score1 = model->addOperand(&type28);
+  auto keypoint1 = model->addOperand(&type27);
+  // Phase 2, operations
+  static bool8 layout_init[] = {false};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap1, boxes1, layout}, {score1, keypoint1});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap1, boxes1},
+    {score1, keypoint1});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_nhwc_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
 void CreateModel_nchw_2(Model *model) {
   OperandType type0(Type::BOOL, {});
   OperandType type5(Type::TENSOR_FLOAT32, {2, 4, 4, 4});
@@ -485,15 +513,15 @@
 
 void CreateModel_nchw_float16_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type18(Type::TENSOR_FLOAT16, {2, 4});
-  OperandType type19(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
-  OperandType type20(Type::TENSOR_FLOAT16, {2, 4, 2});
+  OperandType type22(Type::TENSOR_FLOAT16, {2, 4});
+  OperandType type23(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
+  OperandType type24(Type::TENSOR_FLOAT16, {2, 4, 2});
   // Phase 1, operands
-  auto heatmap1 = model->addOperand(&type19);
-  auto boxes1 = model->addOperand(&type18);
+  auto heatmap1 = model->addOperand(&type23);
+  auto boxes1 = model->addOperand(&type22);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type18);
-  auto keypoint1 = model->addOperand(&type20);
+  auto score1 = model->addOperand(&type22);
+  auto keypoint1 = model->addOperand(&type24);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -510,18 +538,46 @@
   return ignore.find(i) != ignore.end();
 }
 
+void CreateModel_nchw_quant8(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type25(Type::TENSOR_QUANT16_ASYMM, {2, 4}, 0.125f, 0);
+  OperandType type26(Type::TENSOR_QUANT8_ASYMM, {2, 4, 4, 4}, 0.01f, 128);
+  OperandType type27(Type::TENSOR_QUANT16_ASYMM, {2, 4, 2}, 0.125f, 0);
+  OperandType type28(Type::TENSOR_QUANT8_ASYMM, {2, 4}, 0.01f, 0);
+  // Phase 1, operands
+  auto heatmap1 = model->addOperand(&type26);
+  auto boxes1 = model->addOperand(&type25);
+  auto layout = model->addOperand(&type0);
+  auto score1 = model->addOperand(&type28);
+  auto keypoint1 = model->addOperand(&type27);
+  // Phase 2, operations
+  static bool8 layout_init[] = {true};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap1, boxes1, layout}, {score1, keypoint1});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap1, boxes1},
+    {score1, keypoint1});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_nchw_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
 void CreateModel_dynamic_output_shape_nhwc_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type5(Type::TENSOR_FLOAT32, {2, 4, 4, 4});
   OperandType type6(Type::TENSOR_FLOAT32, {2, 4});
   // Phase 1, operands
   auto heatmap1 = model->addOperand(&type5);
   auto boxes1 = model->addOperand(&type6);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type14);
-  auto keypoint1 = model->addOperand(&type15);
+  auto score1 = model->addOperand(&type18);
+  auto keypoint1 = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -540,16 +596,16 @@
 
 void CreateModel_dynamic_output_shape_nhwc_relaxed_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type5(Type::TENSOR_FLOAT32, {2, 4, 4, 4});
   OperandType type6(Type::TENSOR_FLOAT32, {2, 4});
   // Phase 1, operands
   auto heatmap1 = model->addOperand(&type5);
   auto boxes1 = model->addOperand(&type6);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type14);
-  auto keypoint1 = model->addOperand(&type15);
+  auto score1 = model->addOperand(&type18);
+  auto keypoint1 = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -570,16 +626,16 @@
 
 void CreateModel_dynamic_output_shape_nhwc_float16_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type16(Type::TENSOR_FLOAT16, {0, 0});
-  OperandType type17(Type::TENSOR_FLOAT16, {0, 0, 0});
-  OperandType type18(Type::TENSOR_FLOAT16, {2, 4});
-  OperandType type19(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
+  OperandType type20(Type::TENSOR_FLOAT16, {0, 0});
+  OperandType type21(Type::TENSOR_FLOAT16, {0, 0, 0});
+  OperandType type22(Type::TENSOR_FLOAT16, {2, 4});
+  OperandType type23(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
   // Phase 1, operands
-  auto heatmap1 = model->addOperand(&type19);
-  auto boxes1 = model->addOperand(&type18);
+  auto heatmap1 = model->addOperand(&type23);
+  auto boxes1 = model->addOperand(&type22);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type16);
-  auto keypoint1 = model->addOperand(&type17);
+  auto score1 = model->addOperand(&type20);
+  auto keypoint1 = model->addOperand(&type21);
   // Phase 2, operations
   static bool8 layout_init[] = {false};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -596,18 +652,46 @@
   return ignore.find(i) != ignore.end();
 }
 
+void CreateModel_dynamic_output_shape_nhwc_quant8(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type25(Type::TENSOR_QUANT16_ASYMM, {2, 4}, 0.125f, 0);
+  OperandType type26(Type::TENSOR_QUANT8_ASYMM, {2, 4, 4, 4}, 0.01f, 128);
+  OperandType type29(Type::TENSOR_QUANT8_ASYMM, {0, 0}, 0.01f, 0);
+  OperandType type30(Type::TENSOR_QUANT16_ASYMM, {0, 0, 0}, 0.125f, 0);
+  // Phase 1, operands
+  auto heatmap1 = model->addOperand(&type26);
+  auto boxes1 = model->addOperand(&type25);
+  auto layout = model->addOperand(&type0);
+  auto score1 = model->addOperand(&type29);
+  auto keypoint1 = model->addOperand(&type30);
+  // Phase 2, operations
+  static bool8 layout_init[] = {false};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap1, boxes1, layout}, {score1, keypoint1});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap1, boxes1},
+    {score1, keypoint1});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_dynamic_output_shape_nhwc_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
 void CreateModel_dynamic_output_shape_nchw_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type5(Type::TENSOR_FLOAT32, {2, 4, 4, 4});
   OperandType type6(Type::TENSOR_FLOAT32, {2, 4});
   // Phase 1, operands
   auto heatmap1 = model->addOperand(&type5);
   auto boxes1 = model->addOperand(&type6);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type14);
-  auto keypoint1 = model->addOperand(&type15);
+  auto score1 = model->addOperand(&type18);
+  auto keypoint1 = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -626,16 +710,16 @@
 
 void CreateModel_dynamic_output_shape_nchw_relaxed_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type14(Type::TENSOR_FLOAT32, {0, 0});
-  OperandType type15(Type::TENSOR_FLOAT32, {0, 0, 0});
+  OperandType type18(Type::TENSOR_FLOAT32, {0, 0});
+  OperandType type19(Type::TENSOR_FLOAT32, {0, 0, 0});
   OperandType type5(Type::TENSOR_FLOAT32, {2, 4, 4, 4});
   OperandType type6(Type::TENSOR_FLOAT32, {2, 4});
   // Phase 1, operands
   auto heatmap1 = model->addOperand(&type5);
   auto boxes1 = model->addOperand(&type6);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type14);
-  auto keypoint1 = model->addOperand(&type15);
+  auto score1 = model->addOperand(&type18);
+  auto keypoint1 = model->addOperand(&type19);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -656,16 +740,16 @@
 
 void CreateModel_dynamic_output_shape_nchw_float16_2(Model *model) {
   OperandType type0(Type::BOOL, {});
-  OperandType type16(Type::TENSOR_FLOAT16, {0, 0});
-  OperandType type17(Type::TENSOR_FLOAT16, {0, 0, 0});
-  OperandType type18(Type::TENSOR_FLOAT16, {2, 4});
-  OperandType type19(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
+  OperandType type20(Type::TENSOR_FLOAT16, {0, 0});
+  OperandType type21(Type::TENSOR_FLOAT16, {0, 0, 0});
+  OperandType type22(Type::TENSOR_FLOAT16, {2, 4});
+  OperandType type23(Type::TENSOR_FLOAT16, {2, 4, 4, 4});
   // Phase 1, operands
-  auto heatmap1 = model->addOperand(&type19);
-  auto boxes1 = model->addOperand(&type18);
+  auto heatmap1 = model->addOperand(&type23);
+  auto boxes1 = model->addOperand(&type22);
   auto layout = model->addOperand(&type0);
-  auto score1 = model->addOperand(&type16);
-  auto keypoint1 = model->addOperand(&type17);
+  auto score1 = model->addOperand(&type20);
+  auto keypoint1 = model->addOperand(&type21);
   // Phase 2, operations
   static bool8 layout_init[] = {true};
   model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
@@ -682,3 +766,143 @@
   return ignore.find(i) != ignore.end();
 }
 
+void CreateModel_dynamic_output_shape_nchw_quant8(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type25(Type::TENSOR_QUANT16_ASYMM, {2, 4}, 0.125f, 0);
+  OperandType type26(Type::TENSOR_QUANT8_ASYMM, {2, 4, 4, 4}, 0.01f, 128);
+  OperandType type29(Type::TENSOR_QUANT8_ASYMM, {0, 0}, 0.01f, 0);
+  OperandType type30(Type::TENSOR_QUANT16_ASYMM, {0, 0, 0}, 0.125f, 0);
+  // Phase 1, operands
+  auto heatmap1 = model->addOperand(&type26);
+  auto boxes1 = model->addOperand(&type25);
+  auto layout = model->addOperand(&type0);
+  auto score1 = model->addOperand(&type29);
+  auto keypoint1 = model->addOperand(&type30);
+  // Phase 2, operations
+  static bool8 layout_init[] = {true};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap1, boxes1, layout}, {score1, keypoint1});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap1, boxes1},
+    {score1, keypoint1});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_dynamic_output_shape_nchw_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+void CreateModel_nhwc_quant8_2(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type31(Type::TENSOR_QUANT16_ASYMM, {5, 4}, 0.125f, 0);
+  OperandType type32(Type::TENSOR_QUANT8_ASYMM, {5, 4, 4, 1}, 0.5f, 128);
+  OperandType type33(Type::TENSOR_QUANT16_ASYMM, {5, 1, 2}, 0.125f, 0);
+  OperandType type34(Type::TENSOR_QUANT8_ASYMM, {5, 1}, 0.1f, 10);
+  // Phase 1, operands
+  auto heatmap2 = model->addOperand(&type32);
+  auto boxes2 = model->addOperand(&type31);
+  auto layout = model->addOperand(&type0);
+  auto score2 = model->addOperand(&type34);
+  auto keypoint2 = model->addOperand(&type33);
+  // Phase 2, operations
+  static bool8 layout_init[] = {false};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap2, boxes2, layout}, {score2, keypoint2});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap2, boxes2},
+    {score2, keypoint2});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_nhwc_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+void CreateModel_nchw_quant8_2(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type31(Type::TENSOR_QUANT16_ASYMM, {5, 4}, 0.125f, 0);
+  OperandType type33(Type::TENSOR_QUANT16_ASYMM, {5, 1, 2}, 0.125f, 0);
+  OperandType type34(Type::TENSOR_QUANT8_ASYMM, {5, 1}, 0.1f, 10);
+  OperandType type36(Type::TENSOR_QUANT8_ASYMM, {5, 1, 4, 4}, 0.5f, 128);
+  // Phase 1, operands
+  auto heatmap2 = model->addOperand(&type36);
+  auto boxes2 = model->addOperand(&type31);
+  auto layout = model->addOperand(&type0);
+  auto score2 = model->addOperand(&type34);
+  auto keypoint2 = model->addOperand(&type33);
+  // Phase 2, operations
+  static bool8 layout_init[] = {true};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap2, boxes2, layout}, {score2, keypoint2});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap2, boxes2},
+    {score2, keypoint2});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_nchw_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+void CreateModel_dynamic_output_shape_nhwc_quant8_2(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type30(Type::TENSOR_QUANT16_ASYMM, {0, 0, 0}, 0.125f, 0);
+  OperandType type31(Type::TENSOR_QUANT16_ASYMM, {5, 4}, 0.125f, 0);
+  OperandType type32(Type::TENSOR_QUANT8_ASYMM, {5, 4, 4, 1}, 0.5f, 128);
+  OperandType type37(Type::TENSOR_QUANT8_ASYMM, {0, 0}, 0.1f, 10);
+  // Phase 1, operands
+  auto heatmap2 = model->addOperand(&type32);
+  auto boxes2 = model->addOperand(&type31);
+  auto layout = model->addOperand(&type0);
+  auto score2 = model->addOperand(&type37);
+  auto keypoint2 = model->addOperand(&type30);
+  // Phase 2, operations
+  static bool8 layout_init[] = {false};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap2, boxes2, layout}, {score2, keypoint2});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap2, boxes2},
+    {score2, keypoint2});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_dynamic_output_shape_nhwc_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+void CreateModel_dynamic_output_shape_nchw_quant8_2(Model *model) {
+  OperandType type0(Type::BOOL, {});
+  OperandType type30(Type::TENSOR_QUANT16_ASYMM, {0, 0, 0}, 0.125f, 0);
+  OperandType type31(Type::TENSOR_QUANT16_ASYMM, {5, 4}, 0.125f, 0);
+  OperandType type36(Type::TENSOR_QUANT8_ASYMM, {5, 1, 4, 4}, 0.5f, 128);
+  OperandType type37(Type::TENSOR_QUANT8_ASYMM, {0, 0}, 0.1f, 10);
+  // Phase 1, operands
+  auto heatmap2 = model->addOperand(&type36);
+  auto boxes2 = model->addOperand(&type31);
+  auto layout = model->addOperand(&type0);
+  auto score2 = model->addOperand(&type37);
+  auto keypoint2 = model->addOperand(&type30);
+  // Phase 2, operations
+  static bool8 layout_init[] = {true};
+  model->setOperandValue(layout, layout_init, sizeof(bool8) * 1);
+  model->addOperation(ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT, {heatmap2, boxes2, layout}, {score2, keypoint2});
+  // Phase 3, inputs and outputs
+  model->identifyInputsAndOutputs(
+    {heatmap2, boxes2},
+    {score2, keypoint2});
+  assert(model->isValid());
+}
+
+inline bool is_ignored_dynamic_output_shape_nchw_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
diff --git a/runtime/test/generated/tests/heatmap_max_keypoint.mod.py.cpp b/runtime/test/generated/tests/heatmap_max_keypoint.mod.py.cpp
index 1b6b92f..f1be52d 100644
--- a/runtime/test/generated/tests/heatmap_max_keypoint.mod.py.cpp
+++ b/runtime/test/generated/tests/heatmap_max_keypoint.mod.py.cpp
@@ -111,6 +111,12 @@
             heatmap_max_keypoint::get_examples_nhwc_float16_2());
 }
 
+TEST_F(GeneratedTests, heatmap_max_keypoint_nhwc_quant8) {
+    execute(heatmap_max_keypoint::CreateModel_nhwc_quant8,
+            heatmap_max_keypoint::is_ignored_nhwc_quant8,
+            heatmap_max_keypoint::get_examples_nhwc_quant8());
+}
+
 TEST_F(GeneratedTests, heatmap_max_keypoint_nchw_2) {
     execute(heatmap_max_keypoint::CreateModel_nchw_2,
             heatmap_max_keypoint::is_ignored_nchw_2,
@@ -129,6 +135,12 @@
             heatmap_max_keypoint::get_examples_nchw_float16_2());
 }
 
+TEST_F(GeneratedTests, heatmap_max_keypoint_nchw_quant8) {
+    execute(heatmap_max_keypoint::CreateModel_nchw_quant8,
+            heatmap_max_keypoint::is_ignored_nchw_quant8,
+            heatmap_max_keypoint::get_examples_nchw_quant8());
+}
+
 #if 0
 TEST_F(DynamicOutputShapeTests, heatmap_max_keypoint_dynamic_output_shape_nhwc_2) {
     execute(heatmap_max_keypoint::CreateModel_dynamic_output_shape_nhwc_2,
@@ -154,6 +166,14 @@
 
 #endif
 #if 0
+TEST_F(DynamicOutputShapeTests, heatmap_max_keypoint_dynamic_output_shape_nhwc_quant8) {
+    execute(heatmap_max_keypoint::CreateModel_dynamic_output_shape_nhwc_quant8,
+            heatmap_max_keypoint::is_ignored_dynamic_output_shape_nhwc_quant8,
+            heatmap_max_keypoint::get_examples_dynamic_output_shape_nhwc_quant8());
+}
+
+#endif
+#if 0
 TEST_F(DynamicOutputShapeTests, heatmap_max_keypoint_dynamic_output_shape_nchw_2) {
     execute(heatmap_max_keypoint::CreateModel_dynamic_output_shape_nchw_2,
             heatmap_max_keypoint::is_ignored_dynamic_output_shape_nchw_2,
@@ -177,3 +197,39 @@
 }
 
 #endif
+#if 0
+TEST_F(DynamicOutputShapeTests, heatmap_max_keypoint_dynamic_output_shape_nchw_quant8) {
+    execute(heatmap_max_keypoint::CreateModel_dynamic_output_shape_nchw_quant8,
+            heatmap_max_keypoint::is_ignored_dynamic_output_shape_nchw_quant8,
+            heatmap_max_keypoint::get_examples_dynamic_output_shape_nchw_quant8());
+}
+
+#endif
+TEST_F(GeneratedTests, heatmap_max_keypoint_nhwc_quant8_2) {
+    execute(heatmap_max_keypoint::CreateModel_nhwc_quant8_2,
+            heatmap_max_keypoint::is_ignored_nhwc_quant8_2,
+            heatmap_max_keypoint::get_examples_nhwc_quant8_2());
+}
+
+TEST_F(GeneratedTests, heatmap_max_keypoint_nchw_quant8_2) {
+    execute(heatmap_max_keypoint::CreateModel_nchw_quant8_2,
+            heatmap_max_keypoint::is_ignored_nchw_quant8_2,
+            heatmap_max_keypoint::get_examples_nchw_quant8_2());
+}
+
+#if 0
+TEST_F(DynamicOutputShapeTests, heatmap_max_keypoint_dynamic_output_shape_nhwc_quant8_2) {
+    execute(heatmap_max_keypoint::CreateModel_dynamic_output_shape_nhwc_quant8_2,
+            heatmap_max_keypoint::is_ignored_dynamic_output_shape_nhwc_quant8_2,
+            heatmap_max_keypoint::get_examples_dynamic_output_shape_nhwc_quant8_2());
+}
+
+#endif
+#if 0
+TEST_F(DynamicOutputShapeTests, heatmap_max_keypoint_dynamic_output_shape_nchw_quant8_2) {
+    execute(heatmap_max_keypoint::CreateModel_dynamic_output_shape_nchw_quant8_2,
+            heatmap_max_keypoint::is_ignored_dynamic_output_shape_nchw_quant8_2,
+            heatmap_max_keypoint::get_examples_dynamic_output_shape_nchw_quant8_2());
+}
+
+#endif
diff --git a/runtime/test/generated/vts_models/heatmap_max_keypoint.model.cpp b/runtime/test/generated/vts_models/heatmap_max_keypoint.model.cpp
index bbe10e4..3799d43 100644
--- a/runtime/test/generated/vts_models/heatmap_max_keypoint.model.cpp
+++ b/runtime/test/generated/vts_models/heatmap_max_keypoint.model.cpp
@@ -1206,6 +1206,86 @@
 }
 
 // Create the model
+Model createTestModel_nhwc_quant8() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {2, 4, 4, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.01f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {2, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {2, 4},
+            .numberOfConsumers = 0,
+            .scale = 0.01f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {2, 4, 2},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      0
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_nhwc_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
 Model createTestModel_nchw_2() {
     const std::vector<Operand> operands = {
         {
@@ -1447,6 +1527,86 @@
 }
 
 // Create the model
+Model createTestModel_nchw_quant8() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {2, 4, 4, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.01f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {2, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {2, 4},
+            .numberOfConsumers = 0,
+            .scale = 0.01f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {2, 4, 2},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      1
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_nchw_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
 Model createTestModel_dynamic_output_shape_nhwc_2() {
     const std::vector<Operand> operands = {
         {
@@ -1688,6 +1848,86 @@
 }
 
 // Create the model
+Model createTestModel_dynamic_output_shape_nhwc_quant8() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {2, 4, 4, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.01f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {2, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.01f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {0, 0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      0
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_dynamic_output_shape_nhwc_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
 Model createTestModel_dynamic_output_shape_nchw_2() {
     const std::vector<Operand> operands = {
         {
@@ -1928,3 +2168,403 @@
   return ignore.find(i) != ignore.end();
 }
 
+// Create the model
+Model createTestModel_dynamic_output_shape_nchw_quant8() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {2, 4, 4, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.01f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {2, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.01f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {0, 0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      1
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_dynamic_output_shape_nchw_quant8(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
+Model createTestModel_nhwc_quant8_2() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {5, 4, 4, 1},
+            .numberOfConsumers = 1,
+            .scale = 0.5f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {5, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {5, 1},
+            .numberOfConsumers = 0,
+            .scale = 0.1f,
+            .zeroPoint = 10,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {5, 1, 2},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      0
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_nhwc_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
+Model createTestModel_nchw_quant8_2() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {5, 1, 4, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.5f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {5, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {5, 1},
+            .numberOfConsumers = 0,
+            .scale = 0.1f,
+            .zeroPoint = 10,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {5, 1, 2},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      1
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_nchw_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
+Model createTestModel_dynamic_output_shape_nhwc_quant8_2() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {5, 4, 4, 1},
+            .numberOfConsumers = 1,
+            .scale = 0.5f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {5, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.1f,
+            .zeroPoint = 10,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {0, 0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      0
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_dynamic_output_shape_nhwc_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
+// Create the model
+Model createTestModel_dynamic_output_shape_nchw_quant8_2() {
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {5, 1, 4, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.5f,
+            .zeroPoint = 128,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {5, 4},
+            .numberOfConsumers = 1,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::BOOL,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = 1},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT8_ASYMM,
+            .dimensions = {0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.1f,
+            .zeroPoint = 10,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_QUANT16_ASYMM,
+            .dimensions = {0, 0, 0},
+            .numberOfConsumers = 0,
+            .scale = 0.125f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        }
+    };
+
+    const std::vector<Operation> operations = {
+        {
+            .type = OperationType::HEATMAP_MAX_KEYPOINT,
+            .inputs = {0, 1, 2},
+            .outputs = {3, 4},
+        }
+    };
+
+    const std::vector<uint32_t> inputIndexes = {0, 1};
+    const std::vector<uint32_t> outputIndexes = {3, 4};
+    std::vector<uint8_t> operandValues = {
+      1
+    };
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+
+inline bool is_ignored_dynamic_output_shape_nchw_quant8_2(int i) {
+  static std::set<int> ignore = {};
+  return ignore.find(i) != ignore.end();
+}
+
diff --git a/runtime/test/specs/V1_2/heatmap_max_keypoint.mod.py b/runtime/test/specs/V1_2/heatmap_max_keypoint.mod.py
index 603cddc..9b73811 100644
--- a/runtime/test/specs/V1_2/heatmap_max_keypoint.mod.py
+++ b/runtime/test/specs/V1_2/heatmap_max_keypoint.mod.py
@@ -85,6 +85,13 @@
 keypoint2 = Output("keypoint", "TENSOR_FLOAT32", "{2, 4, 2}")
 Model().Operation("HEATMAP_MAX_KEYPOINT", heatmap2, boxes2, layout).To(score2, keypoint2)
 
+quant8 = DataTypeConverter().Identify({
+    heatmap2: ("TENSOR_QUANT8_ASYMM", 0.01, 128),
+    boxes2: ("TENSOR_QUANT16_ASYMM", 0.125, 0),
+    score2: ("TENSOR_QUANT8_ASYMM", 0.01, 0),
+    keypoint2: ("TENSOR_QUANT16_ASYMM", 0.125, 0)
+})
+
 # Instantiate an example
 Example({
     heatmap2: [
@@ -121,4 +128,66 @@
          4.625000,  7.375000,
         26.375000,  9.625000
     ]
-}).AddNchw(heatmap2, layout).AddVariations("relaxed", "float16")
+}).AddNchw(heatmap2, layout).AddVariations("relaxed", "float16", quant8)
+
+
+# TEST 3: HEATMAP_MAX_KEYPOINT_3
+heatmap3 = Input("heatmap", "TENSOR_FLOAT32", "{5, 4, 4, 1}")
+boxes3 = Input("boxes", "TENSOR_FLOAT32", "{5, 4}")
+score3 = Output("score", "TENSOR_FLOAT32", "{5, 1}")
+keypoint3 = Output("keypoint", "TENSOR_FLOAT32", "{5, 1, 2}")
+Model().Operation("HEATMAP_MAX_KEYPOINT", heatmap3, boxes3, layout).To(score3, keypoint3)
+
+quant8 = DataTypeConverter().Identify({
+    heatmap3: ("TENSOR_QUANT8_ASYMM", 0.5, 128),
+    boxes3: ("TENSOR_QUANT16_ASYMM", 0.125, 0),
+    score3: ("TENSOR_QUANT8_ASYMM", 0.1, 10),
+    keypoint3: ("TENSOR_QUANT16_ASYMM", 0.125, 0)
+})
+
+# Instantiate an example
+Example({
+    heatmap3: [
+        -10, -1,  4, -5, # batch0
+         -8, -2,  9,  1,
+          7, -2,  3, -7,
+         -2,  2, -3,  5,
+        -10, -1,  4, -5, # batch1 - test mirror bottom
+         -8, -2,  9,  1,
+          7, -2,  3, -7,
+         -2, 10, -3,  5,
+        -10, -1,  4, -5, # batch2 - test mirror left
+         -8, -2,  4,  1,
+          7, -2,  3, -7,
+         -2,  2, -3,  5,
+        -10, -1,  4, 10, # batch3 - test mirror top right
+         -8, -2,  4,  1,
+          7, -2,  3, -7,
+         -2,  2, -3,  5,
+        -10,-56,  4, -5, # batch4 - test out of range delta
+         -8, -2,  9,  1,
+          7, -2,  3, -7,
+         -2,  2, -3,  5
+    ],
+    boxes3: [
+        5, 2, 10, 20,
+        1, 7, 30, 10,
+        8, 3, 15, 13,
+        6, 5, 19, 12,
+        5, 2, 10, 20
+    ],
+    score3: [
+        9.071493,
+        10.00500,
+        7.187500,
+        10.00000,
+        10.689667
+    ],
+    keypoint3: [
+        8.224462, 8.537316,
+        11.73000, 9.625000,
+        8.875000, 9.562500,
+        17.37500, 5.875000,
+        9.569672, 2.000000
+    ]
+}).AddNchw(heatmap3, layout).AddVariations(quant8, includeDefault=False)