def gen_fifo_functions(self): """ Push and pop code generator for fifo buffering. """ sdfgraph = self.sdfgraph bufsize = self.get_bufsize() pfn = writer() # generate reset code reset_code = writer(); reset_code.writeln('static inline void __RESET_PTR(){') reset_code.indent() # iterator for delay copy reset_code.writeln('int i = 0;') # generate push and pop functions and variables for edge in sdfgraph.edges(): (source,target) = edge buffer_id='buf_'+source+'_'+target token_type=sdfgraph.token_type[edge] num_delay=sdfgraph.delay[edge] pfn.writeln('static '+token_type+' '+buffer_id+'['+str(bufsize[edge])+'] = {0};') pfn.writeln('static int head_'+source+'_'+target+'=0;') pfn.writeln('static int tail_'+source+'_'+target+'=0;') pfn.writeln('static inline void push_'+source+'_'+target+'('+token_type+' x){') pfn.indent() pfn.writeln('buf_'+source+'_'+target+'[tail_'+source+'_'+target+'++]=x;') reset_code.writeln('tail_'+source+'_'+target+'='+str(num_delay)+';') if num_delay > 0: reset_code.writeln('for ( i = 0; i < '+str(num_delay)+'; i++){') reset_code.indent() reset_code.writeln(buffer_id+'[i]='+buffer_id+'['+str(bufsize[edge]-num_delay)+'+i];') reset_code.unindent() reset_code.writeln('}') reset_code.writeln('') pfn.unindent() pfn.writeln('}') pfn.writeln('static inline ' + token_type+' pop_'+source+'_'+target+'(){') pfn.indent() pfn.writeln(token_type+' x;'); pfn.writeln('x=buf_'+source+'_'+target+'[head_'+source+'_'+target+'++];') reset_code.writeln('head_'+source+'_'+target+'=0;') pfn.writeln('return x;') pfn.unindent() pfn.writeln('}') pfn.writeln('static inline ' + token_type+' peek_'+source+'_'+target+'(int _idx){') pfn.indent() pfn.writeln(token_type+' x;'); pfn.writeln('x=buf_'+source+'_'+target+'[head_'+source+'_'+target+'+_idx];') pfn.writeln('return x;') pfn.unindent() pfn.writeln('}') pfn.writeln('') reset_code.writeln('return;') reset_code.unindent() reset_code.writeln('}') return pfn.get() + reset_code.get()
def gen_init(self): """ Generate init codes """ sdfgraph = self.sdfgraph code = writer() code.indent() code.writeln(self.profiler.gen_profile_init(self.scheduler.get_numprocessors(), self.iterations)) code.unindent() code.writeln('// BEGIN: init functions of actors') code.indent() for actor in sdfgraph.nodes(): if sdfgraph.is_generic(actor) and sdfgraph.init[actor] <> '': code.writeln('{') code.indent() init_code = sdfgraph.init[actor] param_list = sdfgraph.node_param[actor] for i in range(0, len(param_list)): (p_type, p_name, p_value) = param_list[i] init_code = init_code.replace(p_name, str(p_value)) code.writeln(init_code) code.unindent() code.writeln('}') code.unindent() code.writeln('// END: init functions of actors') return code.get()
def read_prefetch(self, var, source, target): code = writer() locality = 2 if not source == target: code.writeln('__builtin_prefetch(&' + var + ', 0, ' + str(locality) + ');') return code.get()
def gen_init(self): """ Generate init codes """ sdfgraph = self.sdfgraph code = writer() code.indent() code.writeln( self.profiler.gen_profile_init(self.scheduler.get_numprocessors(), self.iterations)) code.unindent() code.writeln('// BEGIN: init functions of actors') code.indent() for actor in sdfgraph.nodes(): if sdfgraph.is_generic(actor) and sdfgraph.init[actor] <> '': code.writeln('{') code.indent() init_code = sdfgraph.init[actor] param_list = sdfgraph.node_param[actor] for i in range(0, len(param_list)): (p_type, p_name, p_value) = param_list[i] init_code = init_code.replace(p_name, str(p_value)) code.writeln(init_code) code.unindent() code.writeln('}') code.unindent() code.writeln('// END: init functions of actors') return code.get()
def gen_sequence(self, schedule, tid, LocalVars=True, ivar='i'): """ Generate code to invoke actors in sequence of a given schedule. :param schedule: A sequance of actors as a schedule :param procId: Index of the processor to store the execution \ time. If the value is negative, then the functions calls for \ execution time measurement are omitted \ (e.g., sequence for booting). :param ivar: loop variable for a steady state iteration """ sdfgraph = self.sdfgraph if tid < 0: prof = profiler() else: prof = self.profiler code = writer() code.indent() code.indent() for seq in range(0,len(schedule)): actor = schedule[seq] code.writeln('{') code.indent() code.write(prof.gen_actor_profile_start(tid,seq)) varctr = 1 for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred,actor) for i in range(0,sdfgraph.consumption[edge]): var = sdfgraph.token_type[edge]+' x'+str(varctr) fn = 'pop_' + pred +'_' + actor + '()' varctr = varctr+1 varctr = 1 for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor,succ) for i in range(0,sdfgraph.production[edge]): var = 'y'+str(varctr) varctr = varctr+1 actor_function = 'actor_' + actor code.write(actor_function+ '(') code.indent() first = True varctr = 1 for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred,actor) for i in range(0,sdfgraph.consumption[edge]): var = 'x'+str(varctr) varctr = varctr+1 varctr = 1 for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor,succ) for i in range(0,sdfgraph.production[edge]): var = 'y'+str(varctr) varctr = varctr+1 code.unindent() code.writeln(');') code.unindent() code.writeln('}') code.writeln('') code.write(prof.gen_actor_profile_stop(tid,seq)) code.write(prof.gen_actor_profile_record(actor,0,seq,ivar)) return code.get()
def gen_sequence(self, schedule, tid, LocalVars=True, ivar='i'): """ Generate code to invoke actors in sequence of a given schedule. :param schedule: A sequance of actors as a schedule :param procId: Index of the processor to store the execution \ time. If the value is negative, then the functions calls for \ execution time measurement are omitted \ (e.g., sequence for booting). :param ivar: loop variable for a steady state iteration """ sdfgraph = self.sdfgraph if tid < 0: prof = profiler() else: prof = self.profiler code = writer() code.indent() code.indent() for seq in range(0, len(schedule)): actor = schedule[seq] code.writeln('{') code.indent() code.write(prof.gen_actor_profile_start(tid, seq)) varctr = 1 for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred, actor) for i in range(0, sdfgraph.consumption[edge]): var = sdfgraph.token_type[edge] + ' x' + str(varctr) fn = 'pop_' + pred + '_' + actor + '()' varctr = varctr + 1 varctr = 1 for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor, succ) for i in range(0, sdfgraph.production[edge]): var = 'y' + str(varctr) varctr = varctr + 1 actor_function = 'actor_' + actor code.write(actor_function + '(') code.indent() first = True varctr = 1 for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred, actor) for i in range(0, sdfgraph.consumption[edge]): var = 'x' + str(varctr) varctr = varctr + 1 varctr = 1 for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor, succ) for i in range(0, sdfgraph.production[edge]): var = 'y' + str(varctr) varctr = varctr + 1 code.unindent() code.writeln(');') code.unindent() code.writeln('}') code.writeln('') code.write(prof.gen_actor_profile_stop(tid, seq)) code.write(prof.gen_actor_profile_record(actor, 0, seq, ivar)) return code.get()
def header(self): code = writer() code.writeln('#include "rts/rts.h"') code.writeln('') code.writeln('struct RTS_VARS* thr_vars __attribute__((aligned(CACHELINE_SIZE)));') code.writeln('int numcpus __attribute__((aligned(CACHELINE_SIZE)));') code.writeln('int numiters __attribute__((aligned(CACHELINE_SIZE)));') return code.get()
def header(self): code = writer() code.writeln('#include "papi_wrapper/papi_hw_counter.h"') code.writeln('') code.writeln('FILE *summary_f;') code.writeln('struct PAPI_VARS* thr_vars __attribute__((aligned(CACHELINE_SIZE)));') code.writeln('int numcpus __attribute__((aligned(CACHELINE_SIZE)));') code.writeln('int numiters __attribute__((aligned(CACHELINE_SIZE)));') return code.get()
def header(self): code = writer() code.writeln('#include "rts/rts.h"') code.writeln('') code.writeln( 'struct RTS_VARS* thr_vars __attribute__((aligned(CACHELINE_SIZE)));' ) code.writeln('int numcpus __attribute__((aligned(CACHELINE_SIZE)));') code.writeln('int numiters __attribute__((aligned(CACHELINE_SIZE)));') return code.get()
def header(self): code = writer() code.writeln('#include "papi_wrapper/papi_hw_counter.h"') code.writeln('') code.writeln('FILE *summary_f;') code.writeln( 'struct PAPI_VARS* thr_vars __attribute__((aligned(CACHELINE_SIZE)));' ) code.writeln('int numcpus __attribute__((aligned(CACHELINE_SIZE)));') code.writeln('int numiters __attribute__((aligned(CACHELINE_SIZE)));') return code.get()
def gen_state(self, schedule): """ Generate list of state variables accessed by the given schedule. :param schedule: A sequance of actors as a schedule """ sdfgraph = self.sdfgraph num_processor = self.scheduler.get_numprocessors() state = writer() state_decls = {} state.writeln('// BEGIN: state variables for actors') for seq in range(0, len(schedule)): actor = schedule[seq] if sdfgraph.is_generic(actor): # add states to decl if actor not in state_decls: state_decls[actor] = writer() state_decls[actor].write(sdfgraph.state[actor]) for actor in state_decls: if state_decls[actor].get() != "": state.write(state_decls[actor].get()) state.writeln('\n// END: state variables for actors') return state.get()
def gen_state(self, schedule): """ Generate list of state variables accessed by the given schedule. :param schedule: A sequance of actors as a schedule """ sdfgraph = self.sdfgraph num_processor=self.scheduler.get_numprocessors() state = writer() state_decls = {} state.writeln('// BEGIN: state variables for actors') for seq in range(0,len(schedule)): actor = schedule[seq] if sdfgraph.is_generic(actor): # add states to decl if actor not in state_decls: state_decls[actor]=writer() state_decls[actor].write(sdfgraph.state[actor]) for actor in state_decls: if state_decls[actor].get() != "": state.write(state_decls[actor].get()) state.writeln('\n// END: state variables for actors') return state.get()
def gen_fifo_functions(self): """ Push and pop code generator for fifo buffering. """ sdfgraph = self.sdfgraph bufsize = self.get_bufsize() pfn = writer() # generate reset code reset_code = writer() reset_code.writeln('static inline void __RESET_PTR(){') reset_code.indent() # iterator for delay copy reset_code.writeln('int i = 0;') # generate push and pop functions and variables for edge in sdfgraph.edges(): (source, target) = edge buffer_id = 'buf_' + source + '_' + target token_type = sdfgraph.token_type[edge] num_delay = sdfgraph.delay[edge] pfn.writeln('static ' + token_type + ' ' + buffer_id + '[' + str(bufsize[edge]) + '] = {0};') pfn.writeln('static int head_' + source + '_' + target + '=0;') pfn.writeln('static int tail_' + source + '_' + target + '=0;') pfn.writeln('static inline void push_' + source + '_' + target + '(' + token_type + ' x){') pfn.indent() pfn.writeln('buf_' + source + '_' + target + '[tail_' + source + '_' + target + '++]=x;') reset_code.writeln('tail_' + source + '_' + target + '=' + str(num_delay) + ';') if num_delay > 0: reset_code.writeln('for ( i = 0; i < ' + str(num_delay) + '; i++){') reset_code.indent() reset_code.writeln(buffer_id + '[i]=' + buffer_id + '[' + str(bufsize[edge] - num_delay) + '+i];') reset_code.unindent() reset_code.writeln('}') reset_code.writeln('') pfn.unindent() pfn.writeln('}') pfn.writeln('static inline ' + token_type + ' pop_' + source + '_' + target + '(){') pfn.indent() pfn.writeln(token_type + ' x;') pfn.writeln('x=buf_' + source + '_' + target + '[head_' + source + '_' + target + '++];') reset_code.writeln('head_' + source + '_' + target + '=0;') pfn.writeln('return x;') pfn.unindent() pfn.writeln('}') pfn.writeln('static inline ' + token_type + ' peek_' + source + '_' + target + '(int _idx){') pfn.indent() pfn.writeln(token_type + ' x;') pfn.writeln('x=buf_' + source + '_' + target + '[head_' + source + '_' + target + '+_idx];') pfn.writeln('return x;') pfn.unindent() pfn.writeln('}') pfn.writeln('') reset_code.writeln('return;') reset_code.unindent() reset_code.writeln('}') return pfn.get() + reset_code.get()
def read_prefetch(self, var, source, target): code=writer() locality=2 if not source == target: code.writeln('__builtin_prefetch(&'+var+', 0, '+str(locality)+');') return code.get()
def gen_actors(self): """ Generate codes for actor functions with fifo buffers. """ sdfgraph = self.sdfgraph code = writer() for actor in sdfgraph.nodes(): code.write('inline static void actor_' + actor + '(') code.indent() first = True in_queue = [] out_queue = [] for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred, actor) for i in range(0, len(sdfgraph.target_tokens[edge])): in_queue.append(sdfgraph.target_tokens[edge][i]) for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor, succ) for i in range(0, len(sdfgraph.source_tokens[edge])): out_queue.append(sdfgraph.source_tokens[edge][i]) code.unindent() code.writeln('){') code.indent() # TBD: add #line directive to each line so that C-Compiler can track source code of sdf program! if sdfgraph.is_generic(actor): if len(sdfgraph.in_nodes(actor)) > 1: print "ERROR: More than 1 incoming node is found: " + actor + "." sys.exit(1) if len(sdfgraph.out_nodes(actor)) > 1: print "ERROR: More than 1 outgoing node is found: " + actor + "." sys.exit(1) pop_fn = 'pop' push_fn = 'push' peek_fn = 'peek' if len(sdfgraph.in_nodes(actor)) == 0 and len( sdfgraph.out_nodes(actor)) == 1: # Source push_fn = 'push_' + actor + '_' + sdfgraph.out_nodes( actor)[0] elif len(sdfgraph.in_nodes(actor)) == 1 and len( sdfgraph.out_nodes(actor)) == 0: # Sink pop_fn = 'pop_' + sdfgraph.in_nodes(actor)[0] + '_' + actor peek_fn = 'peek_' + sdfgraph.in_nodes( actor)[0] + '_' + actor else: pop_fn = 'pop_' + sdfgraph.in_nodes(actor)[0] + '_' + actor push_fn = 'push_' + actor + '_' + sdfgraph.out_nodes( actor)[0] peek_fn = 'peek_' + sdfgraph.in_nodes( actor)[0] + '_' + actor actor_code = sdfgraph.actor_code[actor] param_list = sdfgraph.node_param[actor] for i in range(0, len(param_list)): (p_type, p_name, p_value) = param_list[i] actor_code = actor_code.replace(p_name, str(p_value)) actor_code = re.sub( r"(?=[^0-9A-Za-z_])" + p_name + "(?=[^0-9A-Za-z_])", str(p_value), actor_code) actor_code = re.sub(r"(?<=[^0-9A-Za-z_])pop(?=[^0-9A-Za-z_])", pop_fn, actor_code) actor_code = re.sub(r"(?<=[^0-9A-Za-z_])push(?=[^0-9A-Za-z_])", push_fn, actor_code) actor_code = re.sub(r"(?<=[^0-9A-Za-z_])peek(?=[^0-9A-Za-z_])", peek_fn, actor_code) code.writeln(actor_code) else: # round robin if len(in_queue) == len(out_queue): for i in range(0, len(in_queue)): tokens = out_queue[i].split('_') out_postfix = tokens[1] for j in range(2, len(tokens) - 1): out_postfix = out_postfix + '_' + tokens[j] tokens = in_queue[i].split('_') in_postfix = tokens[1] for j in range(2, len(tokens) - 1): in_postfix = in_postfix + '_' + tokens[j] code.writeln('push_' + out_postfix + '(pop_' + in_postfix + '());') # duplicate elif len(in_queue) < len(out_queue) and \ len(out_queue)%len(in_queue) == 0: i = 0 for o in range(0, len(out_queue)): tokens = out_queue[o].split('_') out_postfix = tokens[1] for j in range(2, len(tokens) - 1): out_postfix = out_postfix + '_' + tokens[j] tokens = in_queue[i].split('_') in_postfix = tokens[1] for j in range(2, len(tokens) - 1): in_postfix = in_postfix + '_' + tokens[j] code.writeln('push_' + out_postfix + '(peek_' + in_postfix + '(' + str(i) + '));') i = i + 1 i = i % len(in_queue) for i in range(0, len(in_queue)): code.writeln('pop_' + in_postfix + '();') # invalid (inconsistent) sdf graph else: print "ERROR: Graph is inconsistent." print " " + actor + " with " + str( len(in_queue)) + " in-tokens and " + str( len(out_queue)) + " out-tokens." sys.exit(1) code.unindent() code.writeln('}') code.writeln('') return code.get()
def gen_schedule(self): """Generate C code based on the SDF graph without buffers for communication. Communications in between two nodes are done by accessing variables assigned on each tokens directly. Thus no additional buffers are required for communication. """ sdfgraph = self.sdfgraph init_schedule = self.scheduler.get_bootschedule() schedule = self.scheduler.get_schedule() max_rep = self.scheduler.get_max_lev_diff() # adjust max_rep to the total number of iteration if self.iterations < max_rep: print 'WARNING: Number of iteration given,', self.iterations, 'is not sufficient to run a steady-state iteration. Adjust the number of iteration automatically to', max_rep self.iterations = max_rep iterations = self.iterations while True: if iterations % max_rep == 0: break max_rep = max_rep + 1 prof = self.profiler self.fifo = {} self.varctr = 1 code = writer() code.indent() decl = writer() decl.indent() global_block = writer() # generate tokens varctr must be not changed (local_tokens, global_tokens) = self.gen_tokens(init_schedule, schedule) ############################################################## # write global token declarations for idx in range(0, len(global_tokens)): (type, var) = global_tokens[idx] global_block.writeln('\nstatic ' + type + ' ' + var + ';') ############################################################## # write local token declarations for idx in range(0, len(local_tokens[0])): (type, var) = local_tokens[0][idx] code.writeln(type + ' ' + var + ';') # push delay tokens to fifo queue for edge in sdfgraph.edges(): (source, target) = edge self.fifo[edge] = [] for i in range(0, sdfgraph.delay[edge]): var = self.token_prefix + str(self.varctr) code.writeln(var + ' = ' + sdfgraph.delay_tokens[edge][i] + ";") self.varctr = self.varctr + 1 self.fifo[edge].append(var) # prepare for profiling if needed code.writeln(prof.gen_profile_thread_init(0, len(schedule[0]))) code.writeln(prof.gen_profile_open(0)) # start - program profiling code.writeln(prof.gen_program_profile_start()) # write booting code if needed code.writeln('\n' + self.gen_sequence(init_schedule, -1)[0].get()) # generate code for processes fifo_snapshot = deepcopy(self.fifo) # loop statement for steady state iteation code.writeln('') if iterations > 0: decl.writeln("int i;") code.writeln('for(i = 0; i <' + str(iterations / max_rep) + '; i++){') else: code.writeln('for(;;){') code.indent() code.write(prof.gen_thread_profile_start(0)) for rep in range(0, max_rep): iter = str(max_rep) + '*i+' + str(rep) # generate code for the steady state iteration based on schedule code.writeln('\n' + self.gen_sequence(schedule[0], 0, ivar=iter)) # preparation for the next iteration # generate code for copying variables for the first iteration and close functions def for edge in sdfgraph.edges(): (source, target) = edge for i in range(0, len(self.fifo[edge])): src_var = fifo_snapshot[edge][i] dst_var = self.fifo[edge][i] code.writeln(src_var + '=' + dst_var + ';') code.unindent() code.writeln(prof.gen_thread_profile_stop(0)) code.writeln(prof.gen_thread_profile_record(0, 'i')) code.writeln('}') # stop - program profiling code.writeln(prof.gen_program_profile_stop()) # record code.writeln(prof.gen_program_profile_record()) # write profiled data code.writeln(prof.gen_profile_write(0)) # finish profiling code.writeln(prof.gen_profile_close(0)) ############################################################## # wrap up as a block block = writer() block.writeln('') if sdfgraph.name == '': name = 'execute' else: name = sdfgraph.name block.writeln('static inline void ' + name + '(){') # generate state declarations block.writeln(self.gen_state(schedule[0])) block.writeln(decl.get()) block.writeln(self.gen_init()) block.write(code.get()) block.writeln('\t' + self.gen_close()) block.writeln('}') block.writeln('') return (global_block.get(), block.get())
def gen_actors(self): """ Generate codes for actor functions with fifo buffers. """ sdfgraph = self.sdfgraph code = writer() for actor in sdfgraph.nodes(): code.write('inline static void actor_'+actor+'(') code.indent() first = True in_queue=[] out_queue=[] for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred,actor) for i in range(0,len(sdfgraph.target_tokens[edge])): in_queue.append(sdfgraph.target_tokens[edge][i]) for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor,succ) for i in range(0,len(sdfgraph.source_tokens[edge])): out_queue.append(sdfgraph.source_tokens[edge][i]) code.unindent() code.writeln('){') code.indent() # TBD: add #line directive to each line so that C-Compiler can track source code of sdf program! if sdfgraph.is_generic(actor): if len(sdfgraph.in_nodes(actor)) > 1: print "ERROR: More than 1 incoming node is found: "+actor+"." sys.exit(1) if len(sdfgraph.out_nodes(actor)) > 1: print "ERROR: More than 1 outgoing node is found: "+actor+"." sys.exit(1) pop_fn = 'pop' push_fn = 'push' peek_fn = 'peek' if len(sdfgraph.in_nodes(actor)) == 0 and len(sdfgraph.out_nodes(actor)) == 1: # Source push_fn = 'push_'+actor+'_'+sdfgraph.out_nodes(actor)[0] elif len(sdfgraph.in_nodes(actor)) == 1 and len(sdfgraph.out_nodes(actor)) == 0: # Sink pop_fn = 'pop_'+sdfgraph.in_nodes(actor)[0]+'_'+actor peek_fn = 'peek_'+sdfgraph.in_nodes(actor)[0]+'_'+actor else: pop_fn = 'pop_'+sdfgraph.in_nodes(actor)[0]+'_'+actor push_fn = 'push_'+actor+'_'+sdfgraph.out_nodes(actor)[0] peek_fn = 'peek_'+sdfgraph.in_nodes(actor)[0]+'_'+actor actor_code = sdfgraph.actor_code[actor] param_list = sdfgraph.node_param[actor] for i in range(0, len(param_list)): (p_type, p_name, p_value) = param_list[i] actor_code = actor_code.replace(p_name, str(p_value)) actor_code = re.sub(r"(?=[^0-9A-Za-z_])"+p_name+"(?=[^0-9A-Za-z_])",str(p_value),actor_code) actor_code = re.sub(r"(?<=[^0-9A-Za-z_])pop(?=[^0-9A-Za-z_])",pop_fn,actor_code) actor_code = re.sub(r"(?<=[^0-9A-Za-z_])push(?=[^0-9A-Za-z_])",push_fn,actor_code) actor_code = re.sub(r"(?<=[^0-9A-Za-z_])peek(?=[^0-9A-Za-z_])",peek_fn,actor_code) code.writeln(actor_code) else: # round robin if len(in_queue) == len(out_queue): for i in range(0,len(in_queue)): tokens=out_queue[i].split('_') out_postfix=tokens[1] for j in range(2, len(tokens)-1): out_postfix=out_postfix+'_'+tokens[j] tokens=in_queue[i].split('_') in_postfix=tokens[1] for j in range(2, len(tokens)-1): in_postfix=in_postfix+'_'+tokens[j] code.writeln('push_'+out_postfix+'(pop_'+in_postfix+'());') # duplicate elif len(in_queue) < len(out_queue) and \ len(out_queue)%len(in_queue) == 0: i = 0 for o in range(0,len(out_queue)): tokens=out_queue[o].split('_') out_postfix=tokens[1] for j in range(2, len(tokens)-1): out_postfix=out_postfix+'_'+tokens[j] tokens=in_queue[i].split('_') in_postfix=tokens[1] for j in range(2, len(tokens)-1): in_postfix=in_postfix+'_'+tokens[j] code.writeln('push_'+out_postfix+'(peek_'+in_postfix+'('+str(i)+'));') i = i + 1 i = i % len(in_queue) for i in range(0, len(in_queue)): code.writeln('pop_'+in_postfix+'();') # invalid (inconsistent) sdf graph else: print "ERROR: Graph is inconsistent." print " "+actor+" with "+str(len(in_queue))+" in-tokens and "+str(len(out_queue))+" out-tokens." sys.exit(1) code.unindent() code.writeln('}') code.writeln('') return code.get()
def gen_sequence(self, schedule, tid, ivar='i'): """ Generate the code for executing the actor invocations in sequence given a schedule. :param schedule: A sequance of actors :param tid: Index of the processor to execute the sequence on. \ The value is negative if the given schedule is for booting. :param ivar: loop variable for a steady state iteration """ sdfgraph = self.sdfgraph num_processors = self.scheduler.get_numprocessors() prefetcher = self.prefetcher # for booting phase booting_codes={} cur_proc=-1 prev_proc=-1 if self.global_tokens == [] and self.local_tokens == {}: print 'ERROR: Tokens are not generated to run gen_sequence.' sys.exit(1) # when tid is negative, gen sequence for booting phase if tid < 0: prof=profiler() for proc in range(0, num_processors): booting_codes[proc]=writer() booting_codes[proc].indent() booting_codes[proc].writeln('') # when tid is valid, gen sequence for steady state phase else: prof=self.profiler code = writer() code.indent() code.indent() for seq in range(0,len(schedule)): actor = schedule[seq] # code for prefetch prefetch_code = writer() if tid < 0: code=writer() cur_proc=sdfgraph.allocation[actor] # generate firing codes for actor if sdfgraph.is_generic(actor): code.write(prof.gen_actor_profile_start(tid,seq)) actor_function = 'actor_'+actor param_list = sdfgraph.node_param[actor] actor_code = sdfgraph.actor_code[actor] first = True code.indent() code.write('\n//'+actor_function+'_'+str(seq)) code.write('\n{') for i in range(0, len(param_list)): # input params (p_type, p_name, p_value) = param_list[i] actor_code = actor_code.replace(p_name, str(p_value)) for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred,actor) for i in range(0,sdfgraph.consumption[edge]): param = sdfgraph.target_tokens[edge][i] var = self.fifo[edge][0] actor_code = re.sub(r"@"+param+"(?=[^0-9A-Za-z_])", var, actor_code) self.fifo[edge].pop(0) prefetch_code.write(prefetcher.read_prefetch(var, \ sdfgraph.allocation[pred], sdfgraph.allocation[actor])) for i in range(0,len(sdfgraph.peek_tokens[edge])): param = sdfgraph.peek_tokens[edge][i] var = self.fifo[edge][i] actor_code = re.sub(r"@"+param+"(?=[^0-9A-Za-z_])", var, actor_code) prefetch_code.write(prefetcher.read_prefetch(var, \ sdfgraph.allocation[pred], sdfgraph.allocation[actor])) for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor,succ) for i in range(0,sdfgraph.production[edge]): param=sdfgraph.source_tokens[edge][i] # find if the var is local or not var = self.token_prefix+str(self.varctr) self.fifo[edge].append(var) self.varctr = self.varctr+1 actor_code = re.sub(r"@"+param+"(?=[^0-9A-Za-z_])", var, actor_code) prefetch_code.write(prefetcher.write_prefetch(var, \ sdfgraph.allocation[succ], sdfgraph.allocation[actor])) new_code=prefetch_code.get()+code.get() code=writer() code.writeln(new_code) code.write(actor_code) code.write('}') code.unindent() code.write(prof.gen_actor_profile_stop(tid,seq)) code.writeln(prof.gen_actor_profile_record(actor,0,seq,ivar)) else: in_rate = 0 out_rate = 0 multiplicity = 0 for pre in sdfgraph.in_nodes(actor): edge = (pre, actor) in_rate = in_rate + sdfgraph.consumption[edge] for post in sdfgraph.out_nodes(actor): edge = (actor, post) out_rate = out_rate + sdfgraph.production[edge] # round robin if in_rate == out_rate: multiplicity = 1 # duplicate elif in_rate < out_rate and out_rate % in_rate == 0: multiplicity = out_rate/in_rate # invalid (inconsistent) sdf graph else: print "ERROR: Graph is inconsistent." print " "+actor+" with "+str(in_rate)+" in-tokens and "+str(out_rate)+" out-tokens." sys.exit(1) queue = [] for mult in range(0, multiplicity): for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred,actor) for i in range(0,sdfgraph.consumption[edge]): queue.append(self.fifo[edge][0]) if mult == multiplicity-1: self.fifo[edge].pop(0) for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor,succ) for i in range(0,sdfgraph.production[edge]): var = queue.pop(0) self.fifo[edge].append(var) # for boot schedule if tid < 0: booting_codes[cur_proc].writeln(code.get()) #if not cur_proc == prev_proc or seq == len(schedule)-1: if num_processors > 1: for proc in range (0, num_processors): booting_codes[proc].writeln('rts_sync('+str(proc)+');') prev_proc=cur_proc if tid < 0: return booting_codes else: return code.get()
def gen_sequence(self, schedule, tid, ivar='i'): """ Generate the code for executing the actor invocations in sequence given a schedule. :param schedule: A sequance of actors :param tid: Index of the processor to execute the sequence on. \ The value is negative if the given schedule is for booting. :param ivar: loop variable for a steady state iteration """ sdfgraph = self.sdfgraph num_processors = self.scheduler.get_numprocessors() prefetcher = self.prefetcher # for booting phase booting_codes = {} cur_proc = -1 prev_proc = -1 if self.global_tokens == [] and self.local_tokens == {}: print 'ERROR: Tokens are not generated to run gen_sequence.' sys.exit(1) # when tid is negative, gen sequence for booting phase if tid < 0: prof = profiler() for proc in range(0, num_processors): booting_codes[proc] = writer() booting_codes[proc].indent() booting_codes[proc].writeln('') # when tid is valid, gen sequence for steady state phase else: prof = self.profiler code = writer() code.indent() code.indent() for seq in range(0, len(schedule)): actor = schedule[seq] # code for prefetch prefetch_code = writer() if tid < 0: code = writer() cur_proc = sdfgraph.allocation[actor] # generate firing codes for actor if sdfgraph.is_generic(actor): code.write(prof.gen_actor_profile_start(tid, seq)) actor_function = 'actor_' + actor param_list = sdfgraph.node_param[actor] actor_code = sdfgraph.actor_code[actor] first = True code.indent() code.write('\n//' + actor_function + '_' + str(seq)) code.write('\n{') for i in range(0, len(param_list)): # input params (p_type, p_name, p_value) = param_list[i] actor_code = actor_code.replace(p_name, str(p_value)) for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred, actor) for i in range(0, sdfgraph.consumption[edge]): param = sdfgraph.target_tokens[edge][i] var = self.fifo[edge][0] actor_code = re.sub(r"@" + param + "(?=[^0-9A-Za-z_])", var, actor_code) self.fifo[edge].pop(0) prefetch_code.write(prefetcher.read_prefetch(var, \ sdfgraph.allocation[pred], sdfgraph.allocation[actor])) for i in range(0, len(sdfgraph.peek_tokens[edge])): param = sdfgraph.peek_tokens[edge][i] var = self.fifo[edge][i] actor_code = re.sub(r"@" + param + "(?=[^0-9A-Za-z_])", var, actor_code) prefetch_code.write(prefetcher.read_prefetch(var, \ sdfgraph.allocation[pred], sdfgraph.allocation[actor])) for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor, succ) for i in range(0, sdfgraph.production[edge]): param = sdfgraph.source_tokens[edge][i] # find if the var is local or not var = self.token_prefix + str(self.varctr) self.fifo[edge].append(var) self.varctr = self.varctr + 1 actor_code = re.sub(r"@" + param + "(?=[^0-9A-Za-z_])", var, actor_code) prefetch_code.write(prefetcher.write_prefetch(var, \ sdfgraph.allocation[succ], sdfgraph.allocation[actor])) new_code = prefetch_code.get() + code.get() code = writer() code.writeln(new_code) code.write(actor_code) code.write('}') code.unindent() code.write(prof.gen_actor_profile_stop(tid, seq)) code.writeln(prof.gen_actor_profile_record( actor, 0, seq, ivar)) else: in_rate = 0 out_rate = 0 multiplicity = 0 for pre in sdfgraph.in_nodes(actor): edge = (pre, actor) in_rate = in_rate + sdfgraph.consumption[edge] for post in sdfgraph.out_nodes(actor): edge = (actor, post) out_rate = out_rate + sdfgraph.production[edge] # round robin if in_rate == out_rate: multiplicity = 1 # duplicate elif in_rate < out_rate and out_rate % in_rate == 0: multiplicity = out_rate / in_rate # invalid (inconsistent) sdf graph else: print "ERROR: Graph is inconsistent." print " " + actor + " with " + str( in_rate) + " in-tokens and " + str( out_rate) + " out-tokens." sys.exit(1) queue = [] for mult in range(0, multiplicity): for pred in sdfgraph.in_nodes(actor): # incoming nodes edge = (pred, actor) for i in range(0, sdfgraph.consumption[edge]): queue.append(self.fifo[edge][0]) if mult == multiplicity - 1: self.fifo[edge].pop(0) for succ in sdfgraph.out_nodes(actor): # outgoing nodes edge = (actor, succ) for i in range(0, sdfgraph.production[edge]): var = queue.pop(0) self.fifo[edge].append(var) # for boot schedule if tid < 0: booting_codes[cur_proc].writeln(code.get()) #if not cur_proc == prev_proc or seq == len(schedule)-1: if num_processors > 1: for proc in range(0, num_processors): booting_codes[proc].writeln('rts_sync(' + str(proc) + ');') prev_proc = cur_proc if tid < 0: return booting_codes else: return code.get()
def gen_schedule(self): """Generate C code based on the SDF graph with buffers for communication. Communications in between two nodes are done by pushing/popping tokens to/from a buffer which is assigned on each edge of the SDF graph. """ sdfgraph = self.sdfgraph schedule = self.scheduler.get_schedule() prof = self.profiler code = writer() global_block = writer() ############################################################## # generate global functions global_block.writeln(self.gen_state(schedule[0])) # generate fifo related functions global_block.writeln(self.gen_fifo_functions()) # generate actor codes global_block.writeln(self.gen_actors()) ############################################################## # push delay tokens code.indent() for edge in sdfgraph.edges(): (source, target) = edge for i in range(0, sdfgraph.delay[edge]): code.write('push_' + source + '_' + target + '(') code.writeln(sdfgraph.delay_tokens[edge][i] + ');') # prepare for profiling if needed code.writeln(prof.gen_profile_thread_init(0, len(schedule[0]))) code.writeln(prof.gen_profile_open(0)) # start - program profiling code.writeln(prof.gen_program_profile_start()) # loop statement for steady state iteration if self.iterations > 0: code.writeln("int i;") code.writeln('for(i = 0; i < ' + str(self.iterations) + '; i++){') else: code.writeln('for(;;){') code.indent() code.writeln(prof.gen_thread_profile_start(0)) # generate code for the steady state iteration based on schedule code.writeln(self.gen_sequence(schedule[0], 0, LocalVars=False)) # preparation for the next iteration # update pointers (function declaration in gen_fifo_functions()) code.writeln('__RESET_PTR();') code.writeln(prof.gen_thread_profile_stop(0)) code.writeln(prof.gen_thread_profile_record(0, 'i')) code.unindent() code.writeln('}') # stop - program profiling code.writeln(prof.gen_program_profile_stop()) code.writeln(prof.gen_program_profile_record()) # code.writeln(prof.gen_profile_write(0)) # finish profiling code.writeln(prof.gen_profile_close(0)) ############################################################## # wrap up as a block block = writer() block.writeln('') if sdfgraph.name == '': name = 'execute' else: name = sdfgraph.name block.writeln('static inline void ' + name + '(){') # generate state declarations block.writeln(self.gen_init()) block.write(code.get()) block.writeln('\t' + self.gen_close()) block.writeln('}') block.writeln('') return (global_block.get(), block.get())