def create_invocation_end(ctxt: InvocationContext, builder: GraphTypeBuilder): for set in ctxt.get_all_involved_sets(): with builder.subst(set=set.id): handler = """ assert(deviceState->{invocation}_in_progress); assert( deviceState->{invocation}_read_send_mask == 0 ); assert( deviceState->{invocation}_write_send_mask == 0 ); assert( deviceState->{invocation}_read_recv_count == 0 ); assert( deviceState->{invocation}_write_recv_count == deviceProperties->{invocation}_write_recv_total ); deviceState->{invocation}_in_progress=0; deviceState->{invocation}_read_recv_count=0; deviceState->{invocation}_write_recv_count=0; """ if set == ctxt.stat.iter_set: for (ai, arg) in ctxt.global_writes: handler += """ copy_value(message->global_{}, deviceState->global_{}); """.format(arg.global_.id, arg.global_.id) else: for (ai, arg) in ctxt.global_writes: handler += """ zero_value(message->global_{}); """.format(arg.global_.id) builder.add_output_pin("set_{set}", "{invocation}_end", "{invocation}_end", handler)
def create_indirect_read_sends(ctxt: InvocationContext, builder: GraphTypeBuilder): for dat in ctxt.get_indirect_read_dats(): with builder.subst(dat=dat.id, set=dat.set.id): builder.add_output_pin( "set_{set}", "{invocation}_dat_{dat}_read_send", "dat_{dat}", """ assert(deviceState->{invocation}_read_send_mask & RTS_FLAG_{invocation}_dat_{dat}_read_send); copy_value(message->value, deviceState->dat_{dat}); deviceState->{invocation}_read_send_mask &= ~RTS_FLAG_{invocation}_dat_{dat}_read_send; """)
def create_invocation_execute(ctxt: InvocationContext, builder: GraphTypeBuilder): for set in ctxt.get_all_involved_sets(): with builder.subst(set=set.id, kernel=ctxt.stat.name): handler = """ assert( deviceState->{invocation}_in_progress ); assert( deviceState->{invocation}_read_recv_count == {invocation}_{set}_read_recv_total ); deviceState->{invocation}_read_recv_count=0; // Allows us to tell that execute has happened deviceState->{invocation}_write_recv_count++; // The increment for this "virtual" receive deviceState->{invocation}_write_send_mask = {invocation}_{set}_write_send_mask_all; // In device-local shared code """ if set == ctxt.stat.iter_set: handler += "kernel_{kernel}(\n" for (ai, arg) in enumerate(ctxt.stat.arguments): if isinstance(arg, GlobalArgument): if ( ai, arg ) in ctxt.mutable_global_reads | ctxt.global_writes: handler += builder.s(" deviceState->global_{id}", id=arg.global_.id) else: handler += builder.s( " (double*)graphProperties->global_{id}", id=arg.global_.id) elif isinstance(arg, DirectDatArgument): handler += builder.s(" deviceState->dat_{dat}", dat=arg.dat.id) elif isinstance(arg, IndirectDatArgument): handler += builder.s( " deviceState->{invocation}_arg{index}_buffer", index=ai) else: raise RuntimeError("Unexpected arg type.") if ai + 1 < len(ctxt.stat.arguments): handler += "," handler += "\n" handler += ");\n" builder.add_output_pin("set_{set}", "{invocation}_execute", "executeMsgType", handler)
def create_invocation_controller(ctxt: InvocationContext, builder: GraphTypeBuilder): handler = """ assert(deviceState->end_received==0); assert(deviceState->invocation_index==RTS_INDEX_controller_{invocation}_begin); deviceState->end_received=0; deviceState->rts=0; """ for (ai, arg) in ctxt.mutable_global_reads: handler += builder.s(""" copy_value(message->global_{name}, deviceState->global_{name}); """, name=arg.global_.id) builder.add_output_pin("controller", "{invocation}_begin", "{invocation}_begin", handler) handler = """ assert(deviceState->invocation_index==RTS_INDEX_controller_{invocation}_begin); assert(deviceState->end_received < graphProperties->{invocation}_total_responding_devices); deviceState->end_received++; """ # Collect any inc's to global values for (ai, arg) in ctxt.global_writes: assert arg.access_mode == AccessMode.INC handler += builder.s(""" inc_value(deviceState->global_{name}, message->global_{name}); """, name=arg.global_.id) # Check whether we have finished handler += """ if(deviceState->end_received == graphProperties->{invocation}_total_responding_devices){{ """ handler += """ deviceState->invocation_index=-1; deviceState->end_received=0; deviceState->rts=RTS_FLAG_controller_control; }} """ builder.add_input_pin("controller", "{invocation}_end", "{invocation}_end", None, None, handler)
def create_indirect_write_sends(ctxt: InvocationContext, builder: GraphTypeBuilder): for (ai, arg) in ctxt.indirect_writes: with builder.subst(index=ai, set=arg.iter_set.id, dat=arg.dat.id, arity=-arg.index): if arg.index >= 0: builder.add_output_pin( "set_{set}", "{invocation}_arg{index}_write_send", "dat_{dat}", """ assert(deviceState->{invocation}_write_send_mask & RTS_FLAG_{invocation}_arg{index}_write_send); copy_value(message->value, deviceState->{invocation}_arg{index}_buffer); deviceState->{invocation}_write_send_mask &= ~RTS_FLAG_{invocation}_arg{index}_write_send; """) else: builder.add_output_pin( "set_{set}", "{invocation}_arg{index}_write_send", "dat_{dat}_x{arity}", """ assert(deviceState->{invocation}_write_send_mask & RTS_FLAG_{invocation}_arg{index}_write_send); copy_value(message->value, deviceState->{invocation}_arg{index}_buffer); deviceState->{invocation}_write_send_mask &= ~RTS_FLAG_{invocation}_arg{index}_write_send; """)
def compile_global_controller(gi: str, spec: SystemSpecification, builder: GraphTypeBuilder, code: Statement): create_controller_states( code) # Make sure every statement has an entry state builder.add_device_state(gi, "rts", scalar_uint32) builder.add_device_state(gi, "state", scalar_uint32) # This will be used as a hidden global, and captures the value # of the condition for If and While assert "_cond_" in spec.globals start_state = get_statement_state(code) finish_state = make_state() builder.add_rts_clause(gi, "*readyToSend = deviceState->rts;\n") with builder.subst(start_state=start_state): handler = """ deviceState->rts=RTS_FLAG_control; deviceState->state={start_state}; handler_log(4, "rts=%x, state=%d", deviceState->rts, deviceState->state); """ for mg in spec.globals.values(): if isinstance(mg, MutableGlobal): handler += """ copy_value(deviceState->global_{global_}, graphProperties->init_global_{global_}); """.format(global_=mg.id) builder.add_input_pin(gi, "__init__", "__init__", None, None, handler) handler = raw(""" handler_log(4, "rts=%x, state=%d", deviceState->rts, deviceState->state); *doSend=0; // disable this send... deviceState->rts=RTS_FLAG_control; // ... but say that we want to send again (by default) switch(deviceState->state){ """) handler += render_controller_statement(code, finish_state) handler += """ case {finish_state}: handler_log(4, "Hit finish state."); handler_exit(0); break; default: handler_log(3, "Unknown state id %d.", deviceState->state); assert(0); }} """.format(finish_state=finish_state) builder.create_message_type("control", {}) builder.add_output_pin(gi, "control", "control", handler) for user_code in find_scalars_in_code(code): name = user_code.id assert user_code.ast src = mini_op2.framework.kernel_translator.scalar_to_c( user_code.ast, name) builder.add_device_shared_code("controller", raw(src)) for k in code.all_statements(): if isinstance(k, While): name = k.id src = mini_op2.framework.kernel_translator.scalar_to_c( k.expr_ast, name) builder.add_device_shared_code("controller", raw(src))
def create_invocation_tester(testIndex: int, isLast: bool, ctxt: InvocationContext, builder: GraphTypeBuilder): with builder.subst(testIndex=testIndex, isLast=int(isLast)): handler = """ assert(deviceState->end_received==0); assert(deviceState->test_state==2*{testIndex}); deviceState->test_state++; // Odd value means we are waiting for the return deviceState->end_received=0; """ #for (ai,arg) in ctxt.mutable_global_reads: # handler+=builder.s(""" # copy_value(message->global_{name}, graphProperties->test_{invocation}_{name}_in); # """,name=arg.global_.id) builder.add_output_pin("tester", "{invocation}_begin", "{invocation}_begin", handler) handler = """ assert(deviceState->test_state==2*{testIndex}+1); assert(deviceState->end_received < graphProperties->{invocation}_total_responding_devices); deviceState->end_received++; """ # Collect any inc's to global values for (ai, arg) in ctxt.global_writes: assert arg.access_mode == AccessMode.INC handler += builder.s(""" inc_value(deviceState->global_{name}, message->global_{name}); """, name=arg.global_.id) # Check whether we have finished handler += """ if(deviceState->end_received == graphProperties->{invocation}_total_responding_devices){{ """ # Remove for now - not clear how to do this. if False: # ... and if so, try to check the results are "right" for (ai, arg) in ctxt.global_writes: handler += builder.s(""" check_value(deviceState->global_{name}, graphProperties->test_{invocation}_{name}_out); """, name=arg.global_.id) handler += """ if( {isLast} ){{ handler_exit(0); }}else{{ deviceState->test_state++; // start the next invocation deviceState->end_received=0; }} }} """ builder.add_input_pin("tester", "{invocation}_end", "{invocation}_end", None, None, handler) builder.add_rts_clause( "tester", """ if(deviceState->test_state==2*{testIndex}){{ *readyToSend = RTS_FLAG_{invocation}_begin; }} """)