code: def test_tflite_separate_channel_padding_legalize(
      ifm_shape, channel_padding, const_value
  ):
      dtype = "int8"
      padding = (0, 0, 0, 0)
  
      class AreConcatenateOnGraph(ExprVisitor):
          """
          Visits the Graph recursively and checks if it contains 'concatenate' op
          """
  
          def __init__(self):
              ExprVisitor.__init__(self)
              self.on_graph = False
  
          def visit_call(self, call):
              if isinstance(call.op, tvm.ir.Op):
                  if str(call.op.name) == "concatenate":
                      self.on_graph = True
  
              return super().visit_call(call)
  
          def are_concatenate_on_graph(self, subgraph) -> bool:
              """
              This function recursively visits the graph and checks if 'concatenate' op is on graph
              """
              self.visit(subgraph)
              return self.on_graph
  
      def create_tflite_graph():
          class Model(tf.Module):
              @tf.function
              def tf_function(self, x):
                  return tf.pad(
                      x,
                      [
                          [0, 0],
                          [padding[0], padding[2]],
                          [padding[1], padding[3]],
                          [channel_padding[0], channel_padding[1]],
                      ],
                      "CONSTANT",
                      const_value,
                  )
  
          model = Model()
          concrete_func = model.tf_function.get_concrete_function(
              tf.TensorSpec(ifm_shape, dtype=tf.float32)
          )
  
          # Convert the model
          def representative_dataset():
              for _ in range(100):
                  data = np.random.rand(*tuple(ifm_shape))
                  yield [data.astype(np.float32)]
  
          converter = tf.lite.TFLiteConverter.from_concrete_functions(
              [concrete_func]
          )
          converter.optimizations = [tf.lite.Optimize.DEFAULT]
          converter.representative_dataset = representative_dataset
          converter.target_spec.supported_ops = [
              tf.lite.OpsSet.TFLITE_BUILTINS_INT8
          ]
          converter.inference_input_type = tf.int8
          converter.inference_output_type = tf.int8
          tflite_model = converter.convert()
          return tflite_model
  
      def verify(ext_func, channel_padding):
          op = ext_func.body
  
          pad_before = 0
          pad_after = 0
          if channel_padding[0] == 0 and channel_padding[1] > 0:
              pad_after = (
                  ext_func.body.args[0][1].args[0].checked_type.shape[3]
              )
              ifm = ext_func.body.args[0][0].args[0].checked_type
          if channel_padding[0] > 0 and channel_padding[1] == 0:
              pad_before = (
                  ext_func.body.args[0][0].args[0].checked_type.shape[3]
              )
              ifm = ext_func.body.args[0][1].args[0].checked_type
          if channel_padding[0] > 0 and channel_padding[1] > 0:
              pad_before = (
                  ext_func.body.args[0][0].args[0].checked_type.shape[3]
              )
              ifm = ext_func.body.args[0][1].args[0].checked_type
              pad_after = (
                  ext_func.body.args[0][2].args[0].checked_type.shape[3]
              )
  
          # check IFM
          assert list(ifm.shape) == list(ifm_shape)
          assert str(ifm.dtype) == dtype
          assert ifm.shape[3] == ifm_shape[3]
  
          # check OFM
          ofm = op.checked_type
          expected_ofm_shape = list(ifm_shape)
          expected_ofm_shape[3] = (
              channel_padding[0] + ifm_shape[3] + channel_padding[1]
          )
          assert list(ofm.shape) == expected_ofm_shape
          assert str(ofm.dtype) == dtype
  
          # check padding
          assert [pad_before, pad_after] == list(channel_padding)
  
          # check if relay contains 'concatenate' op
          assert (
              AreConcatenateOnGraph().are_concatenate_on_graph(
                  ext_func.body
              )
              == True
          )
  
      pad_pattern_table = [
          (
              ethosu.ChannelPadParams.composite_name,
              ethosu.pad_pattern(),
              lambda pat: ethosu.ChannelPadParams(pat).is_valid(),
          ),
      ]
  
      tflite_graph = create_tflite_graph()
      tflite_model = tflite.Model.Model.GetRootAsModel(tflite_graph, 0)
  
      mod, params = relay.frontend.from_tflite(
          tflite_model,
          shape_dict={"input": ifm_shape},
          dtype_dict={"input": dtype},
      )
  
      mod["main"] = bind_params_by_name(mod["main"], params)
      mod = partition_ethosu_by_table(mod, pad_pattern_table)
  
      mod["tvmgen_default_ethos_u_main_0"] = dataflow_pattern.rewrite(
          legalize.ChannelPadRewriter(),
          mod["tvmgen_default_ethos_u_main_0"],
      )
      verify(mod["tvmgen_default_ethos_u_main_0"], channel_padding)
  
imports: import pytest
  import math
  import numpy
  import tensorflow
  import tflite.Model
  import tvm
  from tvm import relay
  from tvm.relay.backend.contrib.ethosu import legalize, preprocess
  from tvm.relay import dataflow_pattern
  from tvm.relay.op.contrib import ethosu
  from tvm.relay.backend.contrib.ethosu import util, codegen
  from tvm.relay.build_module import bind_params_by_name
  from tvm.relay.frontend.tflite import get_pad_value
  from tvm.relay.expr_functor import ExprVisitor
  from .None import infra
label_desc: Use image node_id 11 for calling a global function with example usage: test_tflite_separate_channel_padding_legalize(ifm_shape, channel_padding, const_value) and returns: tflite_model, super, self, tf