code: def image_dot(self, w, acc_dtype=None):
      # NOTE: we use a 1x1 conv2d to do the matmul. mxk @ kxn = (1,k,m,1).conv2d(n,k,1,1)
      n1, n2 = len(self.shape), len(w.shape)
      assert (
          n1 != 0 and n2 != 0
      ), f"both arguments to matmul need to be at least 1D, but they are {n1}D and {n2}D"
      assert (
          self.shape[-1] == w.shape[-min(n2, 2)]
      ), f"Input Tensor shapes {self.shape} and {w.shape} cannot be multiplied ({self.shape[-1]} != {w.shape[-min(n2, 2)]})"  # noqa: E501
      bs, groups, cin, cout = (
          prod(self.shape[0:-2]),
          prod(w.shape[0:-2]),
          w.shape[-2],
          w.shape[-1],
      )
      out_shape_t = (
          self.shape[0:-2] + (cout, -1)
          if len(self.shape) > 1
          else (cout,)
      )
  
      # NOTE: with NHWC we can remove the transposes
      # bs x groups*cin x H x W
      cx = self.transpose(self.ndim - 1, self.ndim - 2).reshape(
          (bs // groups, groups * cin, -1, 1)
      )
      # groups*cout x cin x H, W
      cw = w.transpose(w.ndim - 1, w.ndim - 2).reshape(
          (groups * cout, cin, 1, 1)
      )
      return (
          image_conv2d(cx, cw, groups=groups, acc_dtype=acc_dtype)
          .reshape(out_shape_t)
          .transpose(self.ndim - 1, self.ndim - 2)
      )
  
imports: from typing import Tuple
  from tinygrad.helpers import prod, IMAGE, getenv, DEBUG
  from tinygrad.dtype import dtypes
  from tinygrad.shape.symbolic import Node
label_desc: Use image node_id 1 for calling a global function with example usage: image_dot(w, acc_dtype) and returns: image_conv2d