Fix tests, add depth_multiplier value check in DEPTHWISE_CONV_2D.

depth_multiplier value was not validated in the
depthwiseConvPrepare method. Newly added tests for the per-channel
quantized convolution had wrong output channel count for their
depth_multiplier value, which was not checked.

+ Minor fix in CpuExecutor, removed use of a filter mOperand field

Bug: 122046844
Test: NeuralNetworksTest_static
Change-Id: I95a187c48dcdb5a8c831557aac35da884680e2c0
Merged-In: I95a187c48dcdb5a8c831557aac35da884680e2c0
(cherry picked from commit 39520cb9792e29efbc35d4d55bae3a43845ca78d)
diff --git a/common/CpuExecutor.cpp b/common/CpuExecutor.cpp
index 19e825a..2066a62 100644
--- a/common/CpuExecutor.cpp
+++ b/common/CpuExecutor.cpp
@@ -672,7 +672,6 @@
             }
             const RunTimeOperandInfo& input  = mOperands[ins[0]];
             const RunTimeOperandInfo& filter = mOperands[ins[1]];
-            const Operand& filterOperand = mModel->operands[ins[1]];
             const RunTimeOperandInfo& bias   = mOperands[ins[2]];
 
             int32_t padding_left, padding_right;
@@ -735,7 +734,7 @@
 
             if (!depthwiseConvPrepare(input_tmp.shape(), filter.shape(), bias.shape(), padding_left,
                                       padding_right, padding_top, padding_bottom, stride_width,
-                                      stride_height, &outShape) ||
+                                      stride_height, depth_multiplier, &outShape) ||
                 !setInfoAndAllocateIfNeeded(&output_tmp, outShape)) {
                 success = false;
                 break;
@@ -761,7 +760,7 @@
                     success = depthwiseConvQuant8PerChannel(
                             reinterpret_cast<const uint8_t*>(input_tmp.buffer), input_tmp.shape(),
                             reinterpret_cast<const int8_t*>(filter.buffer), filter.shape(),
-                            filterOperand.extraParams.channelQuant().scales.data(),
+                            filter.extraParams.channelQuant().scales.data(),
                             reinterpret_cast<const int32_t*>(bias.buffer), bias.shape(),
                             padding_left, padding_right, padding_top, padding_bottom, stride_width,
                             stride_height, depth_multiplier, activation,
diff --git a/common/OperationsUtils.cpp b/common/OperationsUtils.cpp
index 72edd2a..640c9d8 100644
--- a/common/OperationsUtils.cpp
+++ b/common/OperationsUtils.cpp
@@ -360,13 +360,10 @@
     return true;
 }
 
-bool depthwiseConvPrepare(const Shape& input,
-                          const Shape& filter,
-                          const Shape& bias,
-                          int32_t padding_left, int32_t padding_right,
-                          int32_t padding_top, int32_t padding_bottom,
-                          int32_t stride_width, int32_t stride_height,
-                          Shape* output) {
+bool depthwiseConvPrepare(const Shape& input, const Shape& filter, const Shape& bias,
+                          int32_t padding_left, int32_t padding_right, int32_t padding_top,
+                          int32_t padding_bottom, int32_t stride_width, int32_t stride_height,
+                          int32_t depth_multiplier, Shape* output) {
     if (filter.type == OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) {
         NN_OPS_CHECK(input.type == OperandType::TENSOR_QUANT8_ASYMM);
     } else {
@@ -384,12 +381,15 @@
     NN_OPS_CHECK(getSizeOfDimension(filter, 3) == getSizeOfDimension(bias, 0));
 
     uint32_t channels_out = getSizeOfDimension(filter, 3);
+    uint32_t channels_in = getSizeOfDimension(input, 3);
     uint32_t width        = getSizeOfDimension(input, 2);
     uint32_t height       = getSizeOfDimension(input, 1);
     uint32_t filterWidth  = getSizeOfDimension(filter, 2);
     uint32_t filterHeight = getSizeOfDimension(filter, 1);
     uint32_t batches      = getSizeOfDimension(input, 0);
 
+    NN_OPS_CHECK(depth_multiplier * channels_in == channels_out);
+
     uint32_t outWidth = computeOutSize(width, filterWidth, stride_width,
                                        padding_left, padding_right);
     uint32_t outHeight = computeOutSize(height, filterHeight, stride_height,
diff --git a/common/include/OperationsUtils.h b/common/include/OperationsUtils.h
index 77e1a64..c62f6e4 100644
--- a/common/include/OperationsUtils.h
+++ b/common/include/OperationsUtils.h
@@ -341,13 +341,10 @@
 
 bool quantizePrepare(const Shape& input, Shape* output);
 
-bool depthwiseConvPrepare(const Shape& input,
-                          const Shape& filter,
-                          const Shape& bias,
-                          int32_t padding_left, int32_t padding_right,
-                          int32_t padding_top, int32_t padding_bottom,
-                          int32_t stride_width, int32_t stride_height,
-                          Shape* output);
+bool depthwiseConvPrepare(const Shape& input, const Shape& filter, const Shape& bias,
+                          int32_t padding_left, int32_t padding_right, int32_t padding_top,
+                          int32_t padding_bottom, int32_t stride_width, int32_t stride_height,
+                          int32_t depth_multiplier, Shape* output);
 
 bool convPrepare(const Shape& input,
                  const Shape& filter,
diff --git a/runtime/test/generated/examples/depthwise_conv2d_per_channel.example.cpp b/runtime/test/generated/examples/depthwise_conv2d_per_channel.example.cpp
index a451d5d..b25a244 100644
--- a/runtime/test/generated/examples/depthwise_conv2d_per_channel.example.cpp
+++ b/runtime/test/generated/examples/depthwise_conv2d_per_channel.example.cpp
@@ -119,7 +119,7 @@
   // int -> INT32 map
   {},
   // int -> QUANT8_ASYMM map
-  {{0, {132, 130, 128, 128, 132, 130, 129, 128}}},
+  {{0, {132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131}}},
   // int -> QUANT16_SYMM map
   {},
   // int -> FLOAT16 map
@@ -145,7 +145,7 @@
   // int -> FLOAT32 map
   {},
   // int -> INT32 map
-  {{2, {4, 4}}},
+  {{2, {4, 4, 4, 4}}},
   // int -> QUANT8_ASYMM map
   {{0, {129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130}}},
   // int -> QUANT16_SYMM map
@@ -155,7 +155,7 @@
   // int -> BOOL8 map
   {},
   // int -> QUANT8_SYMM_PER_CHANNEL map
-  {{1, {1, 1, 1, 1, 1, 1, 1, 1}}},
+  {{1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}},
 },
 //Output(s)
 { // See tools/test_generator/include/TestHarness.h:MixedTyped
@@ -164,7 +164,7 @@
   // int -> INT32 map
   {},
   // int -> QUANT8_ASYMM map
-  {{0, {132, 130, 128, 128, 132, 130, 129, 128}}},
+  {{0, {132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131}}},
   // int -> QUANT16_SYMM map
   {},
   // int -> FLOAT16 map
@@ -209,7 +209,7 @@
   // int -> INT32 map
   {},
   // int -> QUANT8_ASYMM map
-  {{0, {132, 130, 128, 128, 132, 130, 129, 128}}},
+  {{0, {132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131}}},
   // int -> QUANT16_SYMM map
   {},
   // int -> FLOAT16 map
@@ -235,7 +235,7 @@
   // int -> FLOAT32 map
   {},
   // int -> INT32 map
-  {{2, {4, 4}}},
+  {{2, {4, 4, 4, 4}}},
   // int -> QUANT8_ASYMM map
   {{0, {129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130, 129, 130}}},
   // int -> QUANT16_SYMM map
@@ -245,7 +245,7 @@
   // int -> BOOL8 map
   {},
   // int -> QUANT8_SYMM_PER_CHANNEL map
-  {{1, {1, 1, 1, 1, 1, 1, 1, 1}}},
+  {{1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}},
 },
 //Output(s)
 { // See tools/test_generator/include/TestHarness.h:MixedTyped
@@ -254,7 +254,7 @@
   // int -> INT32 map
   {},
   // int -> QUANT8_ASYMM map
-  {{0, {132, 130, 128, 128, 132, 130, 129, 128}}},
+  {{0, {132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131, 132, 130, 134, 131}}},
   // int -> QUANT16_SYMM map
   {},
   // int -> FLOAT16 map
@@ -299,7 +299,7 @@
   // int -> INT32 map
   {},
   // int -> QUANT8_ASYMM map
-  {{0, {132, 128, 132, 129, 130, 128, 130, 128}}},
+  {{0, {132, 132, 132, 132, 130, 130, 130, 130, 134, 134, 134, 134, 131, 131, 131, 131}}},
   // int -> QUANT16_SYMM map
   {},
   // int -> FLOAT16 map
@@ -325,7 +325,7 @@
   // int -> FLOAT32 map
   {},
   // int -> INT32 map
-  {{2, {4, 4}}},
+  {{2, {4, 4, 4, 4}}},
   // int -> QUANT8_ASYMM map
   {{0, {129, 129, 129, 129, 129, 129, 129, 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 130}}},
   // int -> QUANT16_SYMM map
@@ -335,7 +335,7 @@
   // int -> BOOL8 map
   {},
   // int -> QUANT8_SYMM_PER_CHANNEL map
-  {{1, {1, 1, 1, 1, 1, 1, 1, 1}}},
+  {{1, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}},
 },
 //Output(s)
 { // See tools/test_generator/include/TestHarness.h:MixedTyped
@@ -344,7 +344,7 @@
   // int -> INT32 map
   {},
   // int -> QUANT8_ASYMM map
-  {{0, {132, 128, 132, 129, 130, 128, 130, 128}}},
+  {{0, {132, 132, 132, 132, 130, 130, 130, 130, 134, 134, 134, 134, 131, 131, 131, 131}}},
   // int -> QUANT16_SYMM map
   {},
   // int -> FLOAT16 map
diff --git a/runtime/test/generated/models/depthwise_conv2d_per_channel.model.cpp b/runtime/test/generated/models/depthwise_conv2d_per_channel.model.cpp
index 092bd87..d7a7447 100644
--- a/runtime/test/generated/models/depthwise_conv2d_per_channel.model.cpp
+++ b/runtime/test/generated/models/depthwise_conv2d_per_channel.model.cpp
@@ -55,13 +55,13 @@
 
 void CreateModel_same_weight_as_input(Model *model) {
   OperandType type0(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 0.5f, 0);
-  OperandType type10(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({0.5f, 0.5f},3));
+  OperandType type11(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({0.5f, 0.5f},3));
   OperandType type2(Type::TENSOR_INT32, {2});
   OperandType type3(Type::TENSOR_QUANT8_ASYMM, {1, 1, 1, 2}, 1.0f, 0);
   OperandType type4(Type::INT32, {});
   // Phase 1, operands
   auto op1 = model->addOperand(&type0);
-  auto op2 = model->addOperand(&type10);
+  auto op2 = model->addOperand(&type11);
   auto op3 = model->addOperand(&type2);
   auto param = model->addOperand(&type4);
   auto param1 = model->addOperand(&type4);
@@ -103,15 +103,15 @@
 }
 
 void CreateModel_different(Model *model) {
-  OperandType type2(Type::TENSOR_INT32, {2});
   OperandType type4(Type::INT32, {});
   OperandType type5(Type::TENSOR_QUANT8_ASYMM, {1, 3, 3, 2}, 0.5f, 128);
-  OperandType type6(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f},3));
-  OperandType type7(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 1.0f, 128);
+  OperandType type6(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 4}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f, 1.0f, 0.5f},3));
+  OperandType type7(Type::TENSOR_INT32, {4});
+  OperandType type8(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 4}, 1.0f, 128);
   // Phase 1, operands
   auto op11 = model->addOperand(&type5);
   auto op21 = model->addOperand(&type6);
-  auto op31 = model->addOperand(&type2);
+  auto op31 = model->addOperand(&type7);
   auto param8 = model->addOperand(&type4);
   auto param9 = model->addOperand(&type4);
   auto param10 = model->addOperand(&type4);
@@ -120,12 +120,12 @@
   auto param13 = model->addOperand(&type4);
   auto param14 = model->addOperand(&type4);
   auto param15 = model->addOperand(&type4);
-  auto op41 = model->addOperand(&type7);
+  auto op41 = model->addOperand(&type8);
   // Phase 2, operations
-  static int8_t op21_init[] = {1, 1, 1, 1, 1, 1, 1, 1};
-  model->setOperandValue(op21, op21_init, sizeof(int8_t) * 8);
-  static int32_t op31_init[] = {4, 4};
-  model->setOperandValue(op31, op31_init, sizeof(int32_t) * 2);
+  static int8_t op21_init[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+  model->setOperandValue(op21, op21_init, sizeof(int8_t) * 16);
+  static int32_t op31_init[] = {4, 4, 4, 4};
+  model->setOperandValue(op31, op31_init, sizeof(int32_t) * 4);
   static int32_t param8_init[] = {0};
   model->setOperandValue(param8, param8_init, sizeof(int32_t) * 1);
   static int32_t param9_init[] = {0};
@@ -156,15 +156,15 @@
 }
 
 void CreateModel_different_weight_as_input(Model *model) {
-  OperandType type11(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f},3));
-  OperandType type2(Type::TENSOR_INT32, {2});
+  OperandType type12(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 4}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f, 1.0f, 0.5f},3));
   OperandType type4(Type::INT32, {});
   OperandType type5(Type::TENSOR_QUANT8_ASYMM, {1, 3, 3, 2}, 0.5f, 128);
-  OperandType type7(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 1.0f, 128);
+  OperandType type7(Type::TENSOR_INT32, {4});
+  OperandType type8(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 4}, 1.0f, 128);
   // Phase 1, operands
   auto op11 = model->addOperand(&type5);
-  auto op21 = model->addOperand(&type11);
-  auto op31 = model->addOperand(&type2);
+  auto op21 = model->addOperand(&type12);
+  auto op31 = model->addOperand(&type7);
   auto param8 = model->addOperand(&type4);
   auto param9 = model->addOperand(&type4);
   auto param10 = model->addOperand(&type4);
@@ -173,7 +173,7 @@
   auto param13 = model->addOperand(&type4);
   auto param14 = model->addOperand(&type4);
   auto param15 = model->addOperand(&type4);
-  auto op41 = model->addOperand(&type7);
+  auto op41 = model->addOperand(&type8);
   // Phase 2, operations
   static int32_t param8_init[] = {0};
   model->setOperandValue(param8, param8_init, sizeof(int32_t) * 1);
@@ -205,16 +205,16 @@
 }
 
 void CreateModel_layout_nhwc(Model *model) {
-  OperandType type2(Type::TENSOR_INT32, {2});
+  OperandType type10(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 4}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f, 1.0f, 0.5f},3));
   OperandType type4(Type::INT32, {});
   OperandType type5(Type::TENSOR_QUANT8_ASYMM, {1, 3, 3, 2}, 0.5f, 128);
-  OperandType type7(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 1.0f, 128);
-  OperandType type8(Type::BOOL, {});
-  OperandType type9(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f},3));
+  OperandType type7(Type::TENSOR_INT32, {4});
+  OperandType type8(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 4}, 1.0f, 128);
+  OperandType type9(Type::BOOL, {});
   // Phase 1, operands
   auto op12 = model->addOperand(&type5);
-  auto op22 = model->addOperand(&type9);
-  auto op32 = model->addOperand(&type2);
+  auto op22 = model->addOperand(&type10);
+  auto op32 = model->addOperand(&type7);
   auto param16 = model->addOperand(&type4);
   auto param17 = model->addOperand(&type4);
   auto param18 = model->addOperand(&type4);
@@ -223,13 +223,13 @@
   auto param21 = model->addOperand(&type4);
   auto param22 = model->addOperand(&type4);
   auto param23 = model->addOperand(&type4);
-  auto layout = model->addOperand(&type8);
-  auto op42 = model->addOperand(&type7);
+  auto layout = model->addOperand(&type9);
+  auto op42 = model->addOperand(&type8);
   // Phase 2, operations
-  static int8_t op22_init[] = {1, 1, 1, 1, 1, 1, 1, 1};
-  model->setOperandValue(op22, op22_init, sizeof(int8_t) * 8);
-  static int32_t op32_init[] = {4, 4};
-  model->setOperandValue(op32, op32_init, sizeof(int32_t) * 2);
+  static int8_t op22_init[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+  model->setOperandValue(op22, op22_init, sizeof(int8_t) * 16);
+  static int32_t op32_init[] = {4, 4, 4, 4};
+  model->setOperandValue(op32, op32_init, sizeof(int32_t) * 4);
   static int32_t param16_init[] = {0};
   model->setOperandValue(param16, param16_init, sizeof(int32_t) * 1);
   static int32_t param17_init[] = {0};
@@ -262,16 +262,16 @@
 }
 
 void CreateModel_layout_nhwc_weight_as_input(Model *model) {
-  OperandType type12(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f},3));
-  OperandType type2(Type::TENSOR_INT32, {2});
+  OperandType type13(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 4}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f, 1.0f, 0.5f},3));
   OperandType type4(Type::INT32, {});
   OperandType type5(Type::TENSOR_QUANT8_ASYMM, {1, 3, 3, 2}, 0.5f, 128);
-  OperandType type7(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 1.0f, 128);
-  OperandType type8(Type::BOOL, {});
+  OperandType type7(Type::TENSOR_INT32, {4});
+  OperandType type8(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 4}, 1.0f, 128);
+  OperandType type9(Type::BOOL, {});
   // Phase 1, operands
   auto op12 = model->addOperand(&type5);
-  auto op22 = model->addOperand(&type12);
-  auto op32 = model->addOperand(&type2);
+  auto op22 = model->addOperand(&type13);
+  auto op32 = model->addOperand(&type7);
   auto param16 = model->addOperand(&type4);
   auto param17 = model->addOperand(&type4);
   auto param18 = model->addOperand(&type4);
@@ -280,8 +280,8 @@
   auto param21 = model->addOperand(&type4);
   auto param22 = model->addOperand(&type4);
   auto param23 = model->addOperand(&type4);
-  auto layout = model->addOperand(&type8);
-  auto op42 = model->addOperand(&type7);
+  auto layout = model->addOperand(&type9);
+  auto op42 = model->addOperand(&type8);
   // Phase 2, operations
   static int32_t param16_init[] = {0};
   model->setOperandValue(param16, param16_init, sizeof(int32_t) * 1);
@@ -315,16 +315,16 @@
 }
 
 void CreateModel_layout_nchw(Model *model) {
-  OperandType type13(Type::TENSOR_QUANT8_ASYMM, {1, 2, 3, 3}, 0.5f, 128);
-  OperandType type2(Type::TENSOR_INT32, {2});
+  OperandType type10(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 4}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f, 1.0f, 0.5f},3));
+  OperandType type14(Type::TENSOR_QUANT8_ASYMM, {1, 2, 3, 3}, 0.5f, 128);
+  OperandType type15(Type::TENSOR_QUANT8_ASYMM, {1, 4, 2, 2}, 1.0f, 128);
   OperandType type4(Type::INT32, {});
-  OperandType type7(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 1.0f, 128);
-  OperandType type8(Type::BOOL, {});
-  OperandType type9(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f},3));
+  OperandType type7(Type::TENSOR_INT32, {4});
+  OperandType type9(Type::BOOL, {});
   // Phase 1, operands
-  auto op12 = model->addOperand(&type13);
-  auto op22 = model->addOperand(&type9);
-  auto op32 = model->addOperand(&type2);
+  auto op12 = model->addOperand(&type14);
+  auto op22 = model->addOperand(&type10);
+  auto op32 = model->addOperand(&type7);
   auto param16 = model->addOperand(&type4);
   auto param17 = model->addOperand(&type4);
   auto param18 = model->addOperand(&type4);
@@ -333,13 +333,13 @@
   auto param21 = model->addOperand(&type4);
   auto param22 = model->addOperand(&type4);
   auto param23 = model->addOperand(&type4);
-  auto layout = model->addOperand(&type8);
-  auto op42 = model->addOperand(&type7);
+  auto layout = model->addOperand(&type9);
+  auto op42 = model->addOperand(&type15);
   // Phase 2, operations
-  static int8_t op22_init[] = {1, 1, 1, 1, 1, 1, 1, 1};
-  model->setOperandValue(op22, op22_init, sizeof(int8_t) * 8);
-  static int32_t op32_init[] = {4, 4};
-  model->setOperandValue(op32, op32_init, sizeof(int32_t) * 2);
+  static int8_t op22_init[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+  model->setOperandValue(op22, op22_init, sizeof(int8_t) * 16);
+  static int32_t op32_init[] = {4, 4, 4, 4};
+  model->setOperandValue(op32, op32_init, sizeof(int32_t) * 4);
   static int32_t param16_init[] = {0};
   model->setOperandValue(param16, param16_init, sizeof(int32_t) * 1);
   static int32_t param17_init[] = {0};
@@ -372,16 +372,16 @@
 }
 
 void CreateModel_layout_nchw_weight_as_input(Model *model) {
-  OperandType type13(Type::TENSOR_QUANT8_ASYMM, {1, 2, 3, 3}, 0.5f, 128);
-  OperandType type14(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 2}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f},3));
-  OperandType type2(Type::TENSOR_INT32, {2});
+  OperandType type14(Type::TENSOR_QUANT8_ASYMM, {1, 2, 3, 3}, 0.5f, 128);
+  OperandType type15(Type::TENSOR_QUANT8_ASYMM, {1, 4, 2, 2}, 1.0f, 128);
+  OperandType type16(Type::TENSOR_QUANT8_SYMM_PER_CHANNEL, {1, 2, 2, 4}, 0.0f, 0, SymmPerChannelQuantParams({1.0f, 0.5f, 1.0f, 0.5f},3));
   OperandType type4(Type::INT32, {});
-  OperandType type7(Type::TENSOR_QUANT8_ASYMM, {1, 2, 2, 2}, 1.0f, 128);
-  OperandType type8(Type::BOOL, {});
+  OperandType type7(Type::TENSOR_INT32, {4});
+  OperandType type9(Type::BOOL, {});
   // Phase 1, operands
-  auto op12 = model->addOperand(&type13);
-  auto op22 = model->addOperand(&type14);
-  auto op32 = model->addOperand(&type2);
+  auto op12 = model->addOperand(&type14);
+  auto op22 = model->addOperand(&type16);
+  auto op32 = model->addOperand(&type7);
   auto param16 = model->addOperand(&type4);
   auto param17 = model->addOperand(&type4);
   auto param18 = model->addOperand(&type4);
@@ -390,8 +390,8 @@
   auto param21 = model->addOperand(&type4);
   auto param22 = model->addOperand(&type4);
   auto param23 = model->addOperand(&type4);
-  auto layout = model->addOperand(&type8);
-  auto op42 = model->addOperand(&type7);
+  auto layout = model->addOperand(&type9);
+  auto op42 = model->addOperand(&type15);
   // Phase 2, operations
   static int32_t param16_init[] = {0};
   model->setOperandValue(param16, param16_init, sizeof(int32_t) * 1);
diff --git a/runtime/test/generated/vts_models/depthwise_conv2d_per_channel.model.cpp b/runtime/test/generated/vts_models/depthwise_conv2d_per_channel.model.cpp
index 877a360..484f86c 100644
--- a/runtime/test/generated/vts_models/depthwise_conv2d_per_channel.model.cpp
+++ b/runtime/test/generated/vts_models/depthwise_conv2d_per_channel.model.cpp
@@ -308,58 +308,22 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 0, .length = 8},
+            .location = {.poolIndex = 0, .offset = 0, .length = 16},
             .extraParams = std::move(extraParams1),
         },
         {
             .type = OperandType::TENSOR_INT32,
-            .dimensions = {2},
+            .dimensions = {4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 8, .length = 8},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 16, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 20, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 24, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 28, .length = 4},
+            .location = {.poolIndex = 0, .offset = 16, .length = 16},
         },
         {
             .type = OperandType::INT32,
@@ -398,8 +362,44 @@
             .location = {.poolIndex = 0, .offset = 44, .length = 4},
         },
         {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 48, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 52, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 56, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 60, .length = 4},
+        },
+        {
             .type = OperandType::TENSOR_QUANT8_ASYMM,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 0,
             .scale = 1.0f,
             .zeroPoint = 128,
@@ -419,7 +419,7 @@
     const std::vector<uint32_t> inputIndexes = {0};
     const std::vector<uint32_t> outputIndexes = {11};
     std::vector<uint8_t> operandValues = {
-      1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
     };
     const std::vector<hidl_memory> pools = {};
 
@@ -454,7 +454,7 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
@@ -464,7 +464,7 @@
         },
         {
             .type = OperandType::TENSOR_INT32,
-            .dimensions = {2},
+            .dimensions = {4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
@@ -545,7 +545,7 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_ASYMM,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 0,
             .scale = 1.0f,
             .zeroPoint = 128,
@@ -600,58 +600,22 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 0, .length = 8},
+            .location = {.poolIndex = 0, .offset = 0, .length = 16},
             .extraParams = std::move(extraParams1),
         },
         {
             .type = OperandType::TENSOR_INT32,
-            .dimensions = {2},
+            .dimensions = {4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 8, .length = 8},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 16, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 20, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 24, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 28, .length = 4},
+            .location = {.poolIndex = 0, .offset = 16, .length = 16},
         },
         {
             .type = OperandType::INT32,
@@ -690,17 +654,53 @@
             .location = {.poolIndex = 0, .offset = 44, .length = 4},
         },
         {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 48, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 52, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 56, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 60, .length = 4},
+        },
+        {
             .type = OperandType::BOOL,
             .dimensions = {},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 48, .length = 1},
+            .location = {.poolIndex = 0, .offset = 64, .length = 1},
         },
         {
             .type = OperandType::TENSOR_QUANT8_ASYMM,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 0,
             .scale = 1.0f,
             .zeroPoint = 128,
@@ -720,7 +720,7 @@
     const std::vector<uint32_t> inputIndexes = {0};
     const std::vector<uint32_t> outputIndexes = {12};
     std::vector<uint8_t> operandValues = {
-      1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0
     };
     const std::vector<hidl_memory> pools = {};
 
@@ -755,7 +755,7 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
@@ -765,7 +765,7 @@
         },
         {
             .type = OperandType::TENSOR_INT32,
-            .dimensions = {2},
+            .dimensions = {4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
@@ -855,7 +855,7 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_ASYMM,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 0,
             .scale = 1.0f,
             .zeroPoint = 128,
@@ -910,58 +910,22 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 0, .length = 8},
+            .location = {.poolIndex = 0, .offset = 0, .length = 16},
             .extraParams = std::move(extraParams1),
         },
         {
             .type = OperandType::TENSOR_INT32,
-            .dimensions = {2},
+            .dimensions = {4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 8, .length = 8},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 16, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 20, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 24, .length = 4},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 28, .length = 4},
+            .location = {.poolIndex = 0, .offset = 16, .length = 16},
         },
         {
             .type = OperandType::INT32,
@@ -1000,17 +964,53 @@
             .location = {.poolIndex = 0, .offset = 44, .length = 4},
         },
         {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 48, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 52, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 56, .length = 4},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 60, .length = 4},
+        },
+        {
             .type = OperandType::BOOL,
             .dimensions = {},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 48, .length = 1},
+            .location = {.poolIndex = 0, .offset = 64, .length = 1},
         },
         {
             .type = OperandType::TENSOR_QUANT8_ASYMM,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 4, 2, 2},
             .numberOfConsumers = 0,
             .scale = 1.0f,
             .zeroPoint = 128,
@@ -1030,7 +1030,7 @@
     const std::vector<uint32_t> inputIndexes = {0};
     const std::vector<uint32_t> outputIndexes = {12};
     std::vector<uint8_t> operandValues = {
-      1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1
+      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1
     };
     const std::vector<hidl_memory> pools = {};
 
@@ -1065,7 +1065,7 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 2, 2, 4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
@@ -1075,7 +1075,7 @@
         },
         {
             .type = OperandType::TENSOR_INT32,
-            .dimensions = {2},
+            .dimensions = {4},
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
@@ -1165,7 +1165,7 @@
         },
         {
             .type = OperandType::TENSOR_QUANT8_ASYMM,
-            .dimensions = {1, 2, 2, 2},
+            .dimensions = {1, 4, 2, 2},
             .numberOfConsumers = 0,
             .scale = 1.0f,
             .zeroPoint = 128,
diff --git a/runtime/test/specs/V1_2/depthwise_conv2d_per_channel.mod.py b/runtime/test/specs/V1_2/depthwise_conv2d_per_channel.mod.py
index 152a808..2df79ee 100644
--- a/runtime/test/specs/V1_2/depthwise_conv2d_per_channel.mod.py
+++ b/runtime/test/specs/V1_2/depthwise_conv2d_per_channel.mod.py
@@ -31,17 +31,18 @@
 
 # TEST 2: Different scales, zeroPoint=128
 i2 = Input("op1", "TENSOR_QUANT8_ASYMM", "{1, 3, 3, 2}, 0.5f, 128")
-f2 = Parameter("op2", "TENSOR_QUANT8_SYMM_PER_CHANNEL", "{1, 2, 2, 2}, 0.0f, 0",
-               [1, 1, 1, 1, 1, 1, 1, 1],
-               extraParams = SymmPerChannelQuantParams(channelDim=3, scales=[1.0, 0.5]))
-b2 = Parameter("op3", "TENSOR_INT32", "{2}", [4, 4])
-o2 = Output("op4", "TENSOR_QUANT8_ASYMM", "{1, 2, 2, 2}, 1.f, 128")
+f2 = Parameter("op2", "TENSOR_QUANT8_SYMM_PER_CHANNEL", "{1, 2, 2, 4}, 0.0f, 0",
+               [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+               extraParams = SymmPerChannelQuantParams(channelDim=3, scales=[1.0, 0.5, 1.0, 0.5]))
+b2 = Parameter("op3", "TENSOR_INT32", "{4}", [4, 4, 4, 4])
+o2 = Output("op4", "TENSOR_QUANT8_ASYMM", "{1, 2, 2, 4}, 1.f, 128")
 Model("different").Operation("DEPTHWISE_CONV_2D", i2, f2, b2, 0, 0, 0, 0, 1, 1, 2, 0).To(o2)
 
 # Instantiate an example
 Example({
     i2: [129, 130] * 9,
-    o2: [132, 130, 128, 128, 132, 130, 129, 128],
+    o2: [132, 130, 134, 131, 132, 130, 134, 131,
+         132, 130, 134, 131, 132, 130, 134, 131],
 }).AddInput(f2, b2)
 
 
@@ -49,15 +50,16 @@
 
 # TEST 3: With layout param
 i3 = Input("op1", "TENSOR_QUANT8_ASYMM", "{1, 3, 3, 2}, 0.5f, 128")
-f3 = Parameter("op2", "TENSOR_QUANT8_SYMM_PER_CHANNEL", "{1, 2, 2, 2}, 0.0f, 0",
-               [1, 1, 1, 1, 1, 1, 1, 1],
-               extraParams = SymmPerChannelQuantParams(channelDim=3, scales=[1.0, 0.5]))
-b3 = Parameter("op3", "TENSOR_INT32", "{2}", [4, 4])
-o3 = Output("op4", "TENSOR_QUANT8_ASYMM", "{1, 2, 2, 2}, 1.f, 128")
+f3 = Parameter("op2", "TENSOR_QUANT8_SYMM_PER_CHANNEL", "{1, 2, 2, 4}, 0.0f, 0",
+               [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+               extraParams = SymmPerChannelQuantParams(channelDim=3, scales=[1.0, 0.5, 1.0, 0.5]))
+b3 = Parameter("op3", "TENSOR_INT32", "{4}", [4, 4, 4, 4])
+o3 = Output("op4", "TENSOR_QUANT8_ASYMM", "{1, 2, 2, 4}, 1.f, 128")
 Model("layout").Operation("DEPTHWISE_CONV_2D", i3, f3, b3, 0, 0, 0, 0, 1, 1, 2, 0, layout).To(o3)
 
 # Instantiate an example
 Example({
     i3: [129, 130] * 9,
-    o3: [132, 130, 128, 128, 132, 130, 129, 128],
+    o3: [132, 130, 134, 131, 132, 130, 134, 131,
+         132, 130, 134, 131, 132, 130, 134, 131],
 }).AddNchw(i3, o3, layout).AddInput(f3, b3)