Exemple #1
0
    def copy_memory(self, sdfg, dfg, state_id, src_node, dst_node, edge,
                    function_stream, callsite_stream):
        memlet = edge.data
        if (isinstance(src_node, nodes.AccessNode)
                and (src_node.desc(sdfg).materialize_func is not None)):
            function_stream.write(src_node.desc(sdfg).materialize_func)

            if edge.dst_conn is not None:
                arrayname = str(edge.dst_conn)
            else:
                arrayname = str(dst_node.desc)

            if isinstance(dst_node, nodes.Tasklet) or \
                    (dst_node.desc(sdfg).storage == types.StorageType.Register):
                callsite_stream.write(
                    self.memlet_definition(sdfg,
                                           memlet,
                                           arrayname,
                                           direction="in"), sdfg, state_id,
                    [src_node, dst_node])
            else:
                callsite_stream.write("__dace_materialize(\"" + \
                                      sym2cpp(src_node) + "\", " + \
                                      sym2cpp(memlet.subset.min_element()[0]) +
                                      ", " + \
                                      sym2cpp(memlet.subset.min_element()[0] +
                                          memlet.subset.num_elements()) +
                                      ", " + sym2cpp(dst_node.data) + ");\n",
                                      sdfg, state_id, [src_node, dst_node])

        if (isinstance(dst_node, nodes.AccessNode)
                and (dst_node.desc(sdfg).materialize_func is not None)):
            # This case is pretty complicated due to how the rest of the
            # codegen works: This is not the place to actually copy code. In
            # the place where data is ready to be written there will be a call
            # __foo.write(foo) where foo is the local_name of the memlet that
            # "causes" the write. But this function is actually called when
            # we should set up everything for this call to work.
            # The above mentioned code is generated by process_out_memlets

            function_stream.write(dst_node.desc(sdfg).materialize_func)
            if isinstance(src_node, nodes.Tasklet) or \
                    (src_node.desc(sdfg).storage == types.StorageType.Register):
                callsite_stream.write(
                    self.memlet_definition(sdfg,
                                           memlet,
                                           edge.src_conn,
                                           direction="out"), sdfg, state_id,
                    [src_node, dst_node])
            else:
                callsite_stream.write("__dace_serialize(\"" + \
                        sym2cpp(dst_node) + "\", " + \
                        sym2cpp(memlet.subset.min_element()[0]) +
                        ", " + \
                        sym2cpp(memlet.subset.min_element()[0] +
                            memlet.subset.num_elements()) +
                        ", " + sym2cpp(src_node.data) + ");\n",
                    sdfg, state_id, [src_node, dst_node])
Exemple #2
0
def generate_dummy(sdfg) -> str:
    """ Generates a C program calling this SDFG. Since we do not
        know the purpose/semantics of the program, we allocate
        the right types and and guess values for scalars.
    """
    includes = "#include <stdlib.h>\n"
    includes += "#include \"" + sdfg.name + ".h\"\n\n"
    header = "int main(int argc, char** argv) {\n"
    allocations = ""
    deallocations = ""
    sdfg_call = ""
    footer = "  return 0;\n}\n"

    al = sdfg.arglist()

    # first find all scalars and set them to 42
    for argname, arg in al.items():
        if isinstance(arg, data.Scalar):
            allocations += "  " + str(
                arg.signature(name=argname, with_types=True)) + " = 42;\n"

    # allocate the array args using calloc
    for argname, arg in al.items():
        if isinstance(arg, data.Array):
            dims_mul = cpu.sym2cpp(
                functools.reduce(lambda a, b: a * b, arg.shape, 1))
            basetype = str(arg.dtype)
            allocations += "  " + str(arg.signature(name=argname, with_types=True)) + \
                           " = (" + basetype + "*) calloc(" + dims_mul + ", sizeof("+ basetype +")" + ");\n"
            deallocations += "  free(" + str(arg) + ");\n"

    sdfg_call = '''
  __dace_init_{name}({params});
  __program_{name}({params});
  __dace_exit_{name}({params});\n\n'''.format(name=sdfg.name,
                                              params=sdfg.signature(
                                                  with_types=False,
                                                  for_call=True))

    res = includes
    res += header
    res += allocations
    res += sdfg_call
    res += deallocations
    res += footer
    return res
Exemple #3
0
    def memlet_definition(self, sdfg, memlet, local_name, direction="in"):
        if isinstance(memlet.data, data.Stream):
            return 'auto& %s = %s;\n' % (local_name, memlet.data)

        result = ('auto __%s = ' % local_name +
                  self.memlet_view_ctor(sdfg, memlet, direction) + ';\n')

        # Allocate variable type
        memlet_type = '    dace::vec<%s, %s>' % (
            sdfg.arrays[memlet.data].dtype.ctype, sym2cpp(memlet.veclen))
        if memlet.subset.data_dims() == 0 and memlet.num_accesses >= 0:
            result += memlet_type + ' ' + local_name
            if direction == "in":
                result += ' = __%s;\n' % local_name
            else:
                result += ';\n'

        return result
Exemple #4
0
    def memlet_view_ctor(self, sdfg, memlet, direction):
        useskip = False
        memlet_params = []

        memlet_name = memlet.data
        if isinstance(sdfg.arrays[memlet.data], data.Scalar):
            raise ValueError("This should never have happened")

        if isinstance(memlet.subset, subsets.Indices):
            # Compute address
            memlet_params.append(cpp_array_expr(sdfg, memlet, False))
            dims = 0

        elif isinstance(memlet.subset, subsets.Range):
            dims = len(memlet.subset.ranges)
            #memlet_params.append("")

            # Dimensions to remove from view (due to having one value)
            indexdims = []
            nonIndexDims = []

            for dim, (rb, re, rs) in enumerate(memlet.subset.ranges):
                if rs != 1:
                    useskip = True
                try:
                    if (re - rb) == 0:
                        indexdims.append(dim)
                    else:
                        nonIndexDims.append(dim)
                except TypeError:  # cannot determine truth value of Relational
                    nonIndexDims.append(dim)

            if len(nonIndexDims) > 1 and len(indexdims) > 0:
                raise NotImplementedError(
                    'subviews of more than one dimension ' + 'not implemented')
            elif len(
                    nonIndexDims) == 1 and len(indexdims) > 0:  # One dimension
                indexdim = nonIndexDims[0]

                # Contiguous dimension
                if indexdim == dims - 1:
                    memlet_params[-1] += ' + %s' % cpp_array_expr(
                        sdfg, memlet, False)
                    memlet_params.append(
                        '0, %s' % (sym2cpp(memlet.subset.ranges[-1][1] -
                                           memlet.subset.ranges[-1][0])))
                else:  # Non-contiguous dimension
                    useskip = True
                    memlet_params[-1] += ' + %s' % cpp_array_expr(
                        sdfg, memlet, False)
                    memlet_range = memlet.subset.ranges[indexdim]

                    # TODO(later): Access order
                    memlet_stride = functools.reduce(
                        lambda x, y: x * y,
                        sdfg.arrays[memlet.data].shape[indexdim + 1:])
                    memlet_stride = sym2cpp(memlet_stride)

                    memlet_params.append(
                        '0, %s, %s' %
                        (sym2cpp(memlet_range[1] - memlet_range[0]),
                         sym2cpp(memlet_stride)))

                # Subtract index dimensions from array dimensions
                dims -= len(indexdims)

            elif len(indexdims) == 0:
                for (rb, re, rs), s in zip(memlet.subset.ranges,
                                           sdfg.arrays[memlet.data].shape):
                    if useskip:
                        memlet_params.append(
                            '%s, %s, %s' %
                            (cppunparse.pyexpr2cpp(symbolic.symstr(rb)),
                             cppunparse.pyexpr2cpp(symbolic.symstr(s)),
                             cppunparse.pyexpr2cpp(symbolic.symstr(rs))))
                    else:
                        memlet_params.append(
                            '%s, %s' %
                            (cppunparse.pyexpr2cpp(symbolic.symstr(rb)),
                             cppunparse.pyexpr2cpp(symbolic.symstr(s))))
            elif len(nonIndexDims) == 0:  # Scalar view
                # Compute address
                memlet_params[-1] += ' + ' + cpp_array_expr(
                    sdfg, memlet, False)
                dims = 0

        else:
            raise RuntimeError('Memlet type "%s" not implemented' %
                               memlet.subset)

        if dims == 0:
            return 'dace::ArrayViewImmaterial%s%s<%s, %s, int32_t> ("%s", %s)' % (
                'In' if direction == "in" else "Out", 'Skip'
                if useskip else '', sdfg.arrays[memlet.data].dtype.ctype,
                symbolic.symstr(
                    memlet.veclen), memlet.data, ', '.join(memlet_params))
        else:
            return 'dace::ArrayViewImmaterial%s%s<%s, %s, int32_t, %s> ("%s", %s)' % (
                'In' if direction == "in" else "Out", 'Skip'
                if useskip else '', sdfg.arrays[memlet.data].dtype.ctype,
                symbolic.symstr(memlet.veclen), ', '.join([
                    str(s) for s in memlet.subset.bounding_box_size()
                ]), memlet.data, ', '.join(memlet_params))