Esempio n. 1
0
def replace_properties_dict(node: Any,
                            repl: Dict[str, str],
                            symrepl: Dict[symbolic.SymbolicType, symbolic.SymbolicType] = None):
    symrepl = symrepl or {
        symbolic.pystr_to_symbolic(symname):
        symbolic.pystr_to_symbolic(new_name) if isinstance(new_name, str) else new_name
        for symname, new_name in repl.items()
    }

    for propclass, propval in node.properties():
        if propval is None:
            continue
        pname = propclass.attr_name
        if isinstance(propclass, properties.SymbolicProperty):
            setattr(node, pname, propval.subs(symrepl))
        elif isinstance(propclass, properties.DataProperty):
            if propval in repl:
                setattr(node, pname, repl[propval])
        elif isinstance(propclass, (properties.RangeProperty, properties.ShapeProperty)):
            setattr(node, pname, _replsym(list(propval), symrepl))
        elif isinstance(propclass, properties.CodeProperty):
            # Don't replace variables that appear as an input or an output
            # connector, as this should shadow the outer declaration.
            reduced_repl = set(repl.keys())
            if hasattr(node, 'in_connectors'):
                reduced_repl -= set(node.in_connectors.keys()) | set(node.out_connectors.keys())
            reduced_repl = {k: repl[k] for k in reduced_repl}
            code = propval.code
            if isinstance(code, str) and code:
                lang = propval.language
                if lang is dtypes.Language.CPP:  # Replace in C++ code
                    prefix = ''
                    tokenized = tokenize_cpp.findall(code)
                    for name, new_name in reduced_repl.items():
                        if name not in tokenized:
                            continue

                        # Use local variables and shadowing to replace
                        replacement = f'auto {name} = {cppunparse.pyexpr2cpp(new_name)};\n'
                        prefix = replacement + prefix
                    if prefix:
                        propval.code = prefix + code
                else:
                    warnings.warn('Replacement of %s with %s was not made '
                                    'for string tasklet code of language %s' % (name, new_name, lang))

            elif propval.code is not None:
                afr = ASTFindReplace(reduced_repl)
                for stmt in propval.code:
                    afr.visit(stmt)
        elif (isinstance(propclass, properties.DictProperty) and pname == 'symbol_mapping'):
            # Symbol mappings for nested SDFGs
            for symname, sym_mapping in propval.items():
                try:
                    propval[symname] = symbolic.pystr_to_symbolic(str(sym_mapping)).subs(symrepl)
                except AttributeError:  # If the symbolified value has no subs
                    pass
Esempio n. 2
0
def replace_properties(node: Any, symrepl: Dict[symbolic.symbol, symbolic.SymbolicType], name: str, new_name: str):
    for propclass, propval in node.properties():
        if propval is None:
            continue
        pname = propclass.attr_name
        if isinstance(propclass, properties.SymbolicProperty):
            setattr(node, pname, propval.subs(symrepl))
        elif isinstance(propclass, properties.DataProperty):
            if propval == name:
                setattr(node, pname, new_name)
        elif isinstance(propclass, (properties.RangeProperty, properties.ShapeProperty)):
            setattr(node, pname, _replsym(list(propval), symrepl))
        elif isinstance(propclass, properties.CodeProperty):
            # Don't replace variables that appear as an input or an output
            # connector, as this should shadow the outer declaration.
            if hasattr(node, 'in_connectors'):
                if name in node.in_connectors:
                    continue
            if hasattr(node, 'out_connectors'):
                if name in node.out_connectors:
                    continue
            if isinstance(propval.code, str):
                if str(name) != str(new_name):
                    lang = propval.language
                    newcode = propval.code
                    if not re.findall(r'[^\w]%s[^\w]' % name, newcode):
                        continue

                    if lang is dtypes.Language.CPP:  # Replace in C++ code
                        # Avoid import loop
                        from dace.codegen.targets.cpp import sym2cpp

                        # Use local variables and shadowing to replace
                        replacement = 'auto %s = %s;\n' % (name, sym2cpp(new_name))
                        propval.code = replacement + newcode
                    else:
                        warnings.warn('Replacement of %s with %s was not made '
                                      'for string tasklet code of language %s' % (name, new_name, lang))
            elif propval.code is not None:
                afr = ASTFindReplace({name: symbolic.symstr(new_name)})
                for stmt in propval.code:
                    afr.visit(stmt)
        elif (isinstance(propclass, properties.DictProperty) and pname == 'symbol_mapping'):
            # Symbol mappings for nested SDFGs
            for symname, sym_mapping in propval.items():
                try:
                    propval[symname] = symbolic.pystr_to_symbolic(str(sym_mapping)).subs(symrepl)
                except AttributeError:  # If the symbolified value has no subs
                    pass
Esempio n. 3
0
    def instantiate_loop(
        self,
        sdfg: sd.SDFG,
        loop_states: List[sd.SDFGState],
        loop_subgraph: gr.SubgraphView,
        itervar: str,
        value: symbolic.SymbolicType,
        state_suffix=None,
    ):
        # Using to/from JSON copies faster than deepcopy (which will also
        # copy the parent SDFG)
        new_states = [
            sd.SDFGState.from_json(s.to_json(), context={'sdfg': sdfg})
            for s in loop_states
        ]

        # Replace iterate with value in each state
        for state in new_states:
            state.set_label(state.label + '_' + itervar + '_' + (
                state_suffix if state_suffix is not None else '%d' % value))
            state.replace(itervar, value)

        # Add subgraph to original SDFG
        for edge in loop_subgraph.edges():
            src = new_states[loop_states.index(edge.src)]
            dst = new_states[loop_states.index(edge.dst)]

            # Replace conditions in subgraph edges
            data: sd.InterstateEdge = copy.deepcopy(edge.data)
            if data.condition:
                ASTFindReplace({itervar: str(value)}).visit(data.condition)

            sdfg.add_edge(src, dst, data)

        return new_states
Esempio n. 4
0
def replace_properties(node: Any, name: str, new_name: str):
    if str(name) == str(new_name):
        return
    symrepl = {
        symbolic.symbol(name):
        symbolic.pystr_to_symbolic(new_name)
        if isinstance(new_name, str) else new_name
    }

    for propclass, propval in node.properties():
        if propval is None:
            continue
        pname = propclass.attr_name
        if isinstance(propclass, properties.SymbolicProperty):
            setattr(node, pname, propval.subs(symrepl))
        elif isinstance(propclass, properties.DataProperty):
            if propval == name:
                setattr(node, pname, new_name)
        elif isinstance(propclass,
                        (properties.RangeProperty, properties.ShapeProperty)):
            setattr(node, pname, _replsym(list(propval), symrepl))
        elif isinstance(propclass, properties.CodeProperty):
            if isinstance(propval.code, str):
                if str(name) != str(new_name):
                    lang = propval.language
                    newcode = propval.code
                    if not re.findall(r'[^\w]%s[^\w]' % name, newcode):
                        continue

                    if lang is dtypes.Language.CPP:  # Replace in C++ code
                        # Use local variables and shadowing to replace
                        replacement = 'auto %s = %s;\n' % (name, new_name)
                        propval.code = replacement + newcode
                    else:
                        warnings.warn(
                            'Replacement of %s with %s was not made '
                            'for string tasklet code of language %s' %
                            (name, new_name, lang))
            elif propval.code is not None:
                for stmt in propval.code:
                    ASTFindReplace({name: new_name}).visit(stmt)
        elif (isinstance(propclass, properties.DictProperty)
              and pname == 'symbol_mapping'):
            # Symbol mappings for nested SDFGs
            for symname, sym_mapping in propval.items():
                propval[symname] = sym_mapping.subs(symrepl)
Esempio n. 5
0
    def apply(self, sdfg):
        # Obtain loop information
        guard: sd.SDFGState = sdfg.node(self.subgraph[DetectLoop._loop_guard])
        begin: sd.SDFGState = sdfg.node(self.subgraph[DetectLoop._loop_begin])
        after_state: sd.SDFGState = sdfg.node(
            self.subgraph[DetectLoop._exit_state])

        # Obtain iteration variable, range, and stride
        guard_inedges = sdfg.in_edges(guard)
        condition_edge = sdfg.edges_between(guard, begin)[0]
        itervar = list(guard_inedges[0].data.assignments.keys())[0]
        condition = condition_edge.data.condition_sympy()
        rng = LoopUnroll._loop_range(itervar, guard_inedges, condition)

        # Loop must be unrollable
        if self.count == 0 and any(
                symbolic.issymbolic(r, sdfg.constants) for r in rng):
            raise ValueError('Loop cannot be fully unrolled, size is symbolic')
        if self.count != 0:
            raise NotImplementedError  # TODO(later)

        # Find the state prior to the loop
        if rng[0] == symbolic.pystr_to_symbolic(
                guard_inedges[0].data.assignments[itervar]):
            before_state: sd.SDFGState = guard_inedges[0].src
            last_state: sd.SDFGState = guard_inedges[1].src
        else:
            before_state: sd.SDFGState = guard_inedges[1].src
            last_state: sd.SDFGState = guard_inedges[0].src

        # Get loop states
        loop_states = list(
            sdutil.dfs_topological_sort(
                sdfg,
                sources=[begin],
                condition=lambda _, child: child != guard))
        first_id = loop_states.index(begin)
        last_id = loop_states.index(last_state)
        loop_subgraph = gr.SubgraphView(sdfg, loop_states)

        # Evaluate the real values of the loop
        start, end, stride = (symbolic.evaluate(r, sdfg.constants)
                              for r in rng)

        # Create states for loop subgraph
        unrolled_states = []
        for i in range(start, end + 1, stride):
            # Using to/from JSON copies faster than deepcopy (which will also
            # copy the parent SDFG)
            new_states = [
                sd.SDFGState.from_json(s.to_json(), context={'sdfg': sdfg})
                for s in loop_states
            ]

            # Replace iterate with value in each state
            for state in new_states:
                state.set_label(state.label + '_%s_%d' % (itervar, i))
                state.replace(itervar, i)

            # Add subgraph to original SDFG
            for edge in loop_subgraph.edges():
                src = new_states[loop_states.index(edge.src)]
                dst = new_states[loop_states.index(edge.dst)]

                # Replace conditions in subgraph edges
                data: sd.InterstateEdge = copy.deepcopy(edge.data)
                if data.condition:
                    ASTFindReplace({itervar: str(i)}).visit(data.condition)

                sdfg.add_edge(src, dst, data)

            # Connect iterations with unconditional edges
            if len(unrolled_states) > 0:
                sdfg.add_edge(unrolled_states[-1][1], new_states[first_id],
                              sd.InterstateEdge())

            unrolled_states.append((new_states[first_id], new_states[last_id]))

        # Connect new states to before and after states without conditions
        if unrolled_states:
            sdfg.add_edge(before_state, unrolled_states[0][0],
                          sd.InterstateEdge())
            sdfg.add_edge(unrolled_states[-1][1], after_state,
                          sd.InterstateEdge())

        # Remove old states from SDFG
        sdfg.remove_nodes_from([guard] + loop_states)