def generate_fileheader(self, sdfg: SDFG, global_stream: CodeIOStream, backend: str = 'frame'): """ Generate a header in every output file that includes custom types and constants. :param sdfg: The input SDFG. :param global_stream: Stream to write to (global). :param backend: Whose backend this header belongs to. """ ######################################################### # Environment-based includes for env in self.environments: if len(env.headers) > 0: global_stream.write( "\n".join("#include \"" + h + "\"" for h in env.headers), sdfg) ######################################################### # Custom types datatypes = set() # Types of this SDFG for _, arrname, arr in sdfg.arrays_recursive(): if arr is not None: datatypes.add(arr.dtype) # Emit unique definitions wrote_something = False for typ in datatypes: if hasattr(typ, 'emit_definition'): if not wrote_something: global_stream.write("", sdfg) wrote_something = True global_stream.write(typ.emit_definition(), sdfg) if wrote_something: global_stream.write("", sdfg) ######################################################### # Write constants self.generate_constants(sdfg, global_stream) ######################################################### # Write state struct structstr = '\n'.join(self.statestruct) global_stream.write( f''' struct {sdfg.name}_t {{ {structstr} }}; ''', sdfg) for sd in sdfg.all_sdfgs_recursive(): if None in sd.global_code: global_stream.write(codeblock_to_cpp(sd.global_code[None]), sd) if backend in sd.global_code: global_stream.write(codeblock_to_cpp(sd.global_code[backend]), sd)
def generate_fileheader(self, sdfg: SDFG, global_stream: CodeIOStream, backend: str = 'frame'): """ Generate a header in every output file that includes custom types and constants. :param sdfg: The input SDFG. :param global_stream: Stream to write to (global). :param backend: Whose backend this header belongs to. """ ######################################################### # Custom types datatypes = set() # Types of this SDFG for _, arrname, arr in sdfg.arrays_recursive(): if arr is not None: datatypes.add(arr.dtype) # Emit unique definitions wrote_something = False for typ in datatypes: if hasattr(typ, 'emit_definition'): if not wrote_something: global_stream.write("", sdfg) wrote_something = True global_stream.write(typ.emit_definition(), sdfg) if wrote_something: global_stream.write("", sdfg) ######################################################### # Write constants self.generate_constants(sdfg, global_stream) for sd in sdfg.all_sdfgs_recursive(): if None in sd.global_code: global_stream.write(codeblock_to_cpp(sd.global_code[None]), sd) if backend in sd.global_code: global_stream.write(codeblock_to_cpp(sd.global_code[backend]), sd)
def generate_footer(self, sdfg: SDFG, global_stream: CodeIOStream, callsite_stream: CodeIOStream): """ Generate the footer of the frame-code. Code exists in a separate function for overriding purposes. :param sdfg: The input SDFG. :param global_stream: Stream to write to (global). :param callsite_stream: Stream to write to (at call site). """ import dace.library fname = sdfg.name params = sdfg.signature() paramnames = sdfg.signature(False, for_call=True) initparams = sdfg.signature(with_arrays=False) initparamnames = sdfg.signature(False, for_call=True, with_arrays=False) # Invoke all instrumentation providers for instr in self._dispatcher.instrumentation.values(): if instr is not None: instr.on_sdfg_end(sdfg, callsite_stream, global_stream) # Instrumentation saving if (config.Config.get_bool('instrumentation', 'report_each_invocation') and len(self._dispatcher.instrumentation) > 1): callsite_stream.write( '''__state->report.save("{path}/perf", __HASH_{name});'''. format(path=sdfg.build_folder.replace('\\', '/'), name=sdfg.name), sdfg) # Write closing brace of program callsite_stream.write('}', sdfg) # Write awkward footer to avoid 'extern "C"' issues params_comma = (', ' + params) if params else '' initparams_comma = (', ' + initparams) if initparams else '' paramnames_comma = (', ' + paramnames) if paramnames else '' initparamnames_comma = (', ' + initparamnames) if initparamnames else '' callsite_stream.write( f''' DACE_EXPORTED void __program_{fname}({fname}_t *__state{params_comma}) {{ __program_{fname}_internal(__state{paramnames_comma}); }}''', sdfg) for target in self._dispatcher.used_targets: if target.has_initializer: callsite_stream.write( 'DACE_EXPORTED int __dace_init_%s(%s_t *__state%s);\n' % (target.target_name, sdfg.name, initparams_comma), sdfg) if target.has_finalizer: callsite_stream.write( 'DACE_EXPORTED int __dace_exit_%s(%s_t *__state);\n' % (target.target_name, sdfg.name), sdfg) callsite_stream.write( f""" DACE_EXPORTED {sdfg.name}_t *__dace_init_{sdfg.name}({initparams}) {{ int __result = 0; {sdfg.name}_t *__state = new {sdfg.name}_t; """, sdfg) for target in self._dispatcher.used_targets: if target.has_initializer: callsite_stream.write( '__result |= __dace_init_%s(__state%s);' % (target.target_name, initparamnames_comma), sdfg) for env in self.environments: init_code = _get_or_eval_sdfg_first_arg(env.init_code, sdfg) if init_code: callsite_stream.write("{ // Environment: " + env.__name__, sdfg) callsite_stream.write(init_code) callsite_stream.write("}") for sd in sdfg.all_sdfgs_recursive(): if None in sd.init_code: callsite_stream.write(codeblock_to_cpp(sd.init_code[None]), sd) callsite_stream.write(codeblock_to_cpp(sd.init_code['frame']), sd) callsite_stream.write(self._initcode.getvalue(), sdfg) callsite_stream.write( f""" if (__result) {{ delete __state; return nullptr; }} return __state; }} DACE_EXPORTED void __dace_exit_{sdfg.name}({sdfg.name}_t *__state) {{ """, sdfg) # Instrumentation saving if (not config.Config.get_bool('instrumentation', 'report_each_invocation') and len(self._dispatcher.instrumentation) > 1): callsite_stream.write( '__state->report.save("%s/perf", __HASH_%s);' % (sdfg.build_folder.replace('\\', '/'), sdfg.name), sdfg) callsite_stream.write(self._exitcode.getvalue(), sdfg) for sd in sdfg.all_sdfgs_recursive(): if None in sd.exit_code: callsite_stream.write(codeblock_to_cpp(sd.exit_code[None]), sd) callsite_stream.write(codeblock_to_cpp(sd.exit_code['frame']), sd) for target in self._dispatcher.used_targets: if target.has_finalizer: callsite_stream.write( '__dace_exit_%s(__state);' % target.target_name, sdfg) for env in reversed(self.environments): finalize_code = _get_or_eval_sdfg_first_arg( env.finalize_code, sdfg) if finalize_code: callsite_stream.write("{ // Environment: " + env.__name__, sdfg) callsite_stream.write(finalize_code) callsite_stream.write("}") callsite_stream.write('delete __state;\n}\n', sdfg)
def generate_footer(self, sdfg: SDFG, used_environments: Set[str], global_stream: CodeIOStream, callsite_stream: CodeIOStream): """ Generate the footer of the frame-code. Code exists in a separate function for overriding purposes. :param sdfg: The input SDFG. :param global_stream: Stream to write to (global). :param callsite_stream: Stream to write to (at call site). """ fname = sdfg.name params = sdfg.signature() paramnames = sdfg.signature(False, for_call=True) environments = [ dace.library.get_environment(env_name) for env_name in used_environments ] # Invoke all instrumentation providers for instr in self._dispatcher.instrumentation.values(): if instr is not None: instr.on_sdfg_end(sdfg, callsite_stream, global_stream) # Instrumentation saving if len(self._dispatcher.instrumentation) > 1: callsite_stream.write( 'dace::perf::report.save("%s/perf");' % sdfg.build_folder.replace('\\', '/'), sdfg) # Write closing brace of program callsite_stream.write('}', sdfg) # Write awkward footer to avoid 'extern "C"' issues callsite_stream.write( """ DACE_EXPORTED void __program_%s(%s) { __program_%s_internal(%s); } """ % (fname, params, fname, paramnames), sdfg) for target in self._dispatcher.used_targets: if target.has_initializer: callsite_stream.write( 'DACE_EXPORTED int __dace_init_%s(%s);\n' % (target.target_name, params), sdfg) if target.has_finalizer: callsite_stream.write( 'DACE_EXPORTED int __dace_exit_%s(%s);\n' % (target.target_name, params), sdfg) callsite_stream.write( """ DACE_EXPORTED int __dace_init_%s(%s) { int __result = 0; """ % (sdfg.name, params), sdfg) for target in self._dispatcher.used_targets: if target.has_initializer: callsite_stream.write( '__result |= __dace_init_%s(%s);' % (target.target_name, paramnames), sdfg) for env in environments: if env.init_code: callsite_stream.write("{ // Environment: " + env.__name__, sdfg) callsite_stream.write(env.init_code) callsite_stream.write("}") for sd in sdfg.all_sdfgs_recursive(): if None in sd.init_code: callsite_stream.write(codeblock_to_cpp(sd.init_code[None]), sd) callsite_stream.write(codeblock_to_cpp(sd.init_code['frame']), sd) callsite_stream.write(self._initcode.getvalue(), sdfg) callsite_stream.write( """ return __result; } DACE_EXPORTED void __dace_exit_%s(%s) { """ % (sdfg.name, params), sdfg) callsite_stream.write(self._exitcode.getvalue(), sdfg) for sd in sdfg.all_sdfgs_recursive(): if None in sd.exit_code: callsite_stream.write(codeblock_to_cpp(sd.exit_code[None]), sd) callsite_stream.write(codeblock_to_cpp(sd.exit_code['frame']), sd) for target in self._dispatcher.used_targets: if target.has_finalizer: callsite_stream.write( '__dace_exit_%s(%s);' % (target.target_name, paramnames), sdfg) for env in environments: if env.finalize_code: callsite_stream.write("{ // Environment: " + env.__name__, sdfg) callsite_stream.write(env.init_code) callsite_stream.write("}") callsite_stream.write('}\n', sdfg)