def callback( self, pre: tvm.relay.Expr, post: tvm.relay.Expr, node_map: tvm.ir.container.Map ) -> tvm.relay.Expr: params = self.params_class(post.op.body) params.ifm.tensor = post.args[1] if params.reversed_operands else post.args[0] params.ifm2.tensor = post.args[0] if params.reversed_operands else post.args[1] channels_map = { "NHWC": 3, } if str(params.ofm.layout) not in channels_map.keys(): raise UnsupportedLayout(str(params.ofm.layout)) activation_map = {"clip": "CLIP"} if params.activation: activation = activation_map[params.activation.op.name] clip_min = int(params.activation.attrs.a_min) clip_max = int(params.activation.attrs.a_max) else: activation = "NONE" clip_min = 0 clip_max = 0 # We don't yet support activation functions that need to get legalized to LUTs. lut = relay.const([], dtype="int8") inputs = [params.ifm, params.ifm2] inputs = self.reshape_input(inputs) ethosu_binary_elementwise = ethosu_ops.ethosu_binary_elementwise( ifm=inputs[0], ifm2=inputs[1], lut=lut, operator_type=params.operator_type, ifm_scale=float(params.ifm.q_params.scale_f32), ifm_zero_point=int(params.ifm.q_params.zero_point), ifm2_scale=float(params.ifm2.q_params.scale_f32), ifm2_zero_point=int(params.ifm2.q_params.zero_point), ofm_scale=float(params.ofm.q_params.scale_f32), ofm_zero_point=int(params.ofm.q_params.zero_point), ifm_channels=params.ifm.shape[-1], ifm2_channels=params.ifm2.shape[-1], reversed_operands=params.reversed_operands, ofm_dtype=params.ofm.dtype, activation=activation, clip_min=clip_min, clip_max=clip_max, ifm_layout=str(params.ifm.layout), ifm2_layout=str(params.ifm2.layout), ofm_layout=str(params.ofm.layout), ) output = self.reshape_output(ethosu_binary_elementwise, params.ifm.shape) return output
def callback( self, pre: tvm.relay.Expr, post: tvm.relay.Expr, node_map: tvm.ir.container.Map ) -> tvm.relay.Expr: params = self.params_class(post.op.body) params.ifm.tensor = post.args[0] if str(params.ofm.layout) != "NHWC": raise UnsupportedLayout(str(params.ofm.layout)) activation_map = {"clip": "CLIP"} if params.activation: activation = activation_map[params.activation.op.name] clip_min = int(params.activation.attrs.a_min) clip_max = int(params.activation.attrs.a_max) else: activation = "NONE" clip_min = 0 clip_max = 0 # We don't yet support activation functions that use LUT. lut = relay.const([], dtype="int8") unary_input_shape = params.ifm.shape # If the input tensor is not 4D, enter reshapes before and after the unary operator if len(params.ifm.shape) == 4: unary_input = params.ifm.tensor else: pad_size = 4 - len(unary_input_shape) unary_input_shape = ([1] * pad_size) + unary_input_shape unary_input = relay.op.reshape(params.ifm.tensor, newshape=unary_input_shape) ethosu_unary_elementwise = ethosu_ops.ethosu_unary_elementwise( ifm=unary_input, lut=lut, operator_type=params.operator_type, ifm_scale=float(params.ifm.q_params.scale_f32), ifm_zero_point=int(params.ifm.q_params.zero_point), ofm_scale=float(params.ofm.q_params.scale_f32), ofm_zero_point=int(params.ofm.q_params.zero_point), ofm_channels=unary_input_shape[3], activation=activation, clip_min=clip_min, clip_max=clip_max, ifm_layout=str(params.ifm.layout), ofm_layout=str(params.ofm.layout), ) if len(params.ifm.shape) == 4: op = ethosu_unary_elementwise else: op = relay.op.reshape(ethosu_unary_elementwise, newshape=params.ifm.shape) return op
def callback( self, pre: tvm.relay.Expr, post: tvm.relay.Expr, node_map: tvm.ir.container.Map ) -> tvm.relay.Expr: params = self.params_class(post.op.body) params.ifm.tensor = post.args[0] channels_map = { "NHWC": 3, } if str(params.ofm.layout) not in channels_map.keys(): raise UnsupportedLayout(str(params.ofm.layout)) activation_map = {"clip": "CLIP"} if params.activation: activation = activation_map[params.activation.op.name] clip_min = int(params.activation.attrs.a_min) clip_max = int(params.activation.attrs.a_max) else: activation = "NONE" clip_min = 0 clip_max = 0 # Activations requiring LUT is currently not supported, so setting it to an empty list lut = relay.const([], dtype="int8") return ethosu_ops.ethosu_pooling( ifm=post.args[0], lut=lut, pooling_type=params.pooling_type, ifm_scale=params.ifm.q_params.scale_f32, ifm_zero_point=params.ifm.q_params.zero_point, ofm_scale=params.ofm.q_params.scale_f32, ofm_zero_point=params.ofm.q_params.zero_point, pool_shape=params.pool_shape, ofm_channels=params.ofm.shape[channels_map[str(params.ofm.layout)]], strides=params.strides, padding=params.padding, activation=activation, clip_min=clip_min, clip_max=clip_max, upscale="NONE", ifm_layout=str(params.ifm.layout), ofm_layout=str(params.ofm.layout), )
def callback(self, pre: tvm.relay.Expr, post: tvm.relay.Expr, node_map: tvm.ir.container.Map) -> tvm.relay.Expr: params = ethosu_patterns.QnnConv2DParams(post.op.body) params.ifm.tensor = post.args[0] channels_map = { "NHWC": 3, } if str(params.ofm.layout) not in channels_map.keys(): raise UnsupportedLayout(str(params.ofm.layout)) kernel_size_map = { "HWIO": params.weights.shape[0:2], "OHWI": params.weights.shape[1:3], "HWOI": params.weights.shape[0:2], } if str(params.weights.layout) not in kernel_size_map.keys(): raise UnsupportedLayout(str(params.weights.layout)) activation_map = {"clip": "CLIP"} weight_to_ohwi_transform_map = {"HWIO": [3, 0, 1, 2]} weights_values = params.weights.values weights_values_ohwi = np.transpose( weights_values, weight_to_ohwi_transform_map[str(params.weights.layout)]) if params.activation: activation = activation_map[params.activation.op.name] clip_min = int(params.activation.attrs.a_min) clip_max = int(params.activation.attrs.a_max) else: activation = "NONE" clip_min = 0 clip_max = 0 scale_bias = vela_api.pack_biases( biases=params.biases.tensor.data.asnumpy(), ifm_scale=params.ifm.q_params.scale_f32, ifm_dtype=np.dtype(params.ifm.dtype), weight_scales=params.weights.q_params.scale_f32, ofm_scale=params.ofm.q_params.scale_f32, is_activation_tanh_or_sigmoid=activation in ["TANH", "SIGMOID"], ) ethosu_conv2d = ethosu_ops.ethosu_conv2d( ifm=post.args[0], weight=relay.const(weights_values_ohwi, params.weights.values.dtype), scale_bias=relay.const(scale_bias, "uint8"), lut=relay.const([], dtype="int8"), ifm_scale=float(params.ifm.q_params.scale_f32), ifm_zero_point=int(params.ifm.q_params.zero_point), weight_zero_point=int(params.weights.q_params.zero_point), ofm_scale=float(params.ofm.q_params.scale_f32), ofm_zero_point=int(params.ofm.q_params.zero_point), kernel_shape=kernel_size_map[str(params.weights.layout)], ofm_channels=params.ofm.shape[channels_map[str( params.ofm.layout)]], strides=params.strides, padding=params.padding, dilation=params.dilation, activation=activation, clip_min=clip_min, clip_max=clip_max, upscale="NONE", ifm_layout=str(params.ifm.layout), ofm_layout=str(params.ofm.layout), ) return ethosu_conv2d
def callback( self, pre: tvm.relay.Expr, post: tvm.relay.Expr, node_map: tvm.ir.container.Map ) -> tvm.relay.Expr: params = ethosu_patterns.QnnDepthwiseConv2DParams(post.op.body) params.ifm.tensor = post.args[0] channels_map = { "NHWC": 3, } if str(params.ofm.layout) not in channels_map.keys(): raise UnsupportedLayout(str(params.ofm.layout)) kernel_shape_map = { "HWOI": params.weights.shape[0:2], } if str(params.weights.layout) not in kernel_shape_map.keys(): raise UnsupportedLayout(str(params.weights.layout)) weights_values = params.weights.values weights_values_ohwi = np.moveaxis(weights_values, [0, 1, 2, 3], [1, 2, 0, 3]) activation = "NONE" # Activations requiring LUT is currently not supported, so setting it to an empty list lut = relay.const([], "int8") clip_min = 0 clip_max = 0 if params.activation: activation = ethosu_patterns.QnnDepthwiseConv2DParams.activation_map[ params.activation.op.name ] if activation == "CLIP": clip_min = int(params.activation.attrs.a_min) clip_max = int(params.activation.attrs.a_max) scale_bias = vela_api.pack_biases( biases=params.biases.tensor.data.asnumpy(), ifm_scale=params.ifm.q_params.scale_f32, ifm_dtype=np.dtype(params.ifm.dtype), weight_scales=params.weights.q_params.scale_f32, ofm_scale=params.ofm.q_params.scale_f32, is_activation_tanh_or_sigmoid=activation in ["TANH", "SIGMOID"], ) ethosu_depthwise_conv2d = ethosu_ops.ethosu_depthwise_conv2d( post.args[0], # IFM relay.const(weights_values_ohwi, params.weights.values.dtype), relay.const(scale_bias, "uint8"), lut, float(params.ifm.q_params.scale_f32), int(params.ifm.q_params.zero_point), int(params.weights.q_params.zero_point), float(params.ofm.q_params.scale_f32), int(params.ofm.q_params.zero_point), kernel_shape_map[str(params.weights.layout)], params.ofm.shape[channels_map[str(params.ofm.layout)]], strides=params.strides, padding=params.padding, dilation=params.dilation, activation=activation, clip_min=clip_min, clip_max=clip_max, upscale="NONE", ifm_layout=str(params.ifm.layout), ofm_layout=str(params.ofm.layout), ofm_dtype=str(params.ofm.dtype), ) return ethosu_depthwise_conv2d