def METHOD_NAME(implementation, dtype, storage=dace.StorageType.Default, data_layout='CCC'):
    m = dace.symbol("m")
    n = dace.symbol("n")
    k = dace.symbol("k")
    suffix = "_device" if storage != dace.StorageType.Default else ""
    transient = storage != dace.StorageType.Default
    sdfg = dace.SDFG("mm_{}_{}".format(dtype.type.__name__, data_layout))
    state = sdfg.add_state("dataflow")
    # Data layout is a 3-character string with either C (for row major)
    # or F (for column major) matrices for x, y, and z respectively.
    xstrides = (k, 1) if data_layout[0] == 'C' else (1, m)
    ystrides = (n, 1) if data_layout[1] == 'C' else (1, k)
    zstrides = (n, 1) if data_layout[2] == 'C' else (1, m)
    sdfg.add_array("x" + suffix, [m, k], dtype, storage=storage, transient=transient, strides=xstrides)
    sdfg.add_array("y" + suffix, [k, n], dtype, storage=storage, transient=transient, strides=ystrides)
    sdfg.add_array("result" + suffix, [m, n], dtype, storage=storage, transient=transient, strides=zstrides)
    x = state.add_read("x" + suffix)
    y = state.add_read("y" + suffix)
    result = state.add_write("result" + suffix)
    node = blas.nodes.matmul.MatMul("matmul")
    state.add_memlet_path(x, node, dst_conn="_a", memlet=Memlet.simple(x, "0:m, 0:k"))
    state.add_memlet_path(y, node, dst_conn="_b", memlet=Memlet.simple(y, "0:k, 0:n"))
    state.add_memlet_path(node, result, src_conn="_c", memlet=Memlet.simple(result, "0:m, 0:n"))
    if storage != dace.StorageType.Default:
        sdfg.add_array("x", [m, k], dtype, strides=xstrides)
        sdfg.add_array("y", [k, n], dtype, strides=ystrides)
        sdfg.add_array("result", [m, n], dtype, strides=zstrides)
        init_state = sdfg.add_state("copy_to_device")
        sdfg.add_edge(init_state, state, dace.InterstateEdge())
        x_host = init_state.add_read("x")
        y_host = init_state.add_read("y")
        x_device = init_state.add_write("x" + suffix)
        y_device = init_state.add_write("y" + suffix)
        init_state.add_memlet_path(x_host, x_device, memlet=Memlet.simple(x_host, "0:m, 0:k"))
        init_state.add_memlet_path(y_host, y_device, memlet=Memlet.simple(y_host, "0:k, 0:n"))
        finalize_state = sdfg.add_state("copy_to_host")
        sdfg.add_edge(state, finalize_state, dace.InterstateEdge())
        result_device = finalize_state.add_write("result" + suffix)
        result_host = finalize_state.add_read("result")
        finalize_state.add_memlet_path(result_device, result_host, memlet=Memlet.simple(result_device, "0:m, 0:n"))
    return sdfg