diff --git a/src/relay/op/contrib/ethosu/depthwise.cc b/src/relay/op/contrib/ethosu/depthwise.cc index fa73645d45de..b102ce26c912 100644 --- a/src/relay/op/contrib/ethosu/depthwise.cc +++ b/src/relay/op/contrib/ethosu/depthwise.cc @@ -126,7 +126,7 @@ bool EthosuDepthwiseConv2DRel(const Array& types, int num_inputs, const At ICHECK(ifm->dtype == DataType::UInt(8) || ifm->dtype == DataType::Int(8)) << "Expected ethosu_depthwise_conv2d type(uint8) or type(int8) for ifm but was " << ifm->dtype; - ICHECK(weight->dtype == DataType::UInt(8) || ifm->dtype == DataType::Int(8)) + ICHECK(weight->dtype == DataType::UInt(8) || weight->dtype == DataType::Int(8)) << "Expected ethosu_depthwise_conv2d type(uint8) or type(int8) for weight but was " << weight->dtype; ICHECK(scale_bias->dtype == DataType::UInt(8)) diff --git a/tests/python/contrib/test_ethosu/test_replace_depthwise_conv2d.py b/tests/python/contrib/test_ethosu/test_replace_depthwise_conv2d.py index b3ce74c4e84a..93a2f9e133ce 100644 --- a/tests/python/contrib/test_ethosu/test_replace_depthwise_conv2d.py +++ b/tests/python/contrib/test_ethosu/test_replace_depthwise_conv2d.py @@ -23,22 +23,83 @@ from tvm import relay from tvm.relay.testing import run_opt_pass from tvm.relay.backend.contrib.ethosu.tir.compiler import lower_to_tir + from .infra import make_ethosu_depthwise_conv2d, get_convolutional_args @pytest.mark.parametrize( "trial", [ - [(1, 8, 8, 3), 3, (3, 2), (0, 0), (1, 1), (1, 1), "CLIP", "NHWC", "NHWC"], - [(1, 8, 8, 3), 3, (1, 1), (2, 1), (1, 1), (1, 1), "TANH", "NHWC", "NHWC"], - [(1, 8, 8, 3), 3, (1, 1), (0, 0), (1, 1), (1, 1), "NONE", "NHWC", "NHWC"], - [(1, 1, 1, 1), 1, (1, 1), (0, 0), (1, 1), (1, 1), "CLIP", "NHWC", "NHWC"], - [(1, 7, 9, 4), 4, (3, 2), (1, 2), (2, 1), (1, 2), "SIGMOID", "NHWC", "NHWC"], - [(1, 8, 2, 8, 16), 18, (1, 1), (2, 1), (1, 1), (1, 1), "CLIP", "NHCWB16", "NHWC"], - [(1, 7, 9, 40), 40, (3, 2), (1, 2), (2, 1), (1, 2), "CLIP", "NHWC", "NHCWB16"], - [(1, 4, 12, 9, 16), 182, (2, 3), (6, 3), (2, 2), (1, 1), "CLIP", "NHCWB16", "NHCWB16"], - [(1, 7, 9, 4), 4, (3, 2), (1, 2), (2, 1), (2, 2), "CLIP", "NHWC", "NHWC"], - [(1, 7, 9, 41), 41, (3, 2), (1, 2), (2, 1), (2, 2), "CLIP", "NHWC", "NHCWB16"], + [(1, 8, 8, 3), 3, (3, 2), (0, 0), (1, 1), (1, 1), "CLIP", "NHWC", "NHWC", "int8", "int8"], + [(1, 8, 8, 3), 3, (1, 1), (2, 1), (1, 1), (1, 1), "TANH", "NHWC", "NHWC", "int8", "int8"], + [(1, 8, 8, 3), 3, (1, 1), (0, 0), (1, 1), (1, 1), "NONE", "NHWC", "NHWC", "uint8", "int8"], + [(1, 1, 1, 1), 1, (1, 1), (0, 0), (1, 1), (1, 1), "CLIP", "NHWC", "NHWC", "uint8", "int8"], + [ + (1, 7, 9, 4), + 4, + (3, 2), + (1, 2), + (2, 1), + (1, 2), + "SIGMOID", + "NHWC", + "NHWC", + "uint8", + "uint8", + ], + [ + (1, 8, 2, 8, 16), + 18, + (1, 1), + (2, 1), + (1, 1), + (1, 1), + "CLIP", + "NHCWB16", + "NHWC", + "int8", + "int8", + ], + [ + (1, 7, 9, 40), + 40, + (3, 2), + (1, 2), + (2, 1), + (1, 2), + "CLIP", + "NHWC", + "NHCWB16", + "int8", + "int8", + ], + [ + (1, 4, 12, 9, 16), + 182, + (2, 3), + (6, 3), + (2, 2), + (1, 1), + "CLIP", + "NHCWB16", + "NHCWB16", + "int8", + "int8", + ], + [(1, 7, 9, 4), 4, (3, 2), (1, 2), (2, 1), (2, 2), "CLIP", "NHWC", "NHWC", "int8", "int8"], + [ + (1, 7, 9, 41), + 41, + (3, 2), + (1, 2), + (2, 1), + (2, 2), + "CLIP", + "NHWC", + "NHCWB16", + "int8", + "int8", + ], [ (1, 13, 12, 19, 16), 182, @@ -49,6 +110,8 @@ "CLIP", "NHCWB16", "NHCWB16", + "int8", + "int8", ], ], ) @@ -63,8 +126,10 @@ def _get_func( activation, ifm_layout, ofm_layout, + dtype, + weight_dtype, ): - ifm = relay.var("ifm", shape=ifm_shape, dtype="int8") + ifm = relay.var("ifm", shape=ifm_shape, dtype=dtype) depthwise = make_ethosu_depthwise_conv2d( ifm, channels, @@ -75,6 +140,7 @@ def _get_func( activation, ifm_layout, ofm_layout, + weight_dtype, ) func = relay.Function(relay.analysis.free_vars(depthwise), depthwise) func = run_opt_pass(func, relay.transform.InferType()) @@ -99,6 +165,8 @@ def _visit(stmt): activation, ifm_layout, ofm_layout, + dtype, + _, ) = trial dilated_kernel_h = (kernel_shape[0] - 1) * dilation[0] + 1 dilated_kernel_w = (kernel_shape[1] - 1) * dilation[1] + 1 @@ -125,7 +193,7 @@ def _visit(stmt): ofm_stride_h = 16 * ofm_width * ((channels - 1) // 16 + 1) answer = [ - "int8", + dtype, ifm_shape[1], ifm_shape[2] if ifm_layout == "NHWC" else ifm_shape[3], channels, @@ -142,7 +210,7 @@ def _visit(stmt): ifm_stride_h, ifm_stride_w, ifm_stride_c, - "int8", + dtype, ofm_height, ofm_width, channels, diff --git a/tests/python/contrib/test_ethosu/test_type_inference.py b/tests/python/contrib/test_ethosu/test_type_inference.py index 47fddad773b2..681c49eb68ba 100644 --- a/tests/python/contrib/test_ethosu/test_type_inference.py +++ b/tests/python/contrib/test_ethosu/test_type_inference.py @@ -18,7 +18,7 @@ pytest.importorskip("ethosu.vela") -from tvm import relay +from tvm import relay, TVMError from tvm.relay.testing import run_opt_pass from .infra import make_ethosu_conv2d from .infra import make_ethosu_depthwise_conv2d @@ -92,5 +92,29 @@ def test_ethosu_depthwise_conv2d_type_inference( assert tuple(f.body.checked_type.shape) == ofm_shape +def test_incompatible_weight_data_type(): + ifm = relay.var("ifm", shape=(1, 8, 8, 3), dtype="int8") + depthwise = make_ethosu_depthwise_conv2d( + ifm=ifm, + channels=3, + kernel_shape=(3, 2), + padding=(0, 0), + strides=(1, 1), + dilation=(1, 1), + activation="NONE", + ifm_layout="NHWC", + ofm_layout="NHWC", + weight_dtype="int16", + ) + + func = relay.Function(relay.analysis.free_vars(depthwise), depthwise) + + message = ( + r"Expected ethosu_depthwise_conv2d type\(uint8\) or type\(int8\) for weight but was int16" + ) + with pytest.raises(TVMError, match=message): + run_opt_pass(func, relay.transform.InferType()) + + if __name__ == "__main__": pytest.main([__file__])