def generate_node(self, sdfg: SDFG, state: SDFGState, state_id: int, node: nodes.Node, function_stream: CodeIOStream, callsite_stream: CodeIOStream): self.add_header(function_stream) if not isinstance(node, nodes.Tasklet): return scope = util.get_sve_scope(sdfg, state, node) # Reset the stream variable mappings self.stream_associations = dict() self.wcr_associations = dict() callsite_stream.write('{') self.dispatcher.defined_vars.enter_scope(node) ################## # Generate tasklet # Inputs for edge in state.in_edges(node): self.generate_read(sdfg, state, scope.map, edge, callsite_stream) requires_wb = [] # Temporary output registers for edge in state.out_edges(node): if self.generate_out_register(sdfg, state, edge, callsite_stream): requires_wb.append(edge) # Tasklet code self.unparse_tasklet(sdfg, state, state_id, node, function_stream, callsite_stream) # Writeback from temporary registers to memory for edge in requires_wb: self.generate_writeback(sdfg, state, scope, edge, callsite_stream) self.dispatcher.defined_vars.exit_scope(node) callsite_stream.write('}')
def unparse_tasklet(self, sdfg: sdfg.SDFG, dfg: state.StateSubgraphView, state_id: int, node: nodes.Node, function_stream: prettycode.CodeIOStream, callsite_stream: prettycode.CodeIOStream): # extract data state = sdfg.nodes()[state_id] tasklet = node # construct variables paths unique_name: str = "{}_{}_{}_{}".format(tasklet.name, sdfg.sdfg_id, sdfg.node_id(state), state.node_id(tasklet)) # Collect all of the input and output connectors into buses and scalars buses = {} scalars = {} for edge in state.in_edges(tasklet): arr = sdfg.arrays[edge.src.data] # catch symbolic (compile time variables) check_issymbolic([ tasklet.in_connectors[edge.dst_conn].veclen, tasklet.in_connectors[edge.dst_conn].bytes ], sdfg) # extract parameters vec_len = int( symbolic.evaluate(tasklet.in_connectors[edge.dst_conn].veclen, sdfg.constants)) total_size = int( symbolic.evaluate(tasklet.in_connectors[edge.dst_conn].bytes, sdfg.constants)) if isinstance(arr, data.Array): if self.hardware_target: raise NotImplementedError( 'Array input for hardware* not implemented') else: buses[edge.dst_conn] = (False, total_size, vec_len) elif isinstance(arr, data.Stream): buses[edge.dst_conn] = (False, total_size, vec_len) elif isinstance(arr, data.Scalar): scalars[edge.dst_conn] = (False, total_size * 8) for edge in state.out_edges(tasklet): arr = sdfg.arrays[edge.dst.data] # catch symbolic (compile time variables) check_issymbolic([ tasklet.out_connectors[edge.src_conn].veclen, tasklet.out_connectors[edge.src_conn].bytes ], sdfg) # extract parameters vec_len = int( symbolic.evaluate(tasklet.out_connectors[edge.src_conn].veclen, sdfg.constants)) total_size = int( symbolic.evaluate(tasklet.out_connectors[edge.src_conn].bytes, sdfg.constants)) if isinstance(arr, data.Array): if self.hardware_target: raise NotImplementedError( 'Array input for hardware* not implemented') else: buses[edge.src_conn] = (True, total_size, vec_len) elif isinstance(arr, data.Stream): buses[edge.src_conn] = (True, total_size, vec_len) elif isinstance(arr, data.Scalar): print('Scalar output not implemented') # generate system verilog module components parameter_string: str = self.generate_rtl_parameters(sdfg.constants) inputs, outputs = self.generate_rtl_inputs_outputs(buses, scalars) # create rtl code object (that is later written to file) self.code_objects.append( codeobject.CodeObject( name="{}".format(unique_name), code=RTLCodeGen.RTL_HEADER.format(name=unique_name, parameters=parameter_string, inputs="\n".join(inputs), outputs="\n".join(outputs)) + tasklet.code.code + RTLCodeGen.RTL_FOOTER, language="sv", target=RTLCodeGen, title="rtl", target_type="{}".format(unique_name), additional_compiler_kwargs="", linkable=True, environments=None)) if self.hardware_target: if self.vendor == 'xilinx': rtllib_config = { "name": unique_name, "buses": { name: ('m_axis' if is_output else 's_axis', vec_len) for name, (is_output, _, vec_len) in buses.items() }, "params": { "scalars": { name: total_size for name, (_, total_size) in scalars.items() }, "memory": {} }, "ip_cores": tasklet.ip_cores if isinstance( tasklet, nodes.RTLTasklet) else {}, } self.code_objects.append( codeobject.CodeObject(name=f"{unique_name}_control", code=rtllib_control(rtllib_config), language="v", target=RTLCodeGen, title="rtl", target_type="{}".format(unique_name), additional_compiler_kwargs="", linkable=True, environments=None)) self.code_objects.append( codeobject.CodeObject(name=f"{unique_name}_top", code=rtllib_top(rtllib_config), language="v", target=RTLCodeGen, title="rtl", target_type="{}".format(unique_name), additional_compiler_kwargs="", linkable=True, environments=None)) self.code_objects.append( codeobject.CodeObject(name=f"{unique_name}_package", code=rtllib_package(rtllib_config), language="tcl", target=RTLCodeGen, title="rtl", target_type="scripts", additional_compiler_kwargs="", linkable=True, environments=None)) self.code_objects.append( codeobject.CodeObject(name=f"{unique_name}_synth", code=rtllib_synth(rtllib_config), language="tcl", target=RTLCodeGen, title="rtl", target_type="scripts", additional_compiler_kwargs="", linkable=True, environments=None)) else: # self.vendor != "xilinx" raise NotImplementedError( 'Only RTL codegen for Xilinx is implemented') else: # not hardware_target # generate verilator simulation cpp code components inputs, outputs = self.generate_cpp_inputs_outputs(tasklet) valid_zeros, ready_zeros = self.generate_cpp_zero_inits(tasklet) vector_init = self.generate_cpp_vector_init(tasklet) num_elements = self.generate_cpp_num_elements(tasklet) internal_state_str, internal_state_var = self.generate_cpp_internal_state( tasklet) read_input_hs = self.generate_input_hs(tasklet) feed_elements = self.generate_feeding(tasklet, inputs) in_ptrs, out_ptrs = self.generate_ptrs(tasklet) export_elements = self.generate_exporting(tasklet, outputs) write_output_hs = self.generate_write_output_hs(tasklet) hs_flags = self.generate_hs_flags(tasklet) input_hs_toggle = self.generate_input_hs_toggle(tasklet) output_hs_toggle = self.generate_output_hs_toggle(tasklet) running_condition = self.generate_running_condition(tasklet) # add header code to stream if not self.cpp_general_header_added: sdfg.append_global_code( cpp_code=RTLCodeGen.CPP_GENERAL_HEADER_TEMPLATE.format( debug_include="// generic includes\n#include <iostream>" if self.verilator_debug else "")) self.cpp_general_header_added = True sdfg.append_global_code( cpp_code=RTLCodeGen.CPP_MODEL_HEADER_TEMPLATE.format( name=unique_name)) # add main cpp code to stream callsite_stream.write(contents=RTLCodeGen.CPP_MAIN_TEMPLATE.format( name=unique_name, inputs=inputs, outputs=outputs, num_elements=str.join('\n', num_elements), vector_init=vector_init, valid_zeros=str.join('\n', valid_zeros), ready_zeros=str.join('\n', ready_zeros), read_input_hs=str.join('\n', read_input_hs), feed_elements=str.join('\n', feed_elements), in_ptrs=str.join('\n', in_ptrs), out_ptrs=str.join('\n', out_ptrs), export_elements=str.join('\n', export_elements), write_output_hs=str.join('\n', write_output_hs), hs_flags=str.join('\n', hs_flags), input_hs_toggle=str.join('\n', input_hs_toggle), output_hs_toggle=str.join('\n', output_hs_toggle), running_condition=str.join(' && ', running_condition), internal_state_str=internal_state_str, internal_state_var=internal_state_var, debug_sim_start="std::cout << \"SIM {name} START\" << std::endl;" if self.verilator_debug else "", debug_internal_state=""" // report internal state VL_PRINTF("[t=%lu] ap_aclk=%u ap_areset=%u valid_i=%u ready_i=%u valid_o=%u ready_o=%u \\n", main_time, model->ap_aclk, model->ap_areset, model->valid_i, model->ready_i, model->valid_o, model->ready_o); VL_PRINTF("{internal_state_str}\\n", {internal_state_var}); std::cout << std::flush; """.format(internal_state_str=internal_state_str, internal_state_var=internal_state_var) if self.verilator_debug else "", debug_sim_end="std::cout << \"SIM {name} END\" << std::endl;" if self.verilator_debug else ""), sdfg=sdfg, state_id=state_id, node_id=node)