Beispiel #1
0
   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()
Beispiel #2
0
 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()
Beispiel #4
0
 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()
Beispiel #5
0
 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()
Beispiel #6
0
 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()
Beispiel #7
0
 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()
Beispiel #8
0
 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()
Beispiel #9
0
 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()
Beispiel #10
0
 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()
Beispiel #11
0
    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()
Beispiel #12
0
   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()
Beispiel #13
0
    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()
Beispiel #15
0
    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())
Beispiel #17
0
   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()
Beispiel #18
0
   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()
Beispiel #19
0
    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())