1 // 2 // Copyright © 2021 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include "ParserFlatbuffersSerializeFixture.hpp" 7 8 #include <armnnDeserializer/IDeserializer.hpp> 9 10 #include <doctest/doctest.h> 11 12 #include <string> 13 14 TEST_SUITE("Deserializer_DepthwiseConv2d") 15 { 16 struct DepthwiseConv2dFlatbufferVersion1FixtureOld : public ParserFlatbuffersSerializeFixture 17 { DepthwiseConv2dFlatbufferVersion1FixtureOldDepthwiseConv2dFlatbufferVersion1FixtureOld18 explicit DepthwiseConv2dFlatbufferVersion1FixtureOld() 19 { 20 m_JsonString = R"( 21 { 22 "layers": [ 23 { 24 "layer_type": "InputLayer", 25 "layer": { 26 "base": { 27 "base": { 28 "index": 0, 29 "layerName": "Input", 30 "layerType": "Input", 31 "inputSlots": [ 32 33 ], 34 "outputSlots": [ 35 { 36 "index": 0, 37 "tensorInfo": { 38 "dimensions": [ 39 1, 40 3, 41 3, 42 3 43 ], 44 "dataType": "QAsymmS8", 45 "quantizationScale": 1.0, 46 "quantizationOffset": 0, 47 "quantizationDim": 0, 48 "dimensionality": 1, 49 "dimensionSpecificity": [ 50 true, 51 true, 52 true, 53 true 54 ] 55 } 56 } 57 ] 58 }, 59 "layerBindingId": 0 60 } 61 } 62 }, 63 { 64 "layer_type": "DepthwiseConvolution2dLayer", 65 "layer": { 66 "base": { 67 "index": 1, 68 "layerName": "depwiseConvolution2dWithPerAxis", 69 "layerType": "DepthwiseConvolution2d", 70 "inputSlots": [ 71 { 72 "index": 0, 73 "connection": { 74 "sourceLayerIndex": 0, 75 "outputSlotIndex": 0 76 } 77 } 78 ], 79 "outputSlots": [ 80 { 81 "index": 0, 82 "tensorInfo": { 83 "dimensions": [ 84 1, 85 3, 86 3, 87 3 88 ], 89 "dataType": "QAsymmS8", 90 "quantizationScale": 1.0, 91 "quantizationOffset": 0, 92 "quantizationDim": 0, 93 "dimensionality": 1, 94 "dimensionSpecificity": [ 95 true, 96 true, 97 true, 98 true 99 ] 100 } 101 } 102 ] 103 }, 104 "descriptor": { 105 "padLeft": 1, 106 "padRight": 1, 107 "padTop": 1, 108 "padBottom": 1, 109 "strideX": 1, 110 "strideY": 1, 111 "dilationX": 1, 112 "dilationY": 1, 113 "biasEnabled": false, 114 "dataLayout": "NHWC" 115 }, 116 "weights": { 117 "info": { 118 "dimensions": [ 119 1, 120 3, 121 3, 122 3 123 ], 124 "dataType": "QSymmS8", 125 "quantizationScale": 0.25, 126 "quantizationOffset": 0, 127 "quantizationScales": [ 128 0.25, 129 0.2, 130 0.1 131 ], 132 "quantizationDim": 0, 133 "dimensionality": 1, 134 "dimensionSpecificity": [ 135 true, 136 true, 137 true, 138 true 139 ] 140 }, 141 "data_type": "ByteData", 142 "data": { 143 "data": [ 144 4, 145 20, 146 0, 147 8, 148 20, 149 30, 150 4, 151 0, 152 10, 153 12, 154 0, 155 40, 156 0, 157 5, 158 30, 159 16, 160 10, 161 40, 162 12, 163 0, 164 30, 165 16, 166 20, 167 0, 168 12, 169 20, 170 20 171 ] 172 } 173 } 174 } 175 }, 176 { 177 "layer_type": "OutputLayer", 178 "layer": { 179 "base": { 180 "base": { 181 "index": 2, 182 "layerName": "Output", 183 "layerType": "Output", 184 "inputSlots": [ 185 { 186 "index": 0, 187 "connection": { 188 "sourceLayerIndex": 1, 189 "outputSlotIndex": 0 190 } 191 } 192 ], 193 "outputSlots": [ 194 195 ] 196 }, 197 "layerBindingId": 0 198 } 199 } 200 } 201 ], 202 "inputIds": [ 203 0 204 ], 205 "outputIds": [ 206 0 207 ], 208 "featureVersions": { 209 "bindingIdsScheme": 1 210 } 211 } 212 )"; 213 SetupSingleInputSingleOutput("Input", "Output"); 214 } 215 }; 216 217 struct DepthwiseConv2dFlatbufferVersion1Fixture : public ParserFlatbuffersSerializeFixture 218 { DepthwiseConv2dFlatbufferVersion1FixtureDepthwiseConv2dFlatbufferVersion1Fixture219 explicit DepthwiseConv2dFlatbufferVersion1Fixture() 220 { 221 m_JsonString = R"( 222 { 223 "layers": [ 224 { 225 "layer_type": "InputLayer", 226 "layer": { 227 "base": { 228 "base": { 229 "index": 0, 230 "layerName": "InputLayer", 231 "layerType": "Input", 232 "inputSlots": [ 233 ], 234 "outputSlots": [ 235 { 236 "index": 0, 237 "tensorInfo": { 238 "dimensions": [ 239 1, 240 3, 241 3, 242 3 243 ], 244 "dataType": "QAsymmS8", 245 "quantizationScale": 1.0, 246 "quantizationOffset": 0, 247 "quantizationDim": 0, 248 "dimensionality": 1, 249 "dimensionSpecificity": [ 250 true, 251 true, 252 true, 253 true 254 ] 255 } 256 } 257 ] 258 }, 259 "layerBindingId": 0 260 } 261 } 262 }, 263 { 264 "layer_type": "DepthwiseConvolution2dLayer", 265 "layer": { 266 "base": { 267 "index": 1, 268 "layerName": "depthwiseConvolution2dWithPerAxis", 269 "layerType": "DepthwiseConvolution2d", 270 "inputSlots": [ 271 { 272 "index": 0, 273 "connection": { 274 "sourceLayerIndex": 0, 275 "outputSlotIndex": 0 276 } 277 }, 278 { 279 "index": 1, 280 "connection": { 281 "sourceLayerIndex": 2, 282 "outputSlotIndex": 0 283 } 284 } 285 ], 286 "outputSlots": [ 287 { 288 "index": 0, 289 "tensorInfo": { 290 "dimensions": [ 291 1, 292 3, 293 3, 294 3 295 ], 296 "dataType": "QAsymmS8", 297 "quantizationScale": 1.0, 298 "quantizationOffset": 0, 299 "quantizationDim": 0, 300 "dimensionality": 1, 301 "dimensionSpecificity": [ 302 true, 303 true, 304 true, 305 true 306 ] 307 } 308 } 309 ] 310 }, 311 "descriptor": { 312 "padLeft": 1, 313 "padRight": 1, 314 "padTop": 1, 315 "padBottom": 1, 316 "strideX": 1, 317 "strideY": 1, 318 "dilationX": 1, 319 "dilationY": 1, 320 "biasEnabled": false, 321 "dataLayout": "NHWC" 322 } 323 } 324 }, 325 { 326 "layer_type": "ConstantLayer", 327 "layer": { 328 "base": { 329 "index": 2, 330 "layerName": "Weights", 331 "layerType": "Constant", 332 "inputSlots": [ 333 ], 334 "outputSlots": [ 335 { 336 "index": 0, 337 "tensorInfo": { 338 "dimensions": [ 339 1, 340 3, 341 3, 342 3 343 ], 344 "dataType": "QSymmS8", 345 "quantizationScale": 0.25, 346 "quantizationOffset": 0, 347 "quantizationDim": 0, 348 "dimensionality": 1, 349 "dimensionSpecificity": [ 350 true, 351 true, 352 true, 353 true 354 ], 355 quantizationScales: [ 356 0.25, 357 0.2, 358 0.1 359 ], 360 "isConstant": true, 361 } 362 } 363 ] 364 }, 365 "input": { 366 "info": { 367 "dimensions": [ 368 1, 369 3, 370 3, 371 3 372 ], 373 "dataType": "QSymmS8", 374 "quantizationScale": 0.25, 375 "quantizationOffset": 0, 376 "quantizationDim": 0, 377 "dimensionality": 1, 378 "dimensionSpecificity": [ 379 true, 380 true, 381 true, 382 true 383 ], 384 quantizationScales: [ 385 0.25, 386 0.2, 387 0.1 388 ] 389 }, 390 "data_type": "ByteData", 391 "data": { 392 "data": [ 393 4, 394 20, 395 0, 396 8, 397 20, 398 30, 399 4, 400 0, 401 10, 402 12, 403 0, 404 40, 405 0, 406 5, 407 30, 408 16, 409 10, 410 40, 411 12, 412 0, 413 30, 414 16, 415 20, 416 0, 417 12, 418 20, 419 20 420 ] 421 } 422 } 423 } 424 }, 425 { 426 "layer_type": "OutputLayer", 427 "layer": { 428 "base": { 429 "base": { 430 "index": 3, 431 "layerName": "OutputLayer", 432 "layerType": "Output", 433 "inputSlots": [ 434 { 435 "index": 0, 436 "connection": { 437 "sourceLayerIndex": 1, 438 "outputSlotIndex": 0 439 } 440 } 441 ], 442 "outputSlots": [ 443 ] 444 }, 445 "layerBindingId": 0 446 } 447 } 448 } 449 ], 450 "inputIds": [ 451 0 452 ], 453 "outputIds": [ 454 0 455 ], 456 "featureVersions": { 457 "bindingIdsScheme": 1, 458 "constantTensorsAsInputs": 1 459 } 460 } 461 )"; 462 Setup(); 463 } 464 }; 465 466 // This test uses a model that was created before weights layout scheme version was added to our flatbuffers 467 // file. It ensures older models can still be read and executed 468 // featureVersion weights layout scheme 1 indicates a change in the depthwise weights layout within 469 // armm from [M,I,H,W] --> [1,H,W,I*M] 470 TEST_CASE_FIXTURE(DepthwiseConv2dFlatbufferVersion1FixtureOld, "DepthwiseConv2d_FlatbufferVersion1Old") 471 { 472 RunTest<4, armnn::DataType::QAsymmS8>( 473 0, 474 { 3,2,0,0,4,3,0,1,2, 475 0,1,3,0,4,2,2,2,3, 476 2,4,3,2,0,4,3,4,0}, 477 { 15,60,10,11,37,20, 0,18,17, 478 20,65,28,28,74,26,12,20,18, 479 25,36,12,37,42,25,29,14, 9}); 480 } 481 482 TEST_CASE_FIXTURE(DepthwiseConv2dFlatbufferVersion1Fixture, 483 "DepthwiseConv2d_FlatbufferVersion1_WeightsAndBiasesAsConstantLayers") 484 { 485 RunTest<4, armnn::DataType::QAsymmS8>( 486 0, 487 {{"InputLayer", { 3,2,0,0,4,3,0,1,2, 488 0,1,3,0,4,2,2,2,3, 489 2,4,3,2,0,4,3,4,0}}}, 490 {{"OutputLayer", { 15,60,10,11,37,20, 0,18,17, 491 20,65,28,28,74,26,12,20,18, 492 25,36,12,37,42,25,29,14, 9}}}); 493 } 494 495 }