From c1a978391b16dbbe634bc3338562066a75a6c678 Mon Sep 17 00:00:00 2001 From: Eric Kunze Date: Fri, 1 Jul 2022 16:56:09 -0700 Subject: Align padding for transpose_conv2d to match spec Increasing out pad values now leads to increasing pad. Reference model changes, and test generator changes to match specification definition Change-Id: I4f3ebfbca5048354fb15bedc7ab640ff28ed853a Signed-off-by: Eric Kunze Signed-off-by: Jeremy Johnson --- reference_model/src/ops/tensor_ops.cc | 22 ++++++++-------- verif/generator/tosa_arg_gen.py | 22 +++++++++++----- verif/generator/tosa_error_if.py | 47 ++++++++++++++++++++++++++--------- verif/generator/tosa_test_gen.py | 2 +- 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/reference_model/src/ops/tensor_ops.cc b/reference_model/src/ops/tensor_ops.cc index 03cb9fb..ef6dfa7 100644 --- a/reference_model/src/ops/tensor_ops.cc +++ b/reference_model/src/ops/tensor_ops.cc @@ -1498,14 +1498,7 @@ int OpTransposeConv2d::checkTensorAttributes() return 1; } - for (int32_t i : attribute->out_pad()) - { - if (i < 0) - { - printNodeValidationError("OpTransposeConv2d: At least one pad is smaller than zero"); - return 1; - } - } + for (int32_t i : attribute->stride()) { @@ -1540,8 +1533,13 @@ int OpTransposeConv2d::checkTensorAttributes() int32_t out_pad_left = attribute->out_pad()[2]; int32_t out_pad_right = attribute->out_pad()[3]; - int32_t H = (IH - 1) * stride_y - out_pad_top - out_pad_bottom + kernel_h; - int32_t W = (IW - 1) * stride_x - out_pad_left - out_pad_right + kernel_w; + for (size_t i = 0; i < attribute->out_pad().size(); i++) + { + ERROR_IF(attribute->out_pad()[i] <= -(weight->getShape()[(i / 2) + 1]), "OpTransposeConv2d: At least one out_pad value is larger than kernel size"); + } + + int32_t H = (IH - 1) * stride_y + out_pad_top + out_pad_bottom + kernel_h; + int32_t W = (IW - 1) * stride_x + out_pad_left + out_pad_right + kernel_w; if ((OH != H) || (OW != W)) { @@ -1632,8 +1630,8 @@ int OpTransposeConv2d::eval() { for (int iw = 0; iw < in_width; iw++) { - out_x_origin = iw * stride_w - out_pad_left; - out_y_origin = ih * stride_h - out_pad_top; + out_x_origin = iw * stride_w + out_pad_left; + out_y_origin = ih * stride_h + out_pad_top; for (int ic = 0; ic < in_channels; ic++) { for (int fh = 0; fh < f_height; fh++) diff --git a/verif/generator/tosa_arg_gen.py b/verif/generator/tosa_arg_gen.py index 2596bec..ef84762 100644 --- a/verif/generator/tosa_arg_gen.py +++ b/verif/generator/tosa_arg_gen.py @@ -1111,10 +1111,15 @@ class TosaArgGen: # Generate comprehensive argument lists # - except for named errors, which use specific invalid value(s) - if error_name == ErrorIf.PadSmallerZero: - p_vals = [testGen.rng.choice(range(-5, 0))] + smallest_padding_size = -min(filter_shape[1], filter_shape[2]) + 1 + if error_name == ErrorIf.PadLargerEqualKernel: + max_filter_size = -max(filter_shape[1], filter_shape[2]) + p_vals = [testGen.rng.choice(range(max_filter_size - 10, max_filter_size))] else: - p_vals = [x for x in range(0, testGen.args.max_conv_padding + 1)] + p_vals = [ + x + for x in range(smallest_padding_size, testGen.args.max_conv_padding + 1) + ] paddings = {x for x in itertools.product(*([p_vals] * 4))} if error_name == ErrorIf.StrideSmallerOne: # Can't use stride=0, as it is used to derive output shape, as a divisor @@ -1128,7 +1133,12 @@ class TosaArgGen: if max(ifm_shape) < 64: bigPadding = 9 paddings.update( - {x for x in itertools.product(*([[0, bigPadding]] * 4))} + { + x + for x in itertools.product( + *([[smallest_padding_size, bigPadding]] * 4) + ) + } ) bigStride = 8 strides.update({x for x in itertools.product(*([[1, bigStride]] * 2))}) @@ -1150,8 +1160,8 @@ class TosaArgGen: for p in sorted(list(paddings)): if n % sparsity == 0: # Determine the output shape - oh = (ifm_shape[1] - 1) * s[0] - p[0] - p[1] + filter_shape[1] - ow = (ifm_shape[2] - 1) * s[1] - p[2] - p[3] + filter_shape[2] + oh = (ifm_shape[1] - 1) * s[0] + p[0] + p[1] + filter_shape[1] + ow = (ifm_shape[2] - 1) * s[1] + p[2] + p[3] + filter_shape[2] os = [ifm_shape[0], oh, ow, filter_shape[0]] arg_list.append( ( diff --git a/verif/generator/tosa_error_if.py b/verif/generator/tosa_error_if.py index e4e60b7..f9a00f9 100644 --- a/verif/generator/tosa_error_if.py +++ b/verif/generator/tosa_error_if.py @@ -1261,15 +1261,28 @@ class TosaErrorValidator: if check: pad = kwargs["pad"] - kernel = kwargs["kernel"] - if min(pad) > 0 and min(kernel) > 1: + op = kwargs["op"] + if op["op"] == Op.TRANSPOSE_CONV2D: + # transpose_conv2d + kernel = kwargs["weight_shape"][1:-1] if ( - pad[0] >= kernel[0] - or pad[1] >= kernel[0] - or pad[2] >= kernel[1] - or pad[3] >= kernel[1] + pad[0] <= -kernel[0] + or pad[1] <= -kernel[0] + or pad[2] <= -kernel[1] + or pad[3] <= -kernel[1] ): error_result = True + else: + # pooling op + kernel = kwargs["kernel"] + if min(pad) > 0 and min(kernel) > 1: + if ( + pad[0] >= kernel[0] + or pad[1] >= kernel[0] + or pad[2] >= kernel[1] + or pad[3] >= kernel[1] + ): + error_result = True info_dict = { "error_name": error_name, @@ -1400,12 +1413,22 @@ class TosaErrorValidator: return info_dict @staticmethod - def checkConvParams(weight_shape, stride, pad, dilation): + def checkConvParams(op, weight_shape, stride, pad, dilation): + if op == Op.TRANSPOSE_CONV2D: + pad_ok = ( + pad[0] > -weight_shape[1] + and pad[1] > -weight_shape[1] + and pad[2] > -weight_shape[2] + and pad[3] > -weight_shape[2] + ) + else: + pad_ok = min(pad) >= 0 + return ( # Check kernel sizes min(weight_shape[1:-1]) >= 1 and min(stride) >= 1 - and min(pad) >= 0 + and pad_ok and (dilation is None or min(dilation) >= 1) ) @@ -1437,8 +1460,8 @@ class TosaErrorValidator: if op["op"] == Op.TRANSPOSE_CONV2D: dims_correct.append( (input_shape[index + 1] - 1) * stride[index] - - pad[pad_offset] - - pad[pad_offset + 1] + + pad[pad_offset] + + pad[pad_offset + 1] + weight_shape[index + kernel_offset] ) else: @@ -1457,7 +1480,7 @@ class TosaErrorValidator: # ensure parameters are valid params_valid = TosaErrorValidator.checkConvParams( - weight_shape, stride, pad, dilation + op["op"], weight_shape, stride, pad, dilation ) if params_valid and output_shape[1:-1] != dims_correct: @@ -1507,7 +1530,7 @@ class TosaErrorValidator: # ensure parameters are valid params_valid = TosaErrorValidator.checkConvParams( - weight_shape, stride, pad, dilation + op["op"], weight_shape, stride, pad, dilation ) if params_valid and max(remainders) > 0: error_result = True diff --git a/verif/generator/tosa_test_gen.py b/verif/generator/tosa_test_gen.py index 53d38dd..ce3f81f 100644 --- a/verif/generator/tosa_test_gen.py +++ b/verif/generator/tosa_test_gen.py @@ -2605,7 +2605,7 @@ class TosaTestGen: TosaErrorValidator.evWrongOutputList, TosaErrorValidator.evInputZeroPointNotZero, TosaErrorValidator.evWeightZeroPointNotZero, - TosaErrorValidator.evPadSmallerZero, + TosaErrorValidator.evPadLargerEqualKernel, TosaErrorValidator.evStrideSmallerOne, TosaErrorValidator.evWrongRank, TosaErrorValidator.evConvOutputShapeMismatch, -- cgit v1.2.1