code: def _decl_spatial_pack(
      cfg, data, kernel, strides, padding, dilation, out_dtype, num_tile
  ):
      out_dtype = out_dtype or data.dtype
  
      N, C, IH, IW = get_const_tuple(data.shape)
  
      if isinstance(dilation, int):
          dilation_h = dilation_w = dilation
      else:
          dilation_h, dilation_w = dilation
  
      if len(kernel.shape) == 4:
          pre_packed = False
          C, M, KH, KW = get_const_tuple(kernel.shape)
      else:  # kernel tensor is pre packed
          pre_packed = True
          C, M, KH, KW, VC = get_const_tuple(kernel.shape)
          C = C * VC
  
      dilated_kernel_h = (KH - 1) * dilation_h + 1
      dilated_kernel_w = (KW - 1) * dilation_w + 1
  
      pad_top, pad_left, pad_down, pad_right = get_pad_tuple(
          padding, (dilated_kernel_h, dilated_kernel_w)
      )
      HSTR, WSTR = (
          strides
          if isinstance(strides, (tuple, list))
          else (strides, strides)
      )
      OH = (IH + pad_top + pad_down - dilated_kernel_h) // HSTR + 1
      OW = (IW + pad_left + pad_right - dilated_kernel_w) // WSTR + 1
      # pack data
      HPAD = pad_top + pad_down
      WPAD = pad_left + pad_right
      DOPAD = HPAD != 0 or WPAD != 0
      if DOPAD:
          data_pad = nn.pad(
              data,
              (0, 0, pad_top, pad_left),
              (0, 0, pad_down, pad_right),
              name="data_pad",
          )
      else:
          data_pad = data
  
      # fallback support
      # Currently, Mali schedule doesn't use it like conv2d.
      if cfg.is_fallback:
          ref_log = autotvm.tophub.load_reference_log(
              "arm_cpu",
              "rk3399",
              "depthwise_conv2d_nchw_spatial_pack.arm_cpu",
          )
          cfg.fallback_with_reference_log(ref_log)
  
      # ==================== define configuration space ====================
      n, c, oh, ow = (
          cfg.axis(N),
          cfg.axis(C),
          cfg.axis(OH),
          cfg.axis(OW),
      )
      kh, kw = cfg.reduce_axis(KH), cfg.reduce_axis(KW)
  
      # Currently, Mali schedule doesn't use it like conv2d.
      # Leave num_tile for possible future use of Mali schedule
      if num_tile == 2:  # for arm cpu
          co, vc = cfg.define_split("tile_co", c, num_outputs=2)
          oh, vh = cfg.define_split("tile_oh", oh, num_outputs=2)
          ow, vw = cfg.define_split("tile_ow", ow, num_outputs=2)
      else:
          raise RuntimeError("Invalid num_tile")
  
      cfg.define_reorder(
          "reorder_0",
          [n, co, oh, ow, kh, kw, vh, vw, vc],
          policy="candidate",
          candidate=[
              [n, co, oh, ow, kh, kw, vh, vw, vc],
              [n, co, oh, ow, kh, kw, vc, vh, vw],
          ],
      )
  
      cfg.define_reorder(
          "reorder_1",
          [n, co, oh, ow, vh, vw, vc],
          policy="candidate",
          candidate=[
              [n, co, oh, ow, vh, vw, vc],
              [n, co, oh, ow, vc, vh, vw],
              [n, co, oh, ow, vh, vc, vw],
          ],
      )
  
      cfg.define_annotate("ann_reduce", [kh, kw], policy="try_unroll")
      cfg.define_annotate(
          "ann_spatial", [vh, vw, vc], policy="try_unroll_vec"
      )
      # ====================================================================
  
      VC = cfg["tile_co"].size[-1]
      VH = cfg["tile_oh"].size[-1]
      VW = cfg["tile_ow"].size[-1]
  
      kvshape = (C // VC, M, KH, KW, VC)
      ovshape = (N, C * M // VC, OH // VH, OW // VW, VH, VW, VC)
      oshape = (N, C * M, OH, OW)
  
      if dilation_h != 1 or dilation_w != 1:
          # undilate input data
          dvshape = (N, OH // VH, OW // VW, C, KH, KW, VH, VW)
          data_vec = te.compute(
              dvshape,
              lambda n, h, w, c, kh, kw, vh, vw: data_pad[n][c][
                  (h * VH + vh) * HSTR + kh * dilation_h
              ][(w * VW + vw) * WSTR + kw * dilation_w],
              name="data_vec_undilated",
          )
      else:
          dvshape = (
              N,
              OH // VH,
              OW // VW,
              C,
              VH * HSTR + KH - 1,
              VW * WSTR + KW - 1,
          )
          data_vec = te.compute(
              dvshape,
              lambda n, h, w, c, vh, vw: data_pad[n][c][
                  h * VH * HSTR + vh
              ][w * VW * WSTR + vw],
              name="data_vec",
          )
  
      if pre_packed:
          kernel_vec = kernel
      else:
          kernel_vec = te.compute(
              kvshape,
              lambda co, m, kh, kw, vc: kernel[co * VC + vc][m][kh][kw],
              name="kernel_vec",
          )
  
      kh = te.reduce_axis((0, KH), name="kh")
      kw = te.reduce_axis((0, KW), name="kw")
  
      idxdiv = tvm.tir.indexdiv
      idxmod = tvm.tir.indexmod
  
      if dilation_h != 1 or dilation_w != 1:
          conv = te.compute(
              ovshape,
              lambda n, co, h, w, vh, vw, vc: te.sum(
                  data_vec[
                      n, h, w, idxdiv(co * VC + vc, M), kh, kw, vh, vw
                  ].astype(out_dtype)
                  * kernel_vec[
                      idxdiv(co, M), idxmod(co, M), kh, kw, vc
                  ].astype(out_dtype),
                  axis=[kh, kw],
              ),
              name="depthwise_conv",
          )
      else:
          conv = te.compute(
              ovshape,
              lambda n, co, h, w, vh, vw, vc: te.sum(
                  data_vec[
                      n,
                      h,
                      w,
                      idxdiv((co * VC + vc), M),
                      vh * HSTR + kh,
                      vw * WSTR + kw,
                  ].astype(out_dtype)
                  * kernel_vec[
                      idxdiv(co, M), idxmod(co, M), kh, kw, vc
                  ].astype(out_dtype),
                  axis=[kh, kw],
              ),
              name="depthwise_conv",
          )
  
      output = te.compute(
          oshape,
          lambda n, co, h, w: conv[
              n,
              idxdiv(co, VC),
              idxdiv(h, VH),
              idxdiv(w, VW),
              idxmod(h, VH),
              idxmod(w, VW),
              idxmod(co, VC),
          ],
          name="output_unpack",
          tag="spatial_depthwise_conv2d_nchw_output",
      )
      return output
  
file_path: tvm/python/tvm/topi/arm_cpu/depthwise_conv2d.py
imports: import tvm
  from tvm.target import Target
  from tvm import te
  from tvm import autotvm
  from tvm.autotvm.task.space import SplitEntity, OtherOptionEntity
  from ..None import nn
  from ..utils import traverse_inline, get_const_tuple, get_const_int
  from ..nn.utils import get_pad_tuple
  from .tensor_intrin import smlal_int16_int32
  from .mprofile.dsp.depthwise_conv2d import depthwise_conv2d_nhwc_dsp_compute, depthwise_conv2d_nhwc_dsp_schedule
label_desc: Use image node_id 7 for calling a global function with example usage: _decl_spatial_pack(cfg, data, kernel, strides, padding, dilation, out_dtype, num_tile) and returns: output